summaryrefslogtreecommitdiff
path: root/chromium/cc
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@theqtcompany.com>2015-10-13 13:24:50 +0200
committerAllan Sandfeld Jensen <allan.jensen@theqtcompany.com>2015-10-14 10:57:25 +0000
commitaf3d4809763ef308f08ced947a73b624729ac7ea (patch)
tree4402b911e30383f6c6dace1e8cf3b8e85355db3a /chromium/cc
parent0e8ff63a407fe323e215bb1a2c423c09a4747c8a (diff)
downloadqtwebengine-chromium-af3d4809763ef308f08ced947a73b624729ac7ea.tar.gz
BASELINE: Update Chromium to 47.0.2526.14
Also adding in sources needed for spellchecking. Change-Id: Idd44170fa1616f26315188970a8d5ba7d472b18a Reviewed-by: Michael BrĂ¼ning <michael.bruning@theqtcompany.com>
Diffstat (limited to 'chromium/cc')
-rw-r--r--chromium/cc/BUILD.gn103
-rw-r--r--chromium/cc/OWNERS11
-rw-r--r--chromium/cc/animation/animation_host.cc96
-rw-r--r--chromium/cc/animation/animation_host.h32
-rw-r--r--chromium/cc/animation/animation_timeline.cc2
-rw-r--r--chromium/cc/animation/element_animations.cc17
-rw-r--r--chromium/cc/animation/element_animations.h2
-rw-r--r--chromium/cc/animation/layer_animation_controller.cc187
-rw-r--r--chromium/cc/animation/layer_animation_controller.h33
-rw-r--r--chromium/cc/animation/layer_animation_controller_unittest.cc467
-rw-r--r--chromium/cc/animation/layer_animation_value_observer.h1
-rw-r--r--chromium/cc/animation/scrollbar_animation_controller_linear_fade.cc3
-rw-r--r--chromium/cc/animation/scrollbar_animation_controller_thinning.cc2
-rw-r--r--chromium/cc/animation/transform_operation.cc8
-rw-r--r--chromium/cc/animation/transform_operations.cc10
-rw-r--r--chromium/cc/animation/transform_operations_unittest.cc57
-rw-r--r--chromium/cc/base/BUILD.gn9
-rw-r--r--chromium/cc/base/float_quad_unittest.cc8
-rw-r--r--chromium/cc/base/histograms.cc39
-rw-r--r--chromium/cc/base/histograms.h63
-rw-r--r--chromium/cc/base/list_container.h323
-rw-r--r--chromium/cc/base/list_container_helper.cc (renamed from chromium/cc/base/list_container.cc)275
-rw-r--r--chromium/cc/base/list_container_helper.h178
-rw-r--r--chromium/cc/base/list_container_unittest.cc154
-rw-r--r--chromium/cc/base/math_util.cc33
-rw-r--r--chromium/cc/base/math_util.h62
-rw-r--r--chromium/cc/base/math_util_unittest.cc147
-rw-r--r--chromium/cc/base/random_access_list_container.h94
-rw-r--r--chromium/cc/base/random_access_list_container_unittest.cc107
-rw-r--r--chromium/cc/base/rtree.cc111
-rw-r--r--chromium/cc/base/rtree.h118
-rw-r--r--chromium/cc/base/rtree_unittest.cc68
-rw-r--r--chromium/cc/base/sidecar_list_container.h97
-rw-r--r--chromium/cc/base/sidecar_list_container_unittest.cc198
-rw-r--r--chromium/cc/base/switches.cc12
-rw-r--r--chromium/cc/base/switches.h3
-rw-r--r--chromium/cc/blink/BUILD.gn2
-rw-r--r--chromium/cc/blink/cc_blink.gyp2
-rw-r--r--chromium/cc/blink/web_animation_impl.h36
-rw-r--r--chromium/cc/blink/web_compositor_animation_player_impl.h18
-rw-r--r--chromium/cc/blink/web_compositor_animation_timeline_impl.h10
-rw-r--r--chromium/cc/blink/web_compositor_support_impl.cc10
-rw-r--r--chromium/cc/blink/web_compositor_support_impl.h51
-rw-r--r--chromium/cc/blink/web_content_layer_impl.cc8
-rw-r--r--chromium/cc/blink/web_content_layer_impl.h8
-rw-r--r--chromium/cc/blink/web_display_item_list_impl.cc3
-rw-r--r--chromium/cc/blink/web_display_item_list_impl.h48
-rw-r--r--chromium/cc/blink/web_external_bitmap_impl.cc7
-rw-r--r--chromium/cc/blink/web_external_texture_layer_impl.cc4
-rw-r--r--chromium/cc/blink/web_external_texture_layer_impl.h15
-rw-r--r--chromium/cc/blink/web_filter_animation_curve_impl.h40
-rw-r--r--chromium/cc/blink/web_filter_operations_impl.h40
-rw-r--r--chromium/cc/blink/web_float_animation_curve_impl.h44
-rw-r--r--chromium/cc/blink/web_image_layer_impl.cc9
-rw-r--r--chromium/cc/blink/web_image_layer_impl.h9
-rw-r--r--chromium/cc/blink/web_layer_impl.cc13
-rw-r--r--chromium/cc/blink/web_layer_impl.h176
-rw-r--r--chromium/cc/blink/web_layer_impl_fixed_bounds.h2
-rw-r--r--chromium/cc/blink/web_layer_impl_fixed_bounds_unittest.cc14
-rw-r--r--chromium/cc/blink/web_nine_patch_layer_impl.cc46
-rw-r--r--chromium/cc/blink/web_nine_patch_layer_impl.h37
-rw-r--r--chromium/cc/blink/web_scroll_offset_animation_curve_impl.h11
-rw-r--r--chromium/cc/blink/web_scrollbar_layer_impl.h8
-rw-r--r--chromium/cc/blink/web_transform_animation_curve_impl.h42
-rw-r--r--chromium/cc/blink/web_transform_operations_impl.h20
-rw-r--r--chromium/cc/cc.gyp56
-rw-r--r--chromium/cc/cc_tests.gyp25
-rw-r--r--chromium/cc/cc_unittests.isolate3
-rw-r--r--chromium/cc/debug/devtools_instrumentation.h5
-rw-r--r--chromium/cc/debug/layer_tree_debug_state.cc10
-rw-r--r--chromium/cc/debug/layer_tree_debug_state.h1
-rw-r--r--chromium/cc/debug/micro_benchmark_controller.cc3
-rw-r--r--chromium/cc/debug/paint_time_counter.cc43
-rw-r--r--chromium/cc/debug/paint_time_counter.h45
-rw-r--r--chromium/cc/debug/picture_record_benchmark.cc119
-rw-r--r--chromium/cc/debug/picture_record_benchmark.h37
-rw-r--r--chromium/cc/debug/rasterize_and_record_benchmark.cc73
-rw-r--r--chromium/cc/debug/rasterize_and_record_benchmark.h5
-rw-r--r--chromium/cc/debug/rasterize_and_record_benchmark_impl.cc8
-rw-r--r--chromium/cc/debug/traced_picture.cc56
-rw-r--r--chromium/cc/debug/traced_picture.h42
-rw-r--r--chromium/cc/input/input_handler.h34
-rw-r--r--chromium/cc/input/layer_scroll_offset_delegate.h68
-rw-r--r--chromium/cc/input/page_scale_animation.cc2
-rw-r--r--chromium/cc/input/page_scale_animation.h2
-rw-r--r--chromium/cc/input/scroll_state.cc46
-rw-r--r--chromium/cc/input/scroll_state.h108
-rw-r--r--chromium/cc/input/scroll_state_unittest.cc79
-rw-r--r--chromium/cc/layers/content_layer_client.h6
-rw-r--r--chromium/cc/layers/delegated_frame_provider.cc7
-rw-r--r--chromium/cc/layers/delegated_frame_provider.h8
-rw-r--r--chromium/cc/layers/delegated_frame_provider_unittest.cc32
-rw-r--r--chromium/cc/layers/delegated_renderer_layer.cc2
-rw-r--r--chromium/cc/layers/delegated_renderer_layer.h2
-rw-r--r--chromium/cc/layers/delegated_renderer_layer_impl.cc9
-rw-r--r--chromium/cc/layers/delegated_renderer_layer_impl.h2
-rw-r--r--chromium/cc/layers/delegated_renderer_layer_impl_unittest.cc94
-rw-r--r--chromium/cc/layers/draw_properties.cc23
-rw-r--r--chromium/cc/layers/draw_properties.h51
-rw-r--r--chromium/cc/layers/heads_up_display_layer_impl.cc124
-rw-r--r--chromium/cc/layers/heads_up_display_layer_impl.h4
-rw-r--r--chromium/cc/layers/heads_up_display_layer_impl_unittest.cc3
-rw-r--r--chromium/cc/layers/io_surface_layer_impl.cc3
-rw-r--r--chromium/cc/layers/layer.cc236
-rw-r--r--chromium/cc/layers/layer.h171
-rw-r--r--chromium/cc/layers/layer_impl.cc277
-rw-r--r--chromium/cc/layers/layer_impl.h118
-rw-r--r--chromium/cc/layers/layer_impl_unittest.cc10
-rw-r--r--chromium/cc/layers/layer_lists.cc67
-rw-r--r--chromium/cc/layers/layer_lists.h28
-rw-r--r--chromium/cc/layers/layer_position_constraint_unittest.cc5
-rw-r--r--chromium/cc/layers/layer_unittest.cc4
-rw-r--r--chromium/cc/layers/nine_patch_layer_impl_unittest.cc5
-rw-r--r--chromium/cc/layers/painted_scrollbar_layer.cc10
-rw-r--r--chromium/cc/layers/picture_image_layer.cc32
-rw-r--r--chromium/cc/layers/picture_image_layer.h9
-rw-r--r--chromium/cc/layers/picture_image_layer_impl_unittest.cc8
-rw-r--r--chromium/cc/layers/picture_image_layer_unittest.cc19
-rw-r--r--chromium/cc/layers/picture_layer.cc52
-rw-r--r--chromium/cc/layers/picture_layer_impl.cc135
-rw-r--r--chromium/cc/layers/picture_layer_impl.h5
-rw-r--r--chromium/cc/layers/picture_layer_impl_perftest.cc110
-rw-r--r--chromium/cc/layers/picture_layer_impl_unittest.cc1246
-rw-r--r--chromium/cc/layers/picture_layer_unittest.cc49
-rw-r--r--chromium/cc/layers/render_surface.cc48
-rw-r--r--chromium/cc/layers/render_surface.h147
-rw-r--r--chromium/cc/layers/render_surface_draw_properties.cc14
-rw-r--r--chromium/cc/layers/render_surface_draw_properties.h45
-rw-r--r--chromium/cc/layers/render_surface_impl.cc54
-rw-r--r--chromium/cc/layers/render_surface_impl.h41
-rw-r--r--chromium/cc/layers/scrollbar_layer_impl_base.cc5
-rw-r--r--chromium/cc/layers/scrollbar_layer_impl_base.h1
-rw-r--r--chromium/cc/layers/scrollbar_layer_unittest.cc53
-rw-r--r--chromium/cc/layers/solid_color_layer_impl_unittest.cc7
-rw-r--r--chromium/cc/layers/solid_color_scrollbar_layer_impl.cc4
-rw-r--r--chromium/cc/layers/solid_color_scrollbar_layer_impl.h2
-rw-r--r--chromium/cc/layers/surface_layer_impl.cc93
-rw-r--r--chromium/cc/layers/surface_layer_impl.h1
-rw-r--r--chromium/cc/layers/surface_layer_unittest.cc78
-rw-r--r--chromium/cc/layers/texture_layer.cc17
-rw-r--r--chromium/cc/layers/texture_layer.h6
-rw-r--r--chromium/cc/layers/texture_layer_unittest.cc88
-rw-r--r--chromium/cc/layers/ui_resource_layer_impl_unittest.cc9
-rw-r--r--chromium/cc/layers/video_frame_provider_client_impl_unittest.cc2
-rw-r--r--chromium/cc/layers/video_layer_impl.cc10
-rw-r--r--chromium/cc/layers/video_layer_impl_unittest.cc49
-rw-r--r--chromium/cc/layers/viewport.cc62
-rw-r--r--chromium/cc/layers/viewport.h7
-rw-r--r--chromium/cc/output/compositor_frame.cc1
-rw-r--r--chromium/cc/output/compositor_frame.h5
-rw-r--r--chromium/cc/output/compositor_frame_ack.cc3
-rw-r--r--chromium/cc/output/compositor_frame_ack.h1
-rw-r--r--chromium/cc/output/compositor_frame_metadata.cc4
-rw-r--r--chromium/cc/output/compositor_frame_metadata.h6
-rw-r--r--chromium/cc/output/context_provider.h32
-rw-r--r--chromium/cc/output/delegating_renderer_unittest.cc25
-rw-r--r--chromium/cc/output/direct_renderer.cc19
-rw-r--r--chromium/cc/output/filter_operations.cc46
-rw-r--r--chromium/cc/output/filter_operations_unittest.cc21
-rw-r--r--chromium/cc/output/gl_renderer.cc218
-rw-r--r--chromium/cc/output/gl_renderer.h15
-rw-r--r--chromium/cc/output/gl_renderer_unittest.cc171
-rw-r--r--chromium/cc/output/latency_info_swap_promise.cc10
-rw-r--r--chromium/cc/output/output_surface.cc200
-rw-r--r--chromium/cc/output/output_surface.h32
-rw-r--r--chromium/cc/output/overlay_candidate.cc161
-rw-r--r--chromium/cc/output/overlay_candidate.h41
-rw-r--r--chromium/cc/output/overlay_candidate_validator.h4
-rw-r--r--chromium/cc/output/overlay_processor.cc15
-rw-r--r--chromium/cc/output/overlay_processor.h3
-rw-r--r--chromium/cc/output/overlay_strategy_all_or_nothing.cc44
-rw-r--r--chromium/cc/output/overlay_strategy_all_or_nothing.h35
-rw-r--r--chromium/cc/output/overlay_strategy_common.cc140
-rw-r--r--chromium/cc/output/overlay_strategy_common.h54
-rw-r--r--chromium/cc/output/overlay_strategy_sandwich.cc163
-rw-r--r--chromium/cc/output/overlay_strategy_sandwich.h34
-rw-r--r--chromium/cc/output/overlay_strategy_single_on_top.cc53
-rw-r--r--chromium/cc/output/overlay_strategy_single_on_top.h19
-rw-r--r--chromium/cc/output/overlay_strategy_underlay.cc39
-rw-r--r--chromium/cc/output/overlay_strategy_underlay.h18
-rw-r--r--chromium/cc/output/overlay_unittest.cc795
-rw-r--r--chromium/cc/output/renderer.h2
-rw-r--r--chromium/cc/output/renderer_pixeltest.cc385
-rw-r--r--chromium/cc/output/renderer_settings.cc6
-rw-r--r--chromium/cc/output/renderer_settings.h3
-rw-r--r--chromium/cc/output/shader.cc62
-rw-r--r--chromium/cc/output/shader.h27
-rw-r--r--chromium/cc/output/software_frame_data.cc13
-rw-r--r--chromium/cc/output/software_frame_data.h28
-rw-r--r--chromium/cc/output/software_output_device.cc15
-rw-r--r--chromium/cc/output/software_output_device.h10
-rw-r--r--chromium/cc/output/software_renderer.cc222
-rw-r--r--chromium/cc/output/software_renderer.h15
-rw-r--r--chromium/cc/output/software_renderer_unittest.cc51
-rw-r--r--chromium/cc/playback/clip_display_item.cc10
-rw-r--r--chromium/cc/playback/clip_display_item.h4
-rw-r--r--chromium/cc/playback/clip_path_display_item.cc10
-rw-r--r--chromium/cc/playback/clip_path_display_item.h4
-rw-r--r--chromium/cc/playback/compositing_display_item.cc12
-rw-r--r--chromium/cc/playback/compositing_display_item.h4
-rw-r--r--chromium/cc/playback/discardable_image_map.cc136
-rw-r--r--chromium/cc/playback/discardable_image_map.h67
-rw-r--r--chromium/cc/playback/discardable_image_map_unittest.cc316
-rw-r--r--chromium/cc/playback/display_item.h3
-rw-r--r--chromium/cc/playback/display_item_list.cc111
-rw-r--r--chromium/cc/playback/display_item_list.h39
-rw-r--r--chromium/cc/playback/display_item_list_bounds_calculator.cc61
-rw-r--r--chromium/cc/playback/display_item_list_bounds_calculator.h39
-rw-r--r--chromium/cc/playback/display_item_list_settings.cc5
-rw-r--r--chromium/cc/playback/display_item_list_settings.h4
-rw-r--r--chromium/cc/playback/display_item_list_unittest.cc95
-rw-r--r--chromium/cc/playback/display_list_raster_source.cc60
-rw-r--r--chromium/cc/playback/display_list_raster_source.h11
-rw-r--r--chromium/cc/playback/display_list_raster_source_unittest.cc134
-rw-r--r--chromium/cc/playback/display_list_recording_source.cc75
-rw-r--r--chromium/cc/playback/display_list_recording_source.h12
-rw-r--r--chromium/cc/playback/display_list_recording_source_unittest.cc489
-rw-r--r--chromium/cc/playback/drawing_display_item.cc5
-rw-r--r--chromium/cc/playback/drawing_display_item.h2
-rw-r--r--chromium/cc/playback/filter_display_item.cc17
-rw-r--r--chromium/cc/playback/filter_display_item.h4
-rw-r--r--chromium/cc/playback/float_clip_display_item.cc10
-rw-r--r--chromium/cc/playback/float_clip_display_item.h4
-rw-r--r--chromium/cc/playback/picture.cc338
-rw-r--r--chromium/cc/playback/picture.h119
-rw-r--r--chromium/cc/playback/picture_pile.cc699
-rw-r--r--chromium/cc/playback/picture_pile.h107
-rw-r--r--chromium/cc/playback/picture_pile_impl.cc465
-rw-r--r--chromium/cc/playback/picture_pile_impl.h160
-rw-r--r--chromium/cc/playback/picture_pile_impl_perftest.cc84
-rw-r--r--chromium/cc/playback/picture_pile_impl_unittest.cc550
-rw-r--r--chromium/cc/playback/picture_pile_unittest.cc1345
-rw-r--r--chromium/cc/playback/picture_unittest.cc181
-rw-r--r--chromium/cc/playback/pixel_ref_map.cc174
-rw-r--r--chromium/cc/playback/pixel_ref_map.h94
-rw-r--r--chromium/cc/playback/pixel_ref_map_unittest.cc292
-rw-r--r--chromium/cc/playback/position_image.h33
-rw-r--r--chromium/cc/playback/raster_source.h24
-rw-r--r--chromium/cc/playback/raster_source_helper.cc2
-rw-r--r--chromium/cc/playback/recording_source.h6
-rw-r--r--chromium/cc/playback/recording_source_unittest.cc471
-rw-r--r--chromium/cc/playback/transform_display_item.cc13
-rw-r--r--chromium/cc/playback/transform_display_item.h4
-rw-r--r--chromium/cc/quads/checkerboard_draw_quad.cc54
-rw-r--r--chromium/cc/quads/checkerboard_draw_quad.h44
-rw-r--r--chromium/cc/quads/content_draw_quad_base.h6
-rw-r--r--chromium/cc/quads/draw_quad.cc15
-rw-r--r--chromium/cc/quads/draw_quad.h1
-rw-r--r--chromium/cc/quads/draw_quad_unittest.cc64
-rw-r--r--chromium/cc/quads/io_surface_draw_quad.cc11
-rw-r--r--chromium/cc/quads/io_surface_draw_quad.h7
-rw-r--r--chromium/cc/quads/largest_draw_quad.cc4
-rw-r--r--chromium/cc/quads/render_pass.cc8
-rw-r--r--chromium/cc/quads/render_pass_draw_quad.cc4
-rw-r--r--chromium/cc/quads/render_pass_id.h2
-rw-r--r--chromium/cc/quads/render_pass_unittest.cc87
-rw-r--r--chromium/cc/quads/yuv_video_draw_quad.h2
-rw-r--r--chromium/cc/raster/bitmap_tile_task_worker_pool.cc17
-rw-r--r--chromium/cc/raster/bitmap_tile_task_worker_pool.h4
-rw-r--r--chromium/cc/raster/gpu_tile_task_worker_pool.cc34
-rw-r--r--chromium/cc/raster/gpu_tile_task_worker_pool.h4
-rw-r--r--chromium/cc/raster/one_copy_tile_task_worker_pool.cc846
-rw-r--r--chromium/cc/raster/one_copy_tile_task_worker_pool.h143
-rw-r--r--chromium/cc/raster/pixel_buffer_tile_task_worker_pool.cc754
-rw-r--r--chromium/cc/raster/pixel_buffer_tile_task_worker_pool.h146
-rw-r--r--chromium/cc/raster/raster_buffer.h3
-rw-r--r--chromium/cc/raster/scoped_gpu_raster.cc4
-rw-r--r--chromium/cc/raster/task_graph_runner.cc55
-rw-r--r--chromium/cc/raster/task_graph_runner.h3
-rw-r--r--chromium/cc/raster/tile_task_runner.cc20
-rw-r--r--chromium/cc/raster/tile_task_runner.h20
-rw-r--r--chromium/cc/raster/tile_task_worker_pool.cc54
-rw-r--r--chromium/cc/raster/tile_task_worker_pool.h3
-rw-r--r--chromium/cc/raster/tile_task_worker_pool_perftest.cc46
-rw-r--r--chromium/cc/raster/tile_task_worker_pool_unittest.cc94
-rw-r--r--chromium/cc/raster/zero_copy_tile_task_worker_pool.cc36
-rw-r--r--chromium/cc/raster/zero_copy_tile_task_worker_pool.h12
-rw-r--r--chromium/cc/resources/resource.h33
-rw-r--r--chromium/cc/resources/resource_format.cc81
-rw-r--r--chromium/cc/resources/resource_format.h13
-rw-r--r--chromium/cc/resources/resource_pool.cc291
-rw-r--r--chromium/cc/resources/resource_pool.h134
-rw-r--r--chromium/cc/resources/resource_pool_unittest.cc183
-rw-r--r--chromium/cc/resources/resource_provider.cc478
-rw-r--r--chromium/cc/resources/resource_provider.h103
-rw-r--r--chromium/cc/resources/resource_provider_unittest.cc305
-rw-r--r--chromium/cc/resources/resource_util.h222
-rw-r--r--chromium/cc/resources/resource_util_unittest.cc167
-rw-r--r--chromium/cc/resources/returned_resource.h19
-rw-r--r--chromium/cc/resources/scoped_resource_unittest.cc6
-rw-r--r--chromium/cc/resources/shared_bitmap.cc9
-rw-r--r--chromium/cc/resources/shared_bitmap.h4
-rw-r--r--chromium/cc/resources/video_resource_updater.cc137
-rw-r--r--chromium/cc/resources/video_resource_updater_unittest.cc25
-rw-r--r--chromium/cc/scheduler/begin_frame_source_unittest.cc1
-rw-r--r--chromium/cc/scheduler/compositor_timing_history.cc283
-rw-r--r--chromium/cc/scheduler/compositor_timing_history.h16
-rw-r--r--chromium/cc/scheduler/compositor_timing_history_unittest.cc2
-rw-r--r--chromium/cc/scheduler/scheduler.cc58
-rw-r--r--chromium/cc/scheduler/scheduler.h8
-rw-r--r--chromium/cc/scheduler/scheduler_state_machine.cc300
-rw-r--r--chromium/cc/scheduler/scheduler_state_machine.h72
-rw-r--r--chromium/cc/scheduler/scheduler_state_machine_unittest.cc507
-rw-r--r--chromium/cc/scheduler/scheduler_unittest.cc292
-rw-r--r--chromium/cc/surfaces/BUILD.gn4
-rw-r--r--chromium/cc/surfaces/display.cc71
-rw-r--r--chromium/cc/surfaces/display_scheduler.cc42
-rw-r--r--chromium/cc/surfaces/display_scheduler.h5
-rw-r--r--chromium/cc/surfaces/display_scheduler_unittest.cc104
-rw-r--r--chromium/cc/surfaces/display_unittest.cc136
-rw-r--r--chromium/cc/surfaces/onscreen_display_client.cc4
-rw-r--r--chromium/cc/surfaces/onscreen_display_client.h2
-rw-r--r--chromium/cc/surfaces/surface.h2
-rw-r--r--chromium/cc/surfaces/surface_aggregator.cc130
-rw-r--r--chromium/cc/surfaces/surface_aggregator.h22
-rw-r--r--chromium/cc/surfaces/surface_aggregator_perftest.cc60
-rw-r--r--chromium/cc/surfaces/surface_aggregator_test_helpers.cc19
-rw-r--r--chromium/cc/surfaces/surface_aggregator_unittest.cc376
-rw-r--r--chromium/cc/surfaces/surface_display_output_surface.cc10
-rw-r--r--chromium/cc/surfaces/surface_display_output_surface.h3
-rw-r--r--chromium/cc/surfaces/surface_display_output_surface_unittest.cc3
-rw-r--r--chromium/cc/surfaces/surface_factory.cc12
-rw-r--r--chromium/cc/surfaces/surface_factory.h8
-rw-r--r--chromium/cc/surfaces/surface_factory_unittest.cc69
-rw-r--r--chromium/cc/surfaces/surface_hittest.cc175
-rw-r--r--chromium/cc/surfaces/surface_hittest.h60
-rw-r--r--chromium/cc/surfaces/surface_hittest_unittest.cc487
-rw-r--r--chromium/cc/surfaces/surfaces_pixeltest.cc30
-rw-r--r--chromium/cc/tiles/image_decode_controller.cc120
-rw-r--r--chromium/cc/tiles/image_decode_controller.h53
-rw-r--r--chromium/cc/tiles/picture_layer_tiling.cc306
-rw-r--r--chromium/cc/tiles/picture_layer_tiling.h44
-rw-r--r--chromium/cc/tiles/picture_layer_tiling_perftest.cc10
-rw-r--r--chromium/cc/tiles/picture_layer_tiling_set.cc39
-rw-r--r--chromium/cc/tiles/picture_layer_tiling_set.h7
-rw-r--r--chromium/cc/tiles/picture_layer_tiling_set_unittest.cc93
-rw-r--r--chromium/cc/tiles/picture_layer_tiling_unittest.cc483
-rw-r--r--chromium/cc/tiles/prioritized_tile.cc1
-rw-r--r--chromium/cc/tiles/raster_tile_priority_queue_all.cc13
-rw-r--r--chromium/cc/tiles/tile.cc28
-rw-r--r--chromium/cc/tiles/tile.h58
-rw-r--r--chromium/cc/tiles/tile_draw_info.cc4
-rw-r--r--chromium/cc/tiles/tile_draw_info.h5
-rw-r--r--chromium/cc/tiles/tile_manager.cc217
-rw-r--r--chromium/cc/tiles/tile_manager.h30
-rw-r--r--chromium/cc/tiles/tile_manager_perftest.cc53
-rw-r--r--chromium/cc/tiles/tile_manager_unittest.cc388
-rw-r--r--chromium/cc/trees/channel_impl.h27
-rw-r--r--chromium/cc/trees/channel_main.h33
-rw-r--r--chromium/cc/trees/damage_tracker.cc28
-rw-r--r--chromium/cc/trees/damage_tracker_unittest.cc35
-rw-r--r--chromium/cc/trees/draw_property_utils.cc554
-rw-r--r--chromium/cc/trees/draw_property_utils.h31
-rw-r--r--chromium/cc/trees/latency_info_swap_promise_monitor.cc13
-rw-r--r--chromium/cc/trees/latency_info_swap_promise_monitor.h2
-rw-r--r--chromium/cc/trees/layer_tree_host.cc188
-rw-r--r--chromium/cc/trees/layer_tree_host.h38
-rw-r--r--chromium/cc/trees/layer_tree_host_client.h6
-rw-r--r--chromium/cc/trees/layer_tree_host_common.cc1262
-rw-r--r--chromium/cc/trees/layer_tree_host_common.h193
-rw-r--r--chromium/cc/trees/layer_tree_host_common_perftest.cc4
-rw-r--r--chromium/cc/trees/layer_tree_host_common_unittest.cc4575
-rw-r--r--chromium/cc/trees/layer_tree_host_impl.cc924
-rw-r--r--chromium/cc/trees/layer_tree_host_impl.h63
-rw-r--r--chromium/cc/trees/layer_tree_host_impl_unittest.cc1630
-rw-r--r--chromium/cc/trees/layer_tree_host_perftest.cc3
-rw-r--r--chromium/cc/trees/layer_tree_host_pixeltest_blending.cc75
-rw-r--r--chromium/cc/trees/layer_tree_host_pixeltest_filters.cc151
-rw-r--r--chromium/cc/trees/layer_tree_host_pixeltest_masks.cc136
-rw-r--r--chromium/cc/trees/layer_tree_host_pixeltest_synchronous.cc5
-rw-r--r--chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc18
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest.cc830
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest_animation.cc357
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest_animation_timelines.cc183
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest_context.cc148
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest_damage.cc52
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest_delegated.cc39
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest_picture.cc76
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest_proxy.cc183
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest_scroll.cc384
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest_video.cc8
-rw-r--r--chromium/cc/trees/layer_tree_impl.cc386
-rw-r--r--chromium/cc/trees/layer_tree_impl.h77
-rw-r--r--chromium/cc/trees/layer_tree_impl_unittest.cc137
-rw-r--r--chromium/cc/trees/layer_tree_settings.cc25
-rw-r--r--chromium/cc/trees/layer_tree_settings.h19
-rw-r--r--chromium/cc/trees/mutator_host_client.h5
-rw-r--r--chromium/cc/trees/occlusion.cc5
-rw-r--r--chromium/cc/trees/occlusion_tracker.cc1
-rw-r--r--chromium/cc/trees/occlusion_tracker_perftest.cc6
-rw-r--r--chromium/cc/trees/occlusion_tracker_unittest.cc2
-rw-r--r--chromium/cc/trees/property_tree.cc164
-rw-r--r--chromium/cc/trees/property_tree.h56
-rw-r--r--chromium/cc/trees/property_tree_builder.cc222
-rw-r--r--chromium/cc/trees/property_tree_builder.h2
-rw-r--r--chromium/cc/trees/property_tree_unittest.cc6
-rw-r--r--chromium/cc/trees/proxy.h10
-rw-r--r--chromium/cc/trees/proxy_impl.h34
-rw-r--r--chromium/cc/trees/proxy_main.h40
-rw-r--r--chromium/cc/trees/single_thread_proxy.cc77
-rw-r--r--chromium/cc/trees/single_thread_proxy.h7
-rw-r--r--chromium/cc/trees/thread_proxy.cc248
-rw-r--r--chromium/cc/trees/thread_proxy.h75
-rw-r--r--chromium/cc/trees/threaded_channel.cc60
-rw-r--r--chromium/cc/trees/threaded_channel.h106
405 files changed, 21521 insertions, 21357 deletions
diff --git a/chromium/cc/BUILD.gn b/chromium/cc/BUILD.gn
index 5cd45c2749c..854111b811e 100644
--- a/chromium/cc/BUILD.gn
+++ b/chromium/cc/BUILD.gn
@@ -75,12 +75,8 @@ component("cc") {
"debug/micro_benchmark_controller_impl.h",
"debug/micro_benchmark_impl.cc",
"debug/micro_benchmark_impl.h",
- "debug/paint_time_counter.cc",
- "debug/paint_time_counter.h",
"debug/picture_debug_util.cc",
"debug/picture_debug_util.h",
- "debug/picture_record_benchmark.cc",
- "debug/picture_record_benchmark.h",
"debug/rasterize_and_record_benchmark.cc",
"debug/rasterize_and_record_benchmark.h",
"debug/rasterize_and_record_benchmark_impl.cc",
@@ -92,8 +88,6 @@ component("cc") {
"debug/ring_buffer.h",
"debug/traced_display_item_list.cc",
"debug/traced_display_item_list.h",
- "debug/traced_picture.cc",
- "debug/traced_picture.h",
"debug/traced_value.cc",
"debug/traced_value.h",
"debug/unittest_only_benchmark.cc",
@@ -108,6 +102,8 @@ component("cc") {
"input/page_scale_animation.h",
"input/scroll_elasticity_helper.cc",
"input/scroll_elasticity_helper.h",
+ "input/scroll_state.cc",
+ "input/scroll_state.h",
"input/selection.h",
"input/selection_bound_type.h",
"input/top_controls_manager.cc",
@@ -123,6 +119,7 @@ component("cc") {
"layers/delegated_renderer_layer.h",
"layers/delegated_renderer_layer_impl.cc",
"layers/delegated_renderer_layer_impl.h",
+ "layers/draw_properties.cc",
"layers/draw_properties.h",
"layers/heads_up_display_layer.cc",
"layers/heads_up_display_layer.h",
@@ -138,7 +135,6 @@ component("cc") {
"layers/layer_impl.cc",
"layers/layer_impl.h",
"layers/layer_iterator.h",
- "layers/layer_lists.cc",
"layers/layer_lists.h",
"layers/layer_position_constraint.cc",
"layers/layer_position_constraint.h",
@@ -162,8 +158,8 @@ component("cc") {
"layers/picture_layer_impl.cc",
"layers/picture_layer_impl.h",
"layers/render_pass_sink.h",
- "layers/render_surface.cc",
- "layers/render_surface.h",
+ "layers/render_surface_draw_properties.cc",
+ "layers/render_surface_draw_properties.h",
"layers/render_surface_impl.cc",
"layers/render_surface_impl.h",
"layers/scrollbar_layer_impl_base.cc",
@@ -251,8 +247,12 @@ component("cc") {
"output/overlay_candidate_validator.h",
"output/overlay_processor.cc",
"output/overlay_processor.h",
+ "output/overlay_strategy_all_or_nothing.cc",
+ "output/overlay_strategy_all_or_nothing.h",
"output/overlay_strategy_common.cc",
"output/overlay_strategy_common.h",
+ "output/overlay_strategy_sandwich.cc",
+ "output/overlay_strategy_sandwich.h",
"output/overlay_strategy_single_on_top.cc",
"output/overlay_strategy_single_on_top.h",
"output/overlay_strategy_underlay.cc",
@@ -269,8 +269,6 @@ component("cc") {
"output/renderer_settings.h",
"output/shader.cc",
"output/shader.h",
- "output/software_frame_data.cc",
- "output/software_frame_data.h",
"output/software_output_device.cc",
"output/software_output_device.h",
"output/software_renderer.cc",
@@ -288,10 +286,14 @@ component("cc") {
"playback/clip_path_display_item.h",
"playback/compositing_display_item.cc",
"playback/compositing_display_item.h",
+ "playback/discardable_image_map.cc",
+ "playback/discardable_image_map.h",
"playback/display_item.cc",
"playback/display_item.h",
"playback/display_item_list.cc",
"playback/display_item_list.h",
+ "playback/display_item_list_bounds_calculator.cc",
+ "playback/display_item_list_bounds_calculator.h",
"playback/display_item_list_settings.cc",
"playback/display_item_list_settings.h",
"playback/display_list_raster_source.cc",
@@ -306,21 +308,12 @@ component("cc") {
"playback/float_clip_display_item.h",
"playback/largest_display_item.cc",
"playback/largest_display_item.h",
- "playback/picture.cc",
- "playback/picture.h",
- "playback/picture_pile.cc",
- "playback/picture_pile.h",
- "playback/picture_pile_impl.cc",
- "playback/picture_pile_impl.h",
- "playback/pixel_ref_map.cc",
- "playback/pixel_ref_map.h",
+ "playback/position_image.h",
"playback/raster_source.h",
"playback/raster_source_helper.cc",
"playback/raster_source_helper.h",
"playback/transform_display_item.cc",
"playback/transform_display_item.h",
- "quads/checkerboard_draw_quad.cc",
- "quads/checkerboard_draw_quad.h",
"quads/content_draw_quad_base.cc",
"quads/content_draw_quad_base.h",
"quads/debug_border_draw_quad.cc",
@@ -363,8 +356,6 @@ component("cc") {
"raster/gpu_tile_task_worker_pool.h",
"raster/one_copy_tile_task_worker_pool.cc",
"raster/one_copy_tile_task_worker_pool.h",
- "raster/pixel_buffer_tile_task_worker_pool.cc",
- "raster/pixel_buffer_tile_task_worker_pool.h",
"raster/raster_buffer.cc",
"raster/raster_buffer.h",
"raster/scoped_gpu_raster.cc",
@@ -392,6 +383,7 @@ component("cc") {
"resources/resource_pool.h",
"resources/resource_provider.cc",
"resources/resource_provider.h",
+ "resources/resource_util.h",
"resources/returned_resource.h",
"resources/scoped_resource.cc",
"resources/scoped_resource.h",
@@ -434,6 +426,8 @@ component("cc") {
"scheduler/video_frame_controller.h",
"tiles/eviction_tile_priority_queue.cc",
"tiles/eviction_tile_priority_queue.h",
+ "tiles/image_decode_controller.cc",
+ "tiles/image_decode_controller.h",
"tiles/picture_layer_tiling.cc",
"tiles/picture_layer_tiling.h",
"tiles/picture_layer_tiling_set.cc",
@@ -462,6 +456,8 @@ component("cc") {
"tiles/tiling_set_raster_queue_required.h",
"trees/blocking_task_runner.cc",
"trees/blocking_task_runner.h",
+ "trees/channel_impl.h",
+ "trees/channel_main.h",
"trees/damage_tracker.cc",
"trees/damage_tracker.h",
"trees/draw_property_utils.cc",
@@ -491,6 +487,8 @@ component("cc") {
"trees/property_tree_builder.h",
"trees/proxy.cc",
"trees/proxy.h",
+ "trees/proxy_impl.h",
+ "trees/proxy_main.h",
"trees/scoped_abort_remaining_swap_promises.h",
"trees/single_thread_proxy.cc",
"trees/single_thread_proxy.h",
@@ -498,6 +496,8 @@ component("cc") {
"trees/swap_promise_monitor.h",
"trees/thread_proxy.cc",
"trees/thread_proxy.h",
+ "trees/threaded_channel.cc",
+ "trees/threaded_channel.h",
"trees/tree_synchronizer.cc",
"trees/tree_synchronizer.h",
]
@@ -509,6 +509,8 @@ component("cc") {
]
}
+ configs += [ "//build/config:precompiled_headers" ]
+
public_deps = [
"//cc/base",
"//skia",
@@ -523,12 +525,13 @@ component("cc") {
"//ui/events:events_base",
"//ui/gfx",
"//ui/gfx/geometry",
+ "//ui/gl",
]
defines = [ "CC_IMPLEMENTATION=1" ]
if (!is_debug && (is_win || is_android)) {
- configs -= [ "//build/config/compiler:optimize" ]
+ configs -= [ "//build/config/compiler:default_optimization" ]
configs += [ "//build/config/compiler:optimize_max" ]
}
}
@@ -550,6 +553,9 @@ source_set("test_support") {
"test/fake_delegated_renderer_layer.h",
"test/fake_delegated_renderer_layer_impl.cc",
"test/fake_delegated_renderer_layer_impl.h",
+ "test/fake_display_list_raster_source.cc",
+ "test/fake_display_list_raster_source.h",
+ "test/fake_display_list_recording_source.cc",
"test/fake_display_list_recording_source.h",
"test/fake_external_begin_frame_source.cc",
"test/fake_external_begin_frame_source.h",
@@ -574,10 +580,6 @@ source_set("test_support") {
"test/fake_picture_layer_impl.h",
"test/fake_picture_layer_tiling_client.cc",
"test/fake_picture_layer_tiling_client.h",
- "test/fake_picture_pile.cc",
- "test/fake_picture_pile.h",
- "test/fake_picture_pile_impl.cc",
- "test/fake_picture_pile_impl.h",
"test/fake_proxy.cc",
"test/fake_proxy.h",
"test/fake_renderer_client.cc",
@@ -627,8 +629,6 @@ source_set("test_support") {
"test/pixel_test_software_output_device.h",
"test/pixel_test_utils.cc",
"test/pixel_test_utils.h",
- "test/render_pass_test_common.cc",
- "test/render_pass_test_common.h",
"test/render_pass_test_utils.cc",
"test/render_pass_test_utils.h",
"test/scheduler_test_common.cc",
@@ -662,6 +662,7 @@ source_set("test_support") {
"test/test_web_graphics_context_3d.h",
]
+ configs += [ "//build/config:precompiled_headers" ]
include_dirs = [
".",
"test",
@@ -688,6 +689,7 @@ source_set("test_support") {
"//ui/gfx/geometry",
"//ui/gfx:test_support",
"//ui/gl",
+ "//ui/gl:test_support",
]
if (!is_android) { # TODO(GYP) Enable on Android when osmesa links.
@@ -695,6 +697,15 @@ source_set("test_support") {
}
}
+# TODO(GYP): Delete this after we've converted everything to GN.
+# The _run targets exist only for compatibility w/ GYP.
+group("cc_unittests_run") {
+ testonly = true
+ deps = [
+ ":cc_unittests",
+ ]
+}
+
test("cc_unittests") {
sources = [
"animation/animation_host_unittest.cc",
@@ -708,18 +719,23 @@ test("cc_unittests") {
"animation/scrollbar_animation_controller_linear_fade_unittest.cc",
"animation/scrollbar_animation_controller_thinning_unittest.cc",
"animation/transform_operations_unittest.cc",
+ "base/delayed_unique_notifier_unittest.cc",
"base/float_quad_unittest.cc",
"base/histograms_unittest.cc",
"base/list_container_unittest.cc",
"base/math_util_unittest.cc",
+ "base/random_access_list_container_unittest.cc",
"base/region_unittest.cc",
"base/rolling_time_delta_history_unittest.cc",
+ "base/rtree_unittest.cc",
"base/scoped_ptr_vector_unittest.cc",
- "base/sidecar_list_container_unittest.cc",
"base/simple_enclosed_region_unittest.cc",
"base/tiling_data_unittest.cc",
+ "base/unique_notifier_unittest.cc",
"debug/frame_timing_tracker_unittest.cc",
"debug/micro_benchmark_controller_unittest.cc",
+ "debug/rendering_stats_unittest.cc",
+ "input/scroll_state_unittest.cc",
"input/top_controls_manager_unittest.cc",
"layers/delegated_frame_provider_unittest.cc",
"layers/delegated_frame_resource_collection_unittest.cc",
@@ -754,6 +770,7 @@ test("cc_unittests") {
"layers/video_frame_provider_client_impl_unittest.cc",
"layers/video_layer_impl_unittest.cc",
"output/begin_frame_args_unittest.cc",
+ "output/bsp_tree_unittest.cc",
"output/delegating_renderer_unittest.cc",
"output/filter_operations_unittest.cc",
"output/gl_renderer_unittest.cc",
@@ -765,14 +782,11 @@ test("cc_unittests") {
"output/shader_unittest.cc",
"output/software_renderer_unittest.cc",
"output/texture_mailbox_deleter_unittest.cc",
+ "playback/discardable_image_map_unittest.cc",
"playback/display_item_list_unittest.cc",
"playback/display_list_raster_source_unittest.cc",
"playback/display_list_recording_source_unittest.cc",
- "playback/picture_pile_impl_unittest.cc",
- "playback/picture_pile_unittest.cc",
- "playback/picture_unittest.cc",
- "playback/pixel_ref_map_unittest.cc",
- "playback/recording_source_unittest.cc",
+ "quads/draw_polygon_unittest.cc",
"quads/draw_quad_unittest.cc",
"quads/render_pass_unittest.cc",
"raster/scoped_gpu_raster_unittest.cc",
@@ -782,6 +796,7 @@ test("cc_unittests") {
"resources/platform_color_unittest.cc",
"resources/resource_pool_unittest.cc",
"resources/resource_provider_unittest.cc",
+ "resources/resource_util_unittest.cc",
"resources/scoped_resource_unittest.cc",
"resources/video_resource_updater_unittest.cc",
"scheduler/begin_frame_source_unittest.cc",
@@ -790,6 +805,7 @@ test("cc_unittests") {
"scheduler/scheduler_state_machine_unittest.cc",
"scheduler/scheduler_unittest.cc",
"test/layer_tree_json_parser_unittest.cc",
+ "test/ordered_simple_task_runner_unittest.cc",
"test/test_web_graphics_context_3d_unittest.cc",
"tiles/picture_layer_tiling_set_unittest.cc",
"tiles/picture_layer_tiling_unittest.cc",
@@ -824,9 +840,14 @@ test("cc_unittests") {
"trees/tree_synchronizer_unittest.cc",
# Surfaces test files.
+ "surfaces/display_scheduler_unittest.cc",
+ "surfaces/display_unittest.cc",
"surfaces/surface_aggregator_test_helpers.cc",
"surfaces/surface_aggregator_test_helpers.h",
"surfaces/surface_aggregator_unittest.cc",
+ "surfaces/surface_display_output_surface_unittest.cc",
+ "surfaces/surface_factory_unittest.cc",
+ "surfaces/surface_hittest_unittest.cc",
"surfaces/surface_unittest.cc",
"surfaces/surfaces_pixeltest.cc",
@@ -835,6 +856,11 @@ test("cc_unittests") {
"test/run_all_unittests.cc",
]
+ configs += [ "//build/config:precompiled_headers" ]
+ data = [
+ "test/data/",
+ ]
+
deps = [
":cc",
":test_support",
@@ -853,14 +879,16 @@ test("cc_unittests") {
"//ui/gfx/geometry",
"//ui/gfx:test_support",
"//ui/gl",
+ "//ui/gl:test_support",
]
+
+ data_deps = [ "//third_party/mesa:osmesa" ]
}
test("cc_perftests") {
sources = [
"layers/layer_perftest.cc",
"layers/picture_layer_impl_perftest.cc",
- "playback/picture_pile_impl_perftest.cc",
"quads/draw_quad_perftest.cc",
"raster/task_graph_runner_perftest.cc",
"raster/texture_compressor_perftest.cc",
@@ -893,6 +921,7 @@ test("cc_perftests") {
"//ui/gfx",
"//ui/gfx/geometry",
"//ui/gl",
+ "//ui/gl:test_support",
]
if (is_android) {
diff --git a/chromium/cc/OWNERS b/chromium/cc/OWNERS
index 6cc39e71a21..952f4b51d2d 100644
--- a/chromium/cc/OWNERS
+++ b/chromium/cc/OWNERS
@@ -6,8 +6,8 @@
# ask for informal reviews.
enne@chromium.org
-jamesr@chromium.org
-nduca@chromium.org
+danakj@chromium.org
+vmpstr@chromium.org
# layers / quads / passes
enne@chromium.org
@@ -17,8 +17,7 @@ danakj@chromium.org
piman@chromium.org
danakj@chromium.org
-# resource management / mac-specific
-# unofficial: epenner@chromium.org
+# mac-specific
ccameron@chromium.org
# input, gestures, scrolling
@@ -47,6 +46,10 @@ vollick@chromium.org
vollick@chromium.org
ajuma@chromium.org
+# we miss you
+# jamesr@chromium.org
+# nduca@chromium.org
+
per-file *.isolate=maruel@chromium.org
per-file *.isolate=tandrii@chromium.org
per-file *.isolate=vadimsh@chromium.org
diff --git a/chromium/cc/animation/animation_host.cc b/chromium/cc/animation/animation_host.cc
index e7f289fad9a..a9515be20aa 100644
--- a/chromium/cc/animation/animation_host.cc
+++ b/chromium/cc/animation/animation_host.cc
@@ -357,41 +357,79 @@ bool AnimationHost::ScrollOffsetAnimationWasInterrupted(int layer_id) const {
: false;
}
-bool AnimationHost::IsAnimatingFilterProperty(int layer_id) const {
+static LayerAnimationController::ObserverType ObserverTypeFromTreeType(
+ LayerTreeType tree_type) {
+ return tree_type == LayerTreeType::ACTIVE
+ ? LayerAnimationController::ObserverType::ACTIVE
+ : LayerAnimationController::ObserverType::PENDING;
+}
+
+bool AnimationHost::IsAnimatingFilterProperty(int layer_id,
+ LayerTreeType tree_type) const {
LayerAnimationController* controller = GetControllerForLayerId(layer_id);
- return controller ? controller->IsAnimatingProperty(Animation::FILTER)
- : false;
+ return controller
+ ? controller->IsCurrentlyAnimatingProperty(
+ Animation::FILTER, ObserverTypeFromTreeType(tree_type))
+ : false;
}
-bool AnimationHost::IsAnimatingOpacityProperty(int layer_id) const {
+bool AnimationHost::IsAnimatingOpacityProperty(int layer_id,
+ LayerTreeType tree_type) const {
LayerAnimationController* controller = GetControllerForLayerId(layer_id);
- return controller ? controller->IsAnimatingProperty(Animation::OPACITY)
- : false;
+ return controller
+ ? controller->IsCurrentlyAnimatingProperty(
+ Animation::OPACITY, ObserverTypeFromTreeType(tree_type))
+ : false;
}
-bool AnimationHost::IsAnimatingTransformProperty(int layer_id) const {
+bool AnimationHost::IsAnimatingTransformProperty(
+ int layer_id,
+ LayerTreeType tree_type) const {
LayerAnimationController* controller = GetControllerForLayerId(layer_id);
- return controller ? controller->IsAnimatingProperty(Animation::TRANSFORM)
- : false;
+ return controller
+ ? controller->IsCurrentlyAnimatingProperty(
+ Animation::TRANSFORM, ObserverTypeFromTreeType(tree_type))
+ : false;
}
-bool AnimationHost::HasPotentiallyRunningOpacityAnimation(int layer_id) const {
+bool AnimationHost::HasPotentiallyRunningFilterAnimation(
+ int layer_id,
+ LayerTreeType tree_type) const {
LayerAnimationController* controller = GetControllerForLayerId(layer_id);
- if (!controller)
- return false;
+ return controller
+ ? controller->IsPotentiallyAnimatingProperty(
+ Animation::FILTER, ObserverTypeFromTreeType(tree_type))
+ : false;
+}
- Animation* animation = controller->GetAnimation(Animation::OPACITY);
- return animation && !animation->is_finished();
+bool AnimationHost::HasPotentiallyRunningOpacityAnimation(
+ int layer_id,
+ LayerTreeType tree_type) const {
+ LayerAnimationController* controller = GetControllerForLayerId(layer_id);
+ return controller
+ ? controller->IsPotentiallyAnimatingProperty(
+ Animation::OPACITY, ObserverTypeFromTreeType(tree_type))
+ : false;
}
bool AnimationHost::HasPotentiallyRunningTransformAnimation(
- int layer_id) const {
+ int layer_id,
+ LayerTreeType tree_type) const {
+ LayerAnimationController* controller = GetControllerForLayerId(layer_id);
+ return controller
+ ? controller->IsPotentiallyAnimatingProperty(
+ Animation::TRANSFORM, ObserverTypeFromTreeType(tree_type))
+ : false;
+}
+
+bool AnimationHost::HasAnyAnimationTargetingProperty(
+ int layer_id,
+ Animation::TargetProperty property) const {
LayerAnimationController* controller = GetControllerForLayerId(layer_id);
if (!controller)
return false;
- Animation* animation = controller->GetAnimation(Animation::TRANSFORM);
- return animation && !animation->is_finished();
+ return !!controller->GetAnimation(property);
}
bool AnimationHost::FilterIsAnimatingOnImplOnly(int layer_id) const {
@@ -456,9 +494,14 @@ bool AnimationHost::TransformAnimationBoundsForBox(int layer_id,
: true;
}
-bool AnimationHost::HasOnlyTranslationTransforms(int layer_id) const {
+bool AnimationHost::HasOnlyTranslationTransforms(
+ int layer_id,
+ LayerTreeType tree_type) const {
LayerAnimationController* controller = GetControllerForLayerId(layer_id);
- return controller ? controller->HasOnlyTranslationTransforms() : true;
+ return controller
+ ? controller->HasOnlyTranslationTransforms(
+ ObserverTypeFromTreeType(tree_type))
+ : true;
}
bool AnimationHost::AnimationsPreserveAxisAlignment(int layer_id) const {
@@ -466,17 +509,26 @@ bool AnimationHost::AnimationsPreserveAxisAlignment(int layer_id) const {
return controller ? controller->AnimationsPreserveAxisAlignment() : true;
}
-bool AnimationHost::MaximumTargetScale(int layer_id, float* max_scale) const {
+bool AnimationHost::MaximumTargetScale(int layer_id,
+ LayerTreeType tree_type,
+ float* max_scale) const {
*max_scale = 0.f;
LayerAnimationController* controller = GetControllerForLayerId(layer_id);
- return controller ? controller->MaximumTargetScale(max_scale) : true;
+ return controller
+ ? controller->MaximumTargetScale(
+ ObserverTypeFromTreeType(tree_type), max_scale)
+ : true;
}
bool AnimationHost::AnimationStartScale(int layer_id,
+ LayerTreeType tree_type,
float* start_scale) const {
*start_scale = 0.f;
LayerAnimationController* controller = GetControllerForLayerId(layer_id);
- return controller ? controller->AnimationStartScale(start_scale) : true;
+ return controller
+ ? controller->AnimationStartScale(
+ ObserverTypeFromTreeType(tree_type), start_scale)
+ : true;
}
bool AnimationHost::HasAnyAnimation(int layer_id) const {
diff --git a/chromium/cc/animation/animation_host.h b/chromium/cc/animation/animation_host.h
index 3f69a023379..05782c09786 100644
--- a/chromium/cc/animation/animation_host.h
+++ b/chromium/cc/animation/animation_host.h
@@ -93,12 +93,21 @@ class CC_EXPORT AnimationHost {
bool ScrollOffsetAnimationWasInterrupted(int layer_id) const;
- bool IsAnimatingFilterProperty(int layer_id) const;
- bool IsAnimatingOpacityProperty(int layer_id) const;
- bool IsAnimatingTransformProperty(int layer_id) const;
-
- bool HasPotentiallyRunningOpacityAnimation(int layer_id) const;
- bool HasPotentiallyRunningTransformAnimation(int layer_id) const;
+ bool IsAnimatingFilterProperty(int layer_id, LayerTreeType tree_type) const;
+ bool IsAnimatingOpacityProperty(int layer_id, LayerTreeType tree_type) const;
+ bool IsAnimatingTransformProperty(int layer_id,
+ LayerTreeType tree_type) const;
+
+ bool HasPotentiallyRunningFilterAnimation(int layer_id,
+ LayerTreeType tree_type) const;
+ bool HasPotentiallyRunningOpacityAnimation(int layer_id,
+ LayerTreeType tree_type) const;
+ bool HasPotentiallyRunningTransformAnimation(int layer_id,
+ LayerTreeType tree_type) const;
+
+ bool HasAnyAnimationTargetingProperty(
+ int layer_id,
+ Animation::TargetProperty property) const;
bool FilterIsAnimatingOnImplOnly(int layer_id) const;
bool OpacityIsAnimatingOnImplOnly(int layer_id) const;
@@ -115,11 +124,16 @@ class CC_EXPORT AnimationHost {
const gfx::BoxF& box,
gfx::BoxF* bounds) const;
- bool HasOnlyTranslationTransforms(int layer_id) const;
+ bool HasOnlyTranslationTransforms(int layer_id,
+ LayerTreeType tree_type) const;
bool AnimationsPreserveAxisAlignment(int layer_id) const;
- bool MaximumTargetScale(int layer_id, float* max_scale) const;
- bool AnimationStartScale(int layer_id, float* start_scale) const;
+ bool MaximumTargetScale(int layer_id,
+ LayerTreeType tree_type,
+ float* max_scale) const;
+ bool AnimationStartScale(int layer_id,
+ LayerTreeType tree_type,
+ float* start_scale) const;
bool HasAnyAnimation(int layer_id) const;
bool HasActiveAnimation(int layer_id) const;
diff --git a/chromium/cc/animation/animation_timeline.cc b/chromium/cc/animation/animation_timeline.cc
index 9d19f8fbe0b..c3f5e6918b7 100644
--- a/chromium/cc/animation/animation_timeline.cc
+++ b/chromium/cc/animation/animation_timeline.cc
@@ -35,8 +35,8 @@ void AnimationTimeline::SetAnimationHost(AnimationHost* animation_host) {
}
void AnimationTimeline::AttachPlayer(scoped_refptr<AnimationPlayer> player) {
- DCHECK(animation_host_);
player->SetAnimationHost(animation_host_);
+
player->SetAnimationTimeline(this);
players_.push_back(player);
}
diff --git a/chromium/cc/animation/element_animations.cc b/chromium/cc/animation/element_animations.cc
index 2974bff91a2..b358b5b5e6d 100644
--- a/chromium/cc/animation/element_animations.cc
+++ b/chromium/cc/animation/element_animations.cc
@@ -41,6 +41,11 @@ class ElementAnimations::ValueObserver : public LayerAnimationValueObserver {
// PushProperties for AnimationTimelines for now.
}
+ void OnTransformIsPotentiallyAnimatingChanged(bool is_animating) override {
+ element_animations_->SetTransformIsPotentiallyAnimatingChanged(
+ tree_type_, is_animating);
+ }
+
bool IsActive() const override { return tree_type_ == LayerTreeType::ACTIVE; }
private:
@@ -184,6 +189,18 @@ void ElementAnimations::SetScrollOffsetMutated(
layer_id(), tree_type, scroll_offset);
}
+void ElementAnimations::SetTransformIsPotentiallyAnimatingChanged(
+ LayerTreeType tree_type,
+ bool is_animating) {
+ DCHECK(layer_id());
+ DCHECK(animation_host());
+ DCHECK(animation_host()->mutator_host_client());
+ animation_host()
+ ->mutator_host_client()
+ ->LayerTransformIsPotentiallyAnimatingChanged(layer_id(), tree_type,
+ is_animating);
+}
+
void ElementAnimations::CreateActiveValueObserver() {
DCHECK(layer_animation_controller_);
DCHECK(!active_value_observer_);
diff --git a/chromium/cc/animation/element_animations.h b/chromium/cc/animation/element_animations.h
index 6fb2a429d4a..0d4fb6ac383 100644
--- a/chromium/cc/animation/element_animations.h
+++ b/chromium/cc/animation/element_animations.h
@@ -83,6 +83,8 @@ class CC_EXPORT ElementAnimations : public AnimationDelegate,
const gfx::Transform& transform);
void SetScrollOffsetMutated(LayerTreeType tree_type,
const gfx::ScrollOffset& scroll_offset);
+ void SetTransformIsPotentiallyAnimatingChanged(LayerTreeType tree_type,
+ bool is_animating);
void CreateActiveValueObserver();
void DestroyActiveValueObserver();
diff --git a/chromium/cc/animation/layer_animation_controller.cc b/chromium/cc/animation/layer_animation_controller.cc
index 54b1a717f78..d649ac73972 100644
--- a/chromium/cc/animation/layer_animation_controller.cc
+++ b/chromium/cc/animation/layer_animation_controller.cc
@@ -28,8 +28,9 @@ LayerAnimationController::LayerAnimationController(int id)
value_provider_(nullptr),
layer_animation_delegate_(nullptr),
needs_to_start_animations_(false),
- scroll_offset_animation_was_interrupted_(false) {
-}
+ scroll_offset_animation_was_interrupted_(false),
+ potentially_animating_transform_for_active_observers_(false),
+ potentially_animating_transform_for_pending_observers_(false) {}
LayerAnimationController::~LayerAnimationController() {
if (registrar_)
@@ -46,7 +47,8 @@ void LayerAnimationController::PauseAnimation(int animation_id,
for (size_t i = 0; i < animations_.size(); ++i) {
if (animations_[i]->id() == animation_id) {
animations_[i]->SetRunState(Animation::PAUSED,
- time_offset + animations_[i]->start_time());
+ time_offset + animations_[i]->start_time() +
+ animations_[i]->time_offset());
}
}
}
@@ -61,17 +63,56 @@ struct HasAnimationId {
int id_;
};
+void LayerAnimationController::UpdatePotentiallyAnimatingTransform() {
+ bool was_potentially_animating_transform_for_active_observers =
+ potentially_animating_transform_for_active_observers_;
+ bool was_potentially_animating_transform_for_pending_observers =
+ potentially_animating_transform_for_pending_observers_;
+
+ potentially_animating_transform_for_active_observers_ = false;
+ potentially_animating_transform_for_pending_observers_ = false;
+
+ for (Animation* animation : animations_) {
+ if (!animation->is_finished() &&
+ animation->target_property() == Animation::TRANSFORM) {
+ potentially_animating_transform_for_active_observers_ |=
+ animation->affects_active_observers();
+ potentially_animating_transform_for_pending_observers_ |=
+ animation->affects_pending_observers();
+ }
+ }
+
+ bool changed_for_active_observers =
+ was_potentially_animating_transform_for_active_observers !=
+ potentially_animating_transform_for_active_observers_;
+ bool changed_for_pending_observers =
+ was_potentially_animating_transform_for_pending_observers !=
+ potentially_animating_transform_for_pending_observers_;
+
+ if (!changed_for_active_observers && !changed_for_pending_observers)
+ return;
+
+ NotifyObserversTransformIsPotentiallyAnimatingChanged(
+ changed_for_active_observers, changed_for_pending_observers);
+}
+
void LayerAnimationController::RemoveAnimation(int animation_id) {
+ bool removed_transform_animation = false;
auto animations_to_remove =
animations_.remove_if(HasAnimationId(animation_id));
for (auto it = animations_to_remove; it != animations_.end(); ++it) {
if ((*it)->target_property() == Animation::SCROLL_OFFSET) {
scroll_offset_animation_was_interrupted_ = true;
- break;
+ } else if ((*it)->target_property() == Animation::TRANSFORM &&
+ !(*it)->is_finished()) {
+ removed_transform_animation = true;
}
}
+
animations_.erase(animations_to_remove, animations_.end());
UpdateActivation(NORMAL_ACTIVATION);
+ if (removed_transform_animation)
+ UpdatePotentiallyAnimatingTransform();
}
struct HasAnimationIdAndProperty {
@@ -90,23 +131,37 @@ struct HasAnimationIdAndProperty {
void LayerAnimationController::RemoveAnimation(
int animation_id,
Animation::TargetProperty target_property) {
+ bool removed_transform_animation = false;
auto animations_to_remove = animations_.remove_if(
HasAnimationIdAndProperty(animation_id, target_property));
- if (target_property == Animation::SCROLL_OFFSET &&
- animations_to_remove != animations_.end())
+ if (animations_to_remove == animations_.end())
+ return;
+
+ if (target_property == Animation::SCROLL_OFFSET)
scroll_offset_animation_was_interrupted_ = true;
+ else if (target_property == Animation::TRANSFORM &&
+ !(*animations_to_remove)->is_finished())
+ removed_transform_animation = true;
animations_.erase(animations_to_remove, animations_.end());
UpdateActivation(NORMAL_ACTIVATION);
+ if (removed_transform_animation)
+ UpdatePotentiallyAnimatingTransform();
}
void LayerAnimationController::AbortAnimations(
Animation::TargetProperty target_property) {
+ bool aborted_transform_animation = false;
for (size_t i = 0; i < animations_.size(); ++i) {
if (animations_[i]->target_property() == target_property &&
- !animations_[i]->is_finished())
+ !animations_[i]->is_finished()) {
animations_[i]->SetRunState(Animation::ABORTED, last_tick_time_);
+ if (target_property == Animation::TRANSFORM)
+ aborted_transform_animation = true;
+ }
}
+ if (aborted_transform_animation)
+ UpdatePotentiallyAnimatingTransform();
}
// Ensures that the list of active animations on the main thread and the impl
@@ -241,7 +296,12 @@ struct AffectsNoObservers {
};
void LayerAnimationController::ActivateAnimations() {
+ bool changed_transform_animation = false;
for (size_t i = 0; i < animations_.size(); ++i) {
+ if (animations_[i]->affects_active_observers() !=
+ animations_[i]->affects_pending_observers() &&
+ animations_[i]->target_property() == Animation::TRANSFORM)
+ changed_transform_animation = true;
animations_[i]->set_affects_active_observers(
animations_[i]->affects_pending_observers());
}
@@ -252,12 +312,18 @@ void LayerAnimationController::ActivateAnimations() {
animations_.end());
scroll_offset_animation_was_interrupted_ = false;
UpdateActivation(NORMAL_ACTIVATION);
+ if (changed_transform_animation)
+ UpdatePotentiallyAnimatingTransform();
}
void LayerAnimationController::AddAnimation(scoped_ptr<Animation> animation) {
+ bool added_transform_animation =
+ animation->target_property() == Animation::TRANSFORM;
animations_.push_back(animation.Pass());
needs_to_start_animations_ = true;
UpdateActivation(NORMAL_ACTIVATION);
+ if (added_transform_animation)
+ UpdatePotentiallyAnimatingTransform();
}
Animation* LayerAnimationController::GetAnimation(
@@ -285,13 +351,35 @@ bool LayerAnimationController::HasActiveAnimation() const {
return false;
}
-bool LayerAnimationController::IsAnimatingProperty(
- Animation::TargetProperty target_property) const {
+bool LayerAnimationController::IsPotentiallyAnimatingProperty(
+ Animation::TargetProperty target_property,
+ ObserverType observer_type) const {
+ for (size_t i = 0; i < animations_.size(); ++i) {
+ if (!animations_[i]->is_finished() &&
+ animations_[i]->target_property() == target_property) {
+ if ((observer_type == ObserverType::ACTIVE &&
+ animations_[i]->affects_active_observers()) ||
+ (observer_type == ObserverType::PENDING &&
+ animations_[i]->affects_pending_observers()))
+ return true;
+ }
+ }
+ return false;
+}
+
+bool LayerAnimationController::IsCurrentlyAnimatingProperty(
+ Animation::TargetProperty target_property,
+ ObserverType observer_type) const {
for (size_t i = 0; i < animations_.size(); ++i) {
if (!animations_[i]->is_finished() &&
animations_[i]->InEffect(last_tick_time_) &&
- animations_[i]->target_property() == target_property)
- return true;
+ animations_[i]->target_property() == target_property) {
+ if ((observer_type == ObserverType::ACTIVE &&
+ animations_[i]->affects_active_observers()) ||
+ (observer_type == ObserverType::PENDING &&
+ animations_[i]->affects_pending_observers()))
+ return true;
+ }
}
return false;
}
@@ -365,12 +453,17 @@ void LayerAnimationController::NotifyAnimationFinished(
void LayerAnimationController::NotifyAnimationAborted(
const AnimationEvent& event) {
+ bool aborted_transform_animation = false;
for (size_t i = 0; i < animations_.size(); ++i) {
if (animations_[i]->group() == event.group_id &&
animations_[i]->target_property() == event.target_property) {
animations_[i]->SetRunState(Animation::ABORTED, event.monotonic_time);
+ if (event.target_property == Animation::TRANSFORM)
+ aborted_transform_animation = true;
}
}
+ if (aborted_transform_animation)
+ UpdatePotentiallyAnimatingTransform();
}
void LayerAnimationController::NotifyAnimationPropertyUpdate(
@@ -428,7 +521,10 @@ bool LayerAnimationController::HasFilterAnimationThatInflatesBounds() const {
}
bool LayerAnimationController::HasTransformAnimationThatInflatesBounds() const {
- return IsAnimatingProperty(Animation::TRANSFORM);
+ return IsCurrentlyAnimatingProperty(Animation::TRANSFORM,
+ ObserverType::ACTIVE) ||
+ IsCurrentlyAnimatingProperty(Animation::TRANSFORM,
+ ObserverType::PENDING);
}
bool LayerAnimationController::FilterAnimationBoundsForBox(
@@ -483,12 +579,19 @@ bool LayerAnimationController::HasAnimationThatAffectsScale() const {
return false;
}
-bool LayerAnimationController::HasOnlyTranslationTransforms() const {
+bool LayerAnimationController::HasOnlyTranslationTransforms(
+ ObserverType observer_type) const {
for (size_t i = 0; i < animations_.size(); ++i) {
if (animations_[i]->is_finished() ||
animations_[i]->target_property() != Animation::TRANSFORM)
continue;
+ if ((observer_type == ObserverType::ACTIVE &&
+ !animations_[i]->affects_active_observers()) ||
+ (observer_type == ObserverType::PENDING &&
+ !animations_[i]->affects_pending_observers()))
+ continue;
+
const TransformAnimationCurve* transform_animation_curve =
animations_[i]->curve()->ToTransformAnimationCurve();
if (!transform_animation_curve->IsTranslation())
@@ -513,13 +616,20 @@ bool LayerAnimationController::AnimationsPreserveAxisAlignment() const {
return true;
}
-bool LayerAnimationController::AnimationStartScale(float* start_scale) const {
+bool LayerAnimationController::AnimationStartScale(ObserverType observer_type,
+ float* start_scale) const {
*start_scale = 0.f;
for (size_t i = 0; i < animations_.size(); ++i) {
if (animations_[i]->is_finished() ||
animations_[i]->target_property() != Animation::TRANSFORM)
continue;
+ if ((observer_type == ObserverType::ACTIVE &&
+ !animations_[i]->affects_active_observers()) ||
+ (observer_type == ObserverType::PENDING &&
+ !animations_[i]->affects_pending_observers()))
+ continue;
+
bool forward_direction = true;
switch (animations_[i]->direction()) {
case Animation::DIRECTION_NORMAL:
@@ -543,13 +653,20 @@ bool LayerAnimationController::AnimationStartScale(float* start_scale) const {
return true;
}
-bool LayerAnimationController::MaximumTargetScale(float* max_scale) const {
+bool LayerAnimationController::MaximumTargetScale(ObserverType observer_type,
+ float* max_scale) const {
*max_scale = 0.f;
for (size_t i = 0; i < animations_.size(); ++i) {
if (animations_[i]->is_finished() ||
animations_[i]->target_property() != Animation::TRANSFORM)
continue;
+ if ((observer_type == ObserverType::ACTIVE &&
+ !animations_[i]->affects_active_observers()) ||
+ (observer_type == ObserverType::PENDING &&
+ !animations_[i]->affects_pending_observers()))
+ continue;
+
bool forward_direction = true;
switch (animations_[i]->direction()) {
case Animation::DIRECTION_NORMAL:
@@ -627,20 +744,27 @@ static bool AffectsActiveOnlyAndIsWaitingForDeletion(Animation* animation) {
void LayerAnimationController::RemoveAnimationsCompletedOnMainThread(
LayerAnimationController* controller_impl) const {
+ bool removed_transform_animation = false;
// Animations removed on the main thread should no longer affect pending
// observers, and should stop affecting active observers after the next call
// to ActivateAnimations. If already WAITING_FOR_DELETION, they can be removed
// immediately.
ScopedPtrVector<Animation>& animations = controller_impl->animations_;
for (size_t i = 0; i < animations.size(); ++i) {
- if (IsCompleted(animations[i], this))
+ if (IsCompleted(animations[i], this)) {
animations[i]->set_affects_pending_observers(false);
+ if (animations[i]->target_property() == Animation::TRANSFORM)
+ removed_transform_animation = true;
+ }
}
animations.erase(cc::remove_if(&animations,
animations.begin(),
animations.end(),
AffectsActiveOnlyAndIsWaitingForDeletion),
animations.end());
+
+ if (removed_transform_animation)
+ controller_impl->UpdatePotentiallyAnimatingTransform();
}
void LayerAnimationController::PushPropertiesToImplThread(
@@ -775,12 +899,18 @@ void LayerAnimationController::PromoteStartedAnimations(
void LayerAnimationController::MarkFinishedAnimations(
base::TimeTicks monotonic_time) {
+ bool finished_transform_animation = false;
for (size_t i = 0; i < animations_.size(); ++i) {
- if (animations_[i]->IsFinishedAt(monotonic_time) &&
- animations_[i]->run_state() != Animation::ABORTED &&
- animations_[i]->run_state() != Animation::WAITING_FOR_DELETION)
+ if (!animations_[i]->is_finished() &&
+ animations_[i]->IsFinishedAt(monotonic_time)) {
animations_[i]->SetRunState(Animation::FINISHED, monotonic_time);
+ if (animations_[i]->target_property() == Animation::TRANSFORM) {
+ finished_transform_animation = true;
+ }
+ }
}
+ if (finished_transform_animation)
+ UpdatePotentiallyAnimatingTransform();
}
void LayerAnimationController::MarkAnimationsForDeletion(
@@ -1053,6 +1183,25 @@ void LayerAnimationController::NotifyObserversAnimationWaitingForDeletion() {
OnAnimationWaitingForDeletion());
}
+void LayerAnimationController::
+ NotifyObserversTransformIsPotentiallyAnimatingChanged(
+ bool notify_active_observers,
+ bool notify_pending_observers) {
+ if (value_observers_.might_have_observers()) {
+ base::ObserverListBase<LayerAnimationValueObserver>::Iterator it(
+ &value_observers_);
+ LayerAnimationValueObserver* obs;
+ while ((obs = it.GetNext()) != nullptr) {
+ if (notify_active_observers && obs->IsActive())
+ obs->OnTransformIsPotentiallyAnimatingChanged(
+ potentially_animating_transform_for_active_observers_);
+ else if (notify_pending_observers && !obs->IsActive())
+ obs->OnTransformIsPotentiallyAnimatingChanged(
+ potentially_animating_transform_for_pending_observers_);
+ }
+ }
+}
+
bool LayerAnimationController::HasValueObserver() {
if (value_observers_.might_have_observers()) {
base::ObserverListBase<LayerAnimationValueObserver>::Iterator it(
diff --git a/chromium/cc/animation/layer_animation_controller.h b/chromium/cc/animation/layer_animation_controller.h
index 4b37ad44930..307e89920ae 100644
--- a/chromium/cc/animation/layer_animation_controller.h
+++ b/chromium/cc/animation/layer_animation_controller.h
@@ -36,6 +36,8 @@ class LayerAnimationValueProvider;
class CC_EXPORT LayerAnimationController
: public base::RefCounted<LayerAnimationController> {
public:
+ enum class ObserverType { ACTIVE, PENDING };
+
static scoped_refptr<LayerAnimationController> Create(int id);
int id() const { return id_; }
@@ -79,10 +81,16 @@ class CC_EXPORT LayerAnimationController
// Returns true if there are any animations at all to process.
bool has_any_animation() const { return !animations_.empty(); }
- // Returns true if there is an animation currently animating the given
- // property, or if there is an animation scheduled to animate this property in
- // the future.
- bool IsAnimatingProperty(Animation::TargetProperty target_property) const;
+ // Returns true if there is an animation that is either currently animating
+ // the given property or scheduled to animate this property in the future, and
+ // that affects the given observer type.
+ bool IsPotentiallyAnimatingProperty(Animation::TargetProperty target_property,
+ ObserverType observer_type) const;
+
+ // Returns true if there is an animation that is currently animating the given
+ // property and that affects the given observer type.
+ bool IsCurrentlyAnimatingProperty(Animation::TargetProperty target_property,
+ ObserverType observer_type) const;
void SetAnimationRegistrar(AnimationRegistrar* registrar);
AnimationRegistrar* animation_registrar() { return registrar_; }
@@ -130,19 +138,21 @@ class CC_EXPORT LayerAnimationController
bool HasAnimationThatAffectsScale() const;
- bool HasOnlyTranslationTransforms() const;
+ bool HasOnlyTranslationTransforms(ObserverType observer_type) const;
bool AnimationsPreserveAxisAlignment() const;
// Sets |start_scale| to the maximum of starting animation scale along any
// dimension at any destination in active animations. Returns false if the
// starting scale cannot be computed.
- bool AnimationStartScale(float* start_scale) const;
+ bool AnimationStartScale(ObserverType observer_type,
+ float* start_scale) const;
// Sets |max_scale| to the maximum scale along any dimension at any
// destination in active animations. Returns false if the maximum scale cannot
// be computed.
- bool MaximumTargetScale(float* max_scale) const;
+ bool MaximumTargetScale(ObserverType event_observers_,
+ float* max_scale) const;
// When a scroll animation is removed on the main thread, its compositor
// thread counterpart continues producing scroll deltas until activation.
@@ -203,6 +213,12 @@ class CC_EXPORT LayerAnimationController
void NotifyObserversAnimationWaitingForDeletion();
+ void NotifyObserversTransformIsPotentiallyAnimatingChanged(
+ bool notify_active_observers,
+ bool notify_pending_observers);
+
+ void UpdatePotentiallyAnimatingTransform();
+
bool HasValueObserver();
bool HasActiveValueObserver();
@@ -228,6 +244,9 @@ class CC_EXPORT LayerAnimationController
bool scroll_offset_animation_was_interrupted_;
+ bool potentially_animating_transform_for_active_observers_;
+ bool potentially_animating_transform_for_pending_observers_;
+
DISALLOW_COPY_AND_ASSIGN(LayerAnimationController);
};
diff --git a/chromium/cc/animation/layer_animation_controller_unittest.cc b/chromium/cc/animation/layer_animation_controller_unittest.cc
index e267eea1288..8089ebfe294 100644
--- a/chromium/cc/animation/layer_animation_controller_unittest.cc
+++ b/chromium/cc/animation/layer_animation_controller_unittest.cc
@@ -254,8 +254,14 @@ TEST(LayerAnimationControllerTest, SyncPause) {
EXPECT_FALSE(controller_impl->GetAnimation(Animation::OPACITY));
- int animation_id =
- AddOpacityTransitionToController(controller.get(), 1, 0, 1, false);
+ // Two steps, three ranges: [0-1) -> 0.2, [1-2) -> 0.3, [2-3] -> 0.4.
+ const double duration = 3.0;
+ const int animation_id =
+ AddOpacityStepsToController(controller.get(), duration, 0.2f, 0.4f, 2);
+
+ // Set start offset to be at the beginning of the second range.
+ controller->GetAnimationById(animation_id)
+ ->set_time_offset(TimeDelta::FromSecondsD(1.01));
controller->PushAnimationUpdatesTo(controller_impl.get());
controller_impl->ActivateAnimations();
@@ -264,29 +270,52 @@ TEST(LayerAnimationControllerTest, SyncPause) {
EXPECT_EQ(Animation::WAITING_FOR_TARGET_AVAILABILITY,
controller_impl->GetAnimationById(animation_id)->run_state());
+ TimeTicks time = kInitialTickTime;
+
// Start the animations on each controller.
AnimationEventsVector events;
- controller_impl->Animate(kInitialTickTime);
+ controller_impl->Animate(time);
controller_impl->UpdateState(true, &events);
- controller->Animate(kInitialTickTime);
+ EXPECT_EQ(1u, events.size());
+
+ controller->Animate(time);
controller->UpdateState(true, nullptr);
+ controller->NotifyAnimationStarted(events[0]);
+
EXPECT_EQ(Animation::RUNNING,
controller_impl->GetAnimationById(animation_id)->run_state());
EXPECT_EQ(Animation::RUNNING,
controller->GetAnimationById(animation_id)->run_state());
- // Pause the main-thread animation.
- controller->PauseAnimation(
- animation_id,
- TimeDelta::FromMilliseconds(1000) + TimeDelta::FromMilliseconds(1000));
+ EXPECT_EQ(0.3f, dummy.opacity());
+ EXPECT_EQ(0.3f, dummy_impl.opacity());
+
+ EXPECT_EQ(kInitialTickTime,
+ controller->GetAnimationById(animation_id)->start_time());
+ EXPECT_EQ(kInitialTickTime,
+ controller_impl->GetAnimationById(animation_id)->start_time());
+
+ // Pause the animation at the middle of the second range so the offset
+ // delays animation until the middle of the third range.
+ controller->PauseAnimation(animation_id, TimeDelta::FromSecondsD(1.5));
EXPECT_EQ(Animation::PAUSED,
controller->GetAnimationById(animation_id)->run_state());
// The pause run state change should make it to the impl thread controller.
controller->PushAnimationUpdatesTo(controller_impl.get());
controller_impl->ActivateAnimations();
+
+ // Advance time so it stays within the first range.
+ time += TimeDelta::FromMilliseconds(10);
+ controller->Animate(time);
+ controller_impl->Animate(time);
+
EXPECT_EQ(Animation::PAUSED,
controller_impl->GetAnimationById(animation_id)->run_state());
+
+ // Opacity value doesn't depend on time if paused at specified time offset.
+ EXPECT_EQ(0.4f, dummy.opacity());
+ EXPECT_EQ(0.4f, dummy_impl.opacity());
}
TEST(LayerAnimationControllerTest, DoNotSyncFinishedAnimation) {
@@ -1990,14 +2019,20 @@ TEST(LayerAnimationControllerTest, HasOnlyTranslationTransforms) {
scoped_refptr<LayerAnimationController> controller_impl(
LayerAnimationController::Create(0));
- EXPECT_TRUE(controller_impl->HasOnlyTranslationTransforms());
+ EXPECT_TRUE(controller_impl->HasOnlyTranslationTransforms(
+ LayerAnimationController::ObserverType::ACTIVE));
+ EXPECT_TRUE(controller_impl->HasOnlyTranslationTransforms(
+ LayerAnimationController::ObserverType::PENDING));
controller_impl->AddAnimation(CreateAnimation(
scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(),
1, Animation::OPACITY));
// Opacity animations aren't non-translation transforms.
- EXPECT_TRUE(controller_impl->HasOnlyTranslationTransforms());
+ EXPECT_TRUE(controller_impl->HasOnlyTranslationTransforms(
+ LayerAnimationController::ObserverType::ACTIVE));
+ EXPECT_TRUE(controller_impl->HasOnlyTranslationTransforms(
+ LayerAnimationController::ObserverType::PENDING));
scoped_ptr<KeyframedTransformAnimationCurve> curve1(
KeyframedTransformAnimationCurve::Create());
@@ -2014,7 +2049,10 @@ TEST(LayerAnimationControllerTest, HasOnlyTranslationTransforms) {
controller_impl->AddAnimation(animation.Pass());
// The only transform animation we've added is a translation.
- EXPECT_TRUE(controller_impl->HasOnlyTranslationTransforms());
+ EXPECT_TRUE(controller_impl->HasOnlyTranslationTransforms(
+ LayerAnimationController::ObserverType::ACTIVE));
+ EXPECT_TRUE(controller_impl->HasOnlyTranslationTransforms(
+ LayerAnimationController::ObserverType::PENDING));
scoped_ptr<KeyframedTransformAnimationCurve> curve2(
KeyframedTransformAnimationCurve::Create());
@@ -2027,17 +2065,36 @@ TEST(LayerAnimationControllerTest, HasOnlyTranslationTransforms) {
base::TimeDelta::FromSecondsD(1.0), operations2, nullptr));
animation = Animation::Create(curve2.Pass(), 3, 3, Animation::TRANSFORM);
+ animation->set_affects_active_observers(false);
controller_impl->AddAnimation(animation.Pass());
// A scale animation is not a translation.
- EXPECT_FALSE(controller_impl->HasOnlyTranslationTransforms());
+ EXPECT_FALSE(controller_impl->HasOnlyTranslationTransforms(
+ LayerAnimationController::ObserverType::PENDING));
+ EXPECT_TRUE(controller_impl->HasOnlyTranslationTransforms(
+ LayerAnimationController::ObserverType::ACTIVE));
+
+ controller_impl->ActivateAnimations();
+ EXPECT_FALSE(controller_impl->HasOnlyTranslationTransforms(
+ LayerAnimationController::ObserverType::PENDING));
+ EXPECT_FALSE(controller_impl->HasOnlyTranslationTransforms(
+ LayerAnimationController::ObserverType::ACTIVE));
+
+ controller_impl->GetAnimationById(3)->set_affects_pending_observers(false);
+ EXPECT_TRUE(controller_impl->HasOnlyTranslationTransforms(
+ LayerAnimationController::ObserverType::PENDING));
+ EXPECT_FALSE(controller_impl->HasOnlyTranslationTransforms(
+ LayerAnimationController::ObserverType::ACTIVE));
controller_impl->GetAnimationById(3)
->SetRunState(Animation::FINISHED, TicksFromSecondsF(0.0));
// Only unfinished animations should be considered by
// HasOnlyTranslationTransforms.
- EXPECT_TRUE(controller_impl->HasOnlyTranslationTransforms());
+ EXPECT_TRUE(controller_impl->HasOnlyTranslationTransforms(
+ LayerAnimationController::ObserverType::PENDING));
+ EXPECT_TRUE(controller_impl->HasOnlyTranslationTransforms(
+ LayerAnimationController::ObserverType::ACTIVE));
}
TEST(LayerAnimationControllerTest, AnimationStartScale) {
@@ -2055,10 +2112,23 @@ TEST(LayerAnimationControllerTest, AnimationStartScale) {
base::TimeDelta::FromSecondsD(1.0), operations2, nullptr));
scoped_ptr<Animation> animation(
Animation::Create(curve1.Pass(), 1, 1, Animation::TRANSFORM));
+ animation->set_affects_active_observers(false);
controller_impl->AddAnimation(animation.Pass());
float start_scale = 0.f;
- EXPECT_TRUE(controller_impl->AnimationStartScale(&start_scale));
+ EXPECT_TRUE(controller_impl->AnimationStartScale(
+ LayerAnimationController::ObserverType::PENDING, &start_scale));
+ EXPECT_EQ(4.f, start_scale);
+ EXPECT_TRUE(controller_impl->AnimationStartScale(
+ LayerAnimationController::ObserverType::ACTIVE, &start_scale));
+ EXPECT_EQ(0.f, start_scale);
+
+ controller_impl->ActivateAnimations();
+ EXPECT_TRUE(controller_impl->AnimationStartScale(
+ LayerAnimationController::ObserverType::PENDING, &start_scale));
+ EXPECT_EQ(4.f, start_scale);
+ EXPECT_TRUE(controller_impl->AnimationStartScale(
+ LayerAnimationController::ObserverType::ACTIVE, &start_scale));
EXPECT_EQ(4.f, start_scale);
scoped_ptr<KeyframedTransformAnimationCurve> curve2(
@@ -2076,6 +2146,7 @@ TEST(LayerAnimationControllerTest, AnimationStartScale) {
// Reverse Direction
animation->set_direction(Animation::DIRECTION_REVERSE);
+ animation->set_affects_active_observers(false);
controller_impl->AddAnimation(animation.Pass());
scoped_ptr<KeyframedTransformAnimationCurve> curve3(
@@ -2090,9 +2161,22 @@ TEST(LayerAnimationControllerTest, AnimationStartScale) {
base::TimeDelta::FromSecondsD(1.0), operations5, nullptr));
animation = Animation::Create(curve3.Pass(), 3, 3, Animation::TRANSFORM);
+ animation->set_affects_active_observers(false);
controller_impl->AddAnimation(animation.Pass());
- EXPECT_TRUE(controller_impl->AnimationStartScale(&start_scale));
+ EXPECT_TRUE(controller_impl->AnimationStartScale(
+ LayerAnimationController::ObserverType::PENDING, &start_scale));
+ EXPECT_EQ(6.f, start_scale);
+ EXPECT_TRUE(controller_impl->AnimationStartScale(
+ LayerAnimationController::ObserverType::ACTIVE, &start_scale));
+ EXPECT_EQ(0.f, start_scale);
+
+ controller_impl->ActivateAnimations();
+ EXPECT_TRUE(controller_impl->AnimationStartScale(
+ LayerAnimationController::ObserverType::PENDING, &start_scale));
+ EXPECT_EQ(6.f, start_scale);
+ EXPECT_TRUE(controller_impl->AnimationStartScale(
+ LayerAnimationController::ObserverType::ACTIVE, &start_scale));
EXPECT_EQ(6.f, start_scale);
controller_impl->GetAnimationById(2)
@@ -2100,7 +2184,11 @@ TEST(LayerAnimationControllerTest, AnimationStartScale) {
// Only unfinished animations should be considered by
// AnimationStartScale.
- EXPECT_TRUE(controller_impl->AnimationStartScale(&start_scale));
+ EXPECT_TRUE(controller_impl->AnimationStartScale(
+ LayerAnimationController::ObserverType::PENDING, &start_scale));
+ EXPECT_EQ(5.f, start_scale);
+ EXPECT_TRUE(controller_impl->AnimationStartScale(
+ LayerAnimationController::ObserverType::ACTIVE, &start_scale));
EXPECT_EQ(5.f, start_scale);
}
@@ -2109,7 +2197,11 @@ TEST(LayerAnimationControllerTest, MaximumTargetScale) {
LayerAnimationController::Create(0));
float max_scale = 0.f;
- EXPECT_TRUE(controller_impl->MaximumTargetScale(&max_scale));
+ EXPECT_TRUE(controller_impl->MaximumTargetScale(
+ LayerAnimationController::ObserverType::PENDING, &max_scale));
+ EXPECT_EQ(0.f, max_scale);
+ EXPECT_TRUE(controller_impl->MaximumTargetScale(
+ LayerAnimationController::ObserverType::ACTIVE, &max_scale));
EXPECT_EQ(0.f, max_scale);
scoped_ptr<KeyframedTransformAnimationCurve> curve1(
@@ -2124,9 +2216,22 @@ TEST(LayerAnimationControllerTest, MaximumTargetScale) {
scoped_ptr<Animation> animation(
Animation::Create(curve1.Pass(), 1, 1, Animation::TRANSFORM));
+ animation->set_affects_active_observers(false);
controller_impl->AddAnimation(animation.Pass());
- EXPECT_TRUE(controller_impl->MaximumTargetScale(&max_scale));
+ EXPECT_TRUE(controller_impl->MaximumTargetScale(
+ LayerAnimationController::ObserverType::PENDING, &max_scale));
+ EXPECT_EQ(4.f, max_scale);
+ EXPECT_TRUE(controller_impl->MaximumTargetScale(
+ LayerAnimationController::ObserverType::ACTIVE, &max_scale));
+ EXPECT_EQ(0.f, max_scale);
+
+ controller_impl->ActivateAnimations();
+ EXPECT_TRUE(controller_impl->MaximumTargetScale(
+ LayerAnimationController::ObserverType::PENDING, &max_scale));
+ EXPECT_EQ(4.f, max_scale);
+ EXPECT_TRUE(controller_impl->MaximumTargetScale(
+ LayerAnimationController::ObserverType::ACTIVE, &max_scale));
EXPECT_EQ(4.f, max_scale);
scoped_ptr<KeyframedTransformAnimationCurve> curve2(
@@ -2140,9 +2245,22 @@ TEST(LayerAnimationControllerTest, MaximumTargetScale) {
base::TimeDelta::FromSecondsD(1.0), operations2, nullptr));
animation = Animation::Create(curve2.Pass(), 2, 2, Animation::TRANSFORM);
+ animation->set_affects_active_observers(false);
controller_impl->AddAnimation(animation.Pass());
- EXPECT_TRUE(controller_impl->MaximumTargetScale(&max_scale));
+ EXPECT_TRUE(controller_impl->MaximumTargetScale(
+ LayerAnimationController::ObserverType::PENDING, &max_scale));
+ EXPECT_EQ(6.f, max_scale);
+ EXPECT_TRUE(controller_impl->MaximumTargetScale(
+ LayerAnimationController::ObserverType::ACTIVE, &max_scale));
+ EXPECT_EQ(4.f, max_scale);
+
+ controller_impl->ActivateAnimations();
+ EXPECT_TRUE(controller_impl->MaximumTargetScale(
+ LayerAnimationController::ObserverType::PENDING, &max_scale));
+ EXPECT_EQ(6.f, max_scale);
+ EXPECT_TRUE(controller_impl->MaximumTargetScale(
+ LayerAnimationController::ObserverType::ACTIVE, &max_scale));
EXPECT_EQ(6.f, max_scale);
scoped_ptr<KeyframedTransformAnimationCurve> curve3(
@@ -2156,9 +2274,20 @@ TEST(LayerAnimationControllerTest, MaximumTargetScale) {
base::TimeDelta::FromSecondsD(1.0), operations3, nullptr));
animation = Animation::Create(curve3.Pass(), 3, 3, Animation::TRANSFORM);
+ animation->set_affects_active_observers(false);
controller_impl->AddAnimation(animation.Pass());
- EXPECT_FALSE(controller_impl->MaximumTargetScale(&max_scale));
+ EXPECT_FALSE(controller_impl->MaximumTargetScale(
+ LayerAnimationController::ObserverType::PENDING, &max_scale));
+ EXPECT_TRUE(controller_impl->MaximumTargetScale(
+ LayerAnimationController::ObserverType::ACTIVE, &max_scale));
+ EXPECT_EQ(6.f, max_scale);
+
+ controller_impl->ActivateAnimations();
+ EXPECT_FALSE(controller_impl->MaximumTargetScale(
+ LayerAnimationController::ObserverType::PENDING, &max_scale));
+ EXPECT_FALSE(controller_impl->MaximumTargetScale(
+ LayerAnimationController::ObserverType::ACTIVE, &max_scale));
controller_impl->GetAnimationById(3)
->SetRunState(Animation::FINISHED, TicksFromSecondsF(0.0));
@@ -2167,7 +2296,11 @@ TEST(LayerAnimationControllerTest, MaximumTargetScale) {
// Only unfinished animations should be considered by
// MaximumTargetScale.
- EXPECT_TRUE(controller_impl->MaximumTargetScale(&max_scale));
+ EXPECT_TRUE(controller_impl->MaximumTargetScale(
+ LayerAnimationController::ObserverType::PENDING, &max_scale));
+ EXPECT_EQ(4.f, max_scale);
+ EXPECT_TRUE(controller_impl->MaximumTargetScale(
+ LayerAnimationController::ObserverType::ACTIVE, &max_scale));
EXPECT_EQ(4.f, max_scale);
}
@@ -2197,44 +2330,76 @@ TEST(LayerAnimationControllerTest, MaximumTargetScaleWithDirection) {
// NORMAL direction with positive playback rate.
animation->set_direction(Animation::DIRECTION_NORMAL);
- EXPECT_TRUE(controller_impl->MaximumTargetScale(&max_scale));
+ EXPECT_TRUE(controller_impl->MaximumTargetScale(
+ LayerAnimationController::ObserverType::PENDING, &max_scale));
+ EXPECT_EQ(6.f, max_scale);
+ EXPECT_TRUE(controller_impl->MaximumTargetScale(
+ LayerAnimationController::ObserverType::ACTIVE, &max_scale));
EXPECT_EQ(6.f, max_scale);
// ALTERNATE direction with positive playback rate.
animation->set_direction(Animation::DIRECTION_ALTERNATE);
- EXPECT_TRUE(controller_impl->MaximumTargetScale(&max_scale));
+ EXPECT_TRUE(controller_impl->MaximumTargetScale(
+ LayerAnimationController::ObserverType::PENDING, &max_scale));
+ EXPECT_EQ(6.f, max_scale);
+ EXPECT_TRUE(controller_impl->MaximumTargetScale(
+ LayerAnimationController::ObserverType::ACTIVE, &max_scale));
EXPECT_EQ(6.f, max_scale);
// REVERSE direction with positive playback rate.
animation->set_direction(Animation::DIRECTION_REVERSE);
- EXPECT_TRUE(controller_impl->MaximumTargetScale(&max_scale));
+ EXPECT_TRUE(controller_impl->MaximumTargetScale(
+ LayerAnimationController::ObserverType::PENDING, &max_scale));
+ EXPECT_EQ(3.f, max_scale);
+ EXPECT_TRUE(controller_impl->MaximumTargetScale(
+ LayerAnimationController::ObserverType::ACTIVE, &max_scale));
EXPECT_EQ(3.f, max_scale);
// ALTERNATE reverse direction.
animation->set_direction(Animation::DIRECTION_REVERSE);
- EXPECT_TRUE(controller_impl->MaximumTargetScale(&max_scale));
+ EXPECT_TRUE(controller_impl->MaximumTargetScale(
+ LayerAnimationController::ObserverType::PENDING, &max_scale));
+ EXPECT_EQ(3.f, max_scale);
+ EXPECT_TRUE(controller_impl->MaximumTargetScale(
+ LayerAnimationController::ObserverType::ACTIVE, &max_scale));
EXPECT_EQ(3.f, max_scale);
animation->set_playback_rate(-1.0);
// NORMAL direction with negative playback rate.
animation->set_direction(Animation::DIRECTION_NORMAL);
- EXPECT_TRUE(controller_impl->MaximumTargetScale(&max_scale));
+ EXPECT_TRUE(controller_impl->MaximumTargetScale(
+ LayerAnimationController::ObserverType::PENDING, &max_scale));
+ EXPECT_EQ(3.f, max_scale);
+ EXPECT_TRUE(controller_impl->MaximumTargetScale(
+ LayerAnimationController::ObserverType::ACTIVE, &max_scale));
EXPECT_EQ(3.f, max_scale);
// ALTERNATE direction with negative playback rate.
animation->set_direction(Animation::DIRECTION_ALTERNATE);
- EXPECT_TRUE(controller_impl->MaximumTargetScale(&max_scale));
+ EXPECT_TRUE(controller_impl->MaximumTargetScale(
+ LayerAnimationController::ObserverType::PENDING, &max_scale));
+ EXPECT_EQ(3.f, max_scale);
+ EXPECT_TRUE(controller_impl->MaximumTargetScale(
+ LayerAnimationController::ObserverType::ACTIVE, &max_scale));
EXPECT_EQ(3.f, max_scale);
// REVERSE direction with negative playback rate.
animation->set_direction(Animation::DIRECTION_REVERSE);
- EXPECT_TRUE(controller_impl->MaximumTargetScale(&max_scale));
+ EXPECT_TRUE(controller_impl->MaximumTargetScale(
+ LayerAnimationController::ObserverType::PENDING, &max_scale));
+ EXPECT_EQ(6.f, max_scale);
+ EXPECT_TRUE(controller_impl->MaximumTargetScale(
+ LayerAnimationController::ObserverType::ACTIVE, &max_scale));
EXPECT_EQ(6.f, max_scale);
// ALTERNATE reverse direction with negative playback rate.
animation->set_direction(Animation::DIRECTION_REVERSE);
- EXPECT_TRUE(controller_impl->MaximumTargetScale(&max_scale));
+ EXPECT_TRUE(controller_impl->MaximumTargetScale(
+ LayerAnimationController::ObserverType::PENDING, &max_scale));
+ EXPECT_EQ(6.f, max_scale);
+ EXPECT_TRUE(controller_impl->MaximumTargetScale(
+ LayerAnimationController::ObserverType::ACTIVE, &max_scale));
EXPECT_EQ(6.f, max_scale);
}
@@ -2355,6 +2520,124 @@ TEST(LayerAnimationControllerTest, ActivationBetweenAnimateAndUpdateState) {
EXPECT_EQ(0.75f, dummy_impl.opacity());
}
+TEST(LayerAnimationControllerTest,
+ ObserverNotifiedWhenTransformIsPotentiallyAnimatingChanges) {
+ AnimationEventsVector events;
+ FakeLayerAnimationValueObserver active_dummy_impl;
+ FakeInactiveLayerAnimationValueObserver pending_dummy_impl;
+ scoped_refptr<LayerAnimationController> controller_impl(
+ LayerAnimationController::Create(0));
+ controller_impl->AddValueObserver(&active_dummy_impl);
+ controller_impl->AddValueObserver(&pending_dummy_impl);
+ FakeLayerAnimationValueObserver dummy;
+ scoped_refptr<LayerAnimationController> controller(
+ LayerAnimationController::Create(0));
+ controller->AddValueObserver(&dummy);
+
+ EXPECT_FALSE(dummy.transform_is_animating());
+ EXPECT_FALSE(pending_dummy_impl.transform_is_animating());
+ EXPECT_FALSE(active_dummy_impl.transform_is_animating());
+
+ // Case 1: An animation that's allowed to run until its finish point.
+ AddAnimatedTransformToController(controller.get(), 1.0, 1, 1);
+ EXPECT_TRUE(dummy.transform_is_animating());
+
+ controller->PushAnimationUpdatesTo(controller_impl.get());
+ EXPECT_TRUE(pending_dummy_impl.transform_is_animating());
+ EXPECT_FALSE(active_dummy_impl.transform_is_animating());
+
+ controller_impl->ActivateAnimations();
+ EXPECT_TRUE(pending_dummy_impl.transform_is_animating());
+ EXPECT_TRUE(active_dummy_impl.transform_is_animating());
+
+ controller_impl->Animate(kInitialTickTime);
+ controller_impl->UpdateState(true, &events);
+
+ controller->NotifyAnimationStarted(events[0]);
+ events.clear();
+
+ // Finish the animation.
+ controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
+ controller->UpdateState(true, nullptr);
+ EXPECT_FALSE(dummy.transform_is_animating());
+
+ controller->PushAnimationUpdatesTo(controller_impl.get());
+
+ // controller_impl hasn't yet ticked at/past the end of the animation.
+ EXPECT_TRUE(pending_dummy_impl.transform_is_animating());
+ EXPECT_TRUE(active_dummy_impl.transform_is_animating());
+
+ controller_impl->Animate(kInitialTickTime +
+ TimeDelta::FromMilliseconds(1000));
+ controller_impl->UpdateState(true, &events);
+ EXPECT_FALSE(pending_dummy_impl.transform_is_animating());
+ EXPECT_FALSE(active_dummy_impl.transform_is_animating());
+
+ controller->NotifyAnimationFinished(events[0]);
+ events.clear();
+
+ // Case 2: An animation that's removed before it finishes.
+ int animation_id =
+ AddAnimatedTransformToController(controller.get(), 10.0, 2, 2);
+ EXPECT_TRUE(dummy.transform_is_animating());
+
+ controller->PushAnimationUpdatesTo(controller_impl.get());
+ EXPECT_TRUE(pending_dummy_impl.transform_is_animating());
+ EXPECT_FALSE(active_dummy_impl.transform_is_animating());
+
+ controller_impl->ActivateAnimations();
+ EXPECT_TRUE(pending_dummy_impl.transform_is_animating());
+ EXPECT_TRUE(active_dummy_impl.transform_is_animating());
+
+ controller_impl->Animate(kInitialTickTime +
+ TimeDelta::FromMilliseconds(2000));
+ controller_impl->UpdateState(true, &events);
+
+ controller->NotifyAnimationStarted(events[0]);
+ events.clear();
+
+ controller->RemoveAnimation(animation_id);
+ EXPECT_FALSE(dummy.transform_is_animating());
+
+ controller->PushAnimationUpdatesTo(controller_impl.get());
+ EXPECT_FALSE(pending_dummy_impl.transform_is_animating());
+ EXPECT_TRUE(active_dummy_impl.transform_is_animating());
+
+ controller_impl->ActivateAnimations();
+ EXPECT_FALSE(pending_dummy_impl.transform_is_animating());
+ EXPECT_FALSE(active_dummy_impl.transform_is_animating());
+
+ // Case 3: An animation that's aborted before it finishes.
+ animation_id = AddAnimatedTransformToController(controller.get(), 10.0, 3, 3);
+ EXPECT_TRUE(dummy.transform_is_animating());
+
+ controller->PushAnimationUpdatesTo(controller_impl.get());
+ EXPECT_TRUE(pending_dummy_impl.transform_is_animating());
+ EXPECT_FALSE(active_dummy_impl.transform_is_animating());
+
+ controller_impl->ActivateAnimations();
+ EXPECT_TRUE(pending_dummy_impl.transform_is_animating());
+ EXPECT_TRUE(active_dummy_impl.transform_is_animating());
+
+ controller_impl->Animate(kInitialTickTime +
+ TimeDelta::FromMilliseconds(3000));
+ controller_impl->UpdateState(true, &events);
+
+ controller->NotifyAnimationStarted(events[0]);
+ events.clear();
+
+ controller_impl->AbortAnimations(Animation::TRANSFORM);
+ EXPECT_FALSE(pending_dummy_impl.transform_is_animating());
+ EXPECT_FALSE(active_dummy_impl.transform_is_animating());
+
+ controller_impl->Animate(kInitialTickTime +
+ TimeDelta::FromMilliseconds(4000));
+ controller_impl->UpdateState(true, &events);
+
+ controller->NotifyAnimationAborted(events[0]);
+ EXPECT_FALSE(dummy.transform_is_animating());
+}
+
TEST(LayerAnimationControllerTest, ClippedOpacityValues) {
FakeLayerAnimationValueObserver dummy;
scoped_refptr<LayerAnimationController> controller(
@@ -2524,23 +2807,75 @@ TEST(LayerAnimationControllerTest, StartAnimationsAffectingDifferentObservers) {
EXPECT_EQ(1.f, dummy_impl.opacity());
}
-TEST(LayerAnimationControllerTest, TestIsAnimatingProperty) {
+TEST(LayerAnimationControllerTest, TestIsCurrentlyAnimatingProperty) {
FakeLayerAnimationValueObserver dummy;
scoped_refptr<LayerAnimationController> controller(
LayerAnimationController::Create(0));
controller->AddValueObserver(&dummy);
+ // Create an animation that initially affects only pending observers.
scoped_ptr<Animation> animation(CreateAnimation(
scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(),
1, Animation::OPACITY));
+ animation->set_affects_active_observers(false);
+
controller->AddAnimation(animation.Pass());
controller->Animate(kInitialTickTime);
- EXPECT_TRUE(controller->IsAnimatingProperty(Animation::OPACITY));
+ EXPECT_TRUE(controller->IsCurrentlyAnimatingProperty(
+ Animation::OPACITY, LayerAnimationController::ObserverType::PENDING));
+ EXPECT_FALSE(controller->IsCurrentlyAnimatingProperty(
+ Animation::OPACITY, LayerAnimationController::ObserverType::ACTIVE));
controller->UpdateState(true, nullptr);
EXPECT_TRUE(controller->HasActiveAnimation());
- EXPECT_TRUE(controller->IsAnimatingProperty(Animation::OPACITY));
- EXPECT_FALSE(controller->IsAnimatingProperty(Animation::FILTER));
+
+ EXPECT_TRUE(controller->IsCurrentlyAnimatingProperty(
+ Animation::OPACITY, LayerAnimationController::ObserverType::PENDING));
+ EXPECT_FALSE(controller->IsCurrentlyAnimatingProperty(
+ Animation::OPACITY, LayerAnimationController::ObserverType::ACTIVE));
+ EXPECT_FALSE(controller->IsCurrentlyAnimatingProperty(
+ Animation::FILTER, LayerAnimationController::ObserverType::PENDING));
+ EXPECT_FALSE(controller->IsCurrentlyAnimatingProperty(
+ Animation::FILTER, LayerAnimationController::ObserverType::ACTIVE));
+
+ controller->ActivateAnimations();
+
+ EXPECT_TRUE(controller->IsCurrentlyAnimatingProperty(
+ Animation::OPACITY, LayerAnimationController::ObserverType::PENDING));
+ EXPECT_TRUE(controller->IsCurrentlyAnimatingProperty(
+ Animation::OPACITY, LayerAnimationController::ObserverType::ACTIVE));
+ EXPECT_FALSE(controller->IsCurrentlyAnimatingProperty(
+ Animation::FILTER, LayerAnimationController::ObserverType::PENDING));
+ EXPECT_FALSE(controller->IsCurrentlyAnimatingProperty(
+ Animation::FILTER, LayerAnimationController::ObserverType::ACTIVE));
+
+ controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(10));
+ controller->UpdateState(true, nullptr);
+
+ EXPECT_TRUE(controller->IsCurrentlyAnimatingProperty(
+ Animation::OPACITY, LayerAnimationController::ObserverType::PENDING));
+ EXPECT_TRUE(controller->IsCurrentlyAnimatingProperty(
+ Animation::OPACITY, LayerAnimationController::ObserverType::ACTIVE));
+ EXPECT_FALSE(controller->IsCurrentlyAnimatingProperty(
+ Animation::FILTER, LayerAnimationController::ObserverType::PENDING));
+ EXPECT_FALSE(controller->IsCurrentlyAnimatingProperty(
+ Animation::FILTER, LayerAnimationController::ObserverType::ACTIVE));
+
EXPECT_EQ(0.f, dummy.opacity());
+
+ // Tick past the end of the animation.
+ controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1100));
+ controller->UpdateState(true, nullptr);
+
+ EXPECT_FALSE(controller->IsCurrentlyAnimatingProperty(
+ Animation::OPACITY, LayerAnimationController::ObserverType::PENDING));
+ EXPECT_FALSE(controller->IsCurrentlyAnimatingProperty(
+ Animation::OPACITY, LayerAnimationController::ObserverType::ACTIVE));
+ EXPECT_FALSE(controller->IsCurrentlyAnimatingProperty(
+ Animation::FILTER, LayerAnimationController::ObserverType::PENDING));
+ EXPECT_FALSE(controller->IsCurrentlyAnimatingProperty(
+ Animation::FILTER, LayerAnimationController::ObserverType::ACTIVE));
+
+ EXPECT_EQ(1.f, dummy.opacity());
}
TEST(LayerAnimationControllerTest, TestIsAnimatingPropertyTimeOffsetFillMode) {
@@ -2549,23 +2884,79 @@ TEST(LayerAnimationControllerTest, TestIsAnimatingPropertyTimeOffsetFillMode) {
LayerAnimationController::Create(0));
controller->AddValueObserver(&dummy);
+ // Create an animation that initially affects only pending observers, and has
+ // a start delay of 2 seconds.
scoped_ptr<Animation> animation(CreateAnimation(
scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(),
1, Animation::OPACITY));
animation->set_fill_mode(Animation::FILL_MODE_NONE);
animation->set_time_offset(TimeDelta::FromMilliseconds(-2000));
+ animation->set_affects_active_observers(false);
+
controller->AddAnimation(animation.Pass());
controller->Animate(kInitialTickTime);
- controller->UpdateState(true, nullptr);
- EXPECT_FALSE(controller->IsAnimatingProperty(Animation::OPACITY));
+
+ // Since the animation has a start delay, the observers it affects have a
+ // potentially running transform animation but aren't currently animating
+ // transform.
+ EXPECT_TRUE(controller->IsPotentiallyAnimatingProperty(
+ Animation::OPACITY, LayerAnimationController::ObserverType::PENDING));
+ EXPECT_FALSE(controller->IsPotentiallyAnimatingProperty(
+ Animation::OPACITY, LayerAnimationController::ObserverType::ACTIVE));
+ EXPECT_FALSE(controller->IsCurrentlyAnimatingProperty(
+ Animation::OPACITY, LayerAnimationController::ObserverType::PENDING));
+ EXPECT_FALSE(controller->IsCurrentlyAnimatingProperty(
+ Animation::OPACITY, LayerAnimationController::ObserverType::ACTIVE));
+ EXPECT_TRUE(controller->HasActiveAnimation());
+ EXPECT_FALSE(controller->IsPotentiallyAnimatingProperty(
+ Animation::FILTER, LayerAnimationController::ObserverType::PENDING));
+ EXPECT_FALSE(controller->IsPotentiallyAnimatingProperty(
+ Animation::FILTER, LayerAnimationController::ObserverType::ACTIVE));
+
+ controller->ActivateAnimations();
+
+ EXPECT_TRUE(controller->IsPotentiallyAnimatingProperty(
+ Animation::OPACITY, LayerAnimationController::ObserverType::PENDING));
+ EXPECT_TRUE(controller->IsPotentiallyAnimatingProperty(
+ Animation::OPACITY, LayerAnimationController::ObserverType::ACTIVE));
+ EXPECT_FALSE(controller->IsCurrentlyAnimatingProperty(
+ Animation::OPACITY, LayerAnimationController::ObserverType::PENDING));
+ EXPECT_FALSE(controller->IsCurrentlyAnimatingProperty(
+ Animation::OPACITY, LayerAnimationController::ObserverType::ACTIVE));
EXPECT_TRUE(controller->HasActiveAnimation());
- EXPECT_FALSE(controller->IsAnimatingProperty(Animation::OPACITY));
- EXPECT_FALSE(controller->IsAnimatingProperty(Animation::FILTER));
+ EXPECT_FALSE(controller->IsPotentiallyAnimatingProperty(
+ Animation::FILTER, LayerAnimationController::ObserverType::PENDING));
+ EXPECT_FALSE(controller->IsPotentiallyAnimatingProperty(
+ Animation::FILTER, LayerAnimationController::ObserverType::ACTIVE));
+ controller->UpdateState(true, nullptr);
+
+ // Tick past the start delay.
controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(2000));
controller->UpdateState(true, nullptr);
- EXPECT_TRUE(controller->IsAnimatingProperty(Animation::OPACITY));
+ EXPECT_TRUE(controller->IsPotentiallyAnimatingProperty(
+ Animation::OPACITY, LayerAnimationController::ObserverType::PENDING));
+ EXPECT_TRUE(controller->IsPotentiallyAnimatingProperty(
+ Animation::OPACITY, LayerAnimationController::ObserverType::ACTIVE));
+ EXPECT_TRUE(controller->IsCurrentlyAnimatingProperty(
+ Animation::OPACITY, LayerAnimationController::ObserverType::PENDING));
+ EXPECT_TRUE(controller->IsCurrentlyAnimatingProperty(
+ Animation::OPACITY, LayerAnimationController::ObserverType::ACTIVE));
+
+ // After the animaton finishes, the observers it affects have neither a
+ // potentially running transform animation nor a currently running transform
+ // animation.
+ controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(4000));
+ controller->UpdateState(true, nullptr);
+ EXPECT_FALSE(controller->IsPotentiallyAnimatingProperty(
+ Animation::OPACITY, LayerAnimationController::ObserverType::PENDING));
+ EXPECT_FALSE(controller->IsPotentiallyAnimatingProperty(
+ Animation::OPACITY, LayerAnimationController::ObserverType::ACTIVE));
+ EXPECT_FALSE(controller->IsCurrentlyAnimatingProperty(
+ Animation::OPACITY, LayerAnimationController::ObserverType::PENDING));
+ EXPECT_FALSE(controller->IsCurrentlyAnimatingProperty(
+ Animation::OPACITY, LayerAnimationController::ObserverType::ACTIVE));
}
} // namespace
diff --git a/chromium/cc/animation/layer_animation_value_observer.h b/chromium/cc/animation/layer_animation_value_observer.h
index fb9901d7514..092b53b0b9d 100644
--- a/chromium/cc/animation/layer_animation_value_observer.h
+++ b/chromium/cc/animation/layer_animation_value_observer.h
@@ -26,6 +26,7 @@ class CC_EXPORT LayerAnimationValueObserver {
virtual void OnScrollOffsetAnimated(
const gfx::ScrollOffset& scroll_offset) = 0;
virtual void OnAnimationWaitingForDeletion() = 0;
+ virtual void OnTransformIsPotentiallyAnimatingChanged(bool is_animating) = 0;
virtual bool IsActive() const = 0;
};
diff --git a/chromium/cc/animation/scrollbar_animation_controller_linear_fade.cc b/chromium/cc/animation/scrollbar_animation_controller_linear_fade.cc
index d1049bda1cb..72fdd584960 100644
--- a/chromium/cc/animation/scrollbar_animation_controller_linear_fade.cc
+++ b/chromium/cc/animation/scrollbar_animation_controller_linear_fade.cc
@@ -62,7 +62,8 @@ void ScrollbarAnimationControllerLinearFade::ApplyOpacityToScrollbars(
ScrollbarLayerImplBase* scrollbar = *it;
if (scrollbar->is_overlay_scrollbar())
- scrollbar->SetOpacity(scrollbar->CanScrollOrientation() ? opacity : 0);
+ scrollbar->OnOpacityAnimated(scrollbar->CanScrollOrientation() ? opacity
+ : 0);
}
}
diff --git a/chromium/cc/animation/scrollbar_animation_controller_thinning.cc b/chromium/cc/animation/scrollbar_animation_controller_thinning.cc
index af6987e0e0b..6ced8098224 100644
--- a/chromium/cc/animation/scrollbar_animation_controller_thinning.cc
+++ b/chromium/cc/animation/scrollbar_animation_controller_thinning.cc
@@ -148,7 +148,7 @@ void ScrollbarAnimationControllerThinning::ApplyOpacityAndThumbThicknessScale(
? AdjustScale(opacity, scrollbar->opacity(), opacity_change_)
: 0;
- scrollbar->SetOpacity(effectiveOpacity);
+ scrollbar->OnOpacityAnimated(effectiveOpacity);
scrollbar->SetThumbThicknessScaleFactor(AdjustScale(
thumb_thickness_scale, scrollbar->thumb_thickness_scale_factor(),
thickness_change_));
diff --git a/chromium/cc/animation/transform_operation.cc b/chromium/cc/animation/transform_operation.cc
index e487921cdb4..465429df4b6 100644
--- a/chromium/cc/animation/transform_operation.cc
+++ b/chromium/cc/animation/transform_operation.cc
@@ -41,7 +41,7 @@ static bool ShareSameAxis(const TransformOperation* from,
if (IsOperationIdentity(from) && IsOperationIdentity(to))
return false;
- if (!from && !IsOperationIdentity(to)) {
+ if (IsOperationIdentity(from) && !IsOperationIdentity(to)) {
*axis_x = to->rotate.axis.x;
*axis_y = to->rotate.axis.y;
*axis_z = to->rotate.axis.z;
@@ -49,7 +49,7 @@ static bool ShareSameAxis(const TransformOperation* from,
return true;
}
- if (!IsOperationIdentity(from) && !to) {
+ if (!IsOperationIdentity(from) && IsOperationIdentity(to)) {
*axis_x = from->rotate.axis.x;
*axis_y = from->rotate.axis.y;
*axis_z = from->rotate.axis.z;
@@ -157,8 +157,8 @@ bool TransformOperation::BlendTransformOperations(
SkMScalar from_y = IsOperationIdentity(from) ? 0 : from->skew.y;
SkMScalar to_x = IsOperationIdentity(to) ? 0 : to->skew.x;
SkMScalar to_y = IsOperationIdentity(to) ? 0 : to->skew.y;
- result->SkewX(BlendSkMScalars(from_x, to_x, progress));
- result->SkewY(BlendSkMScalars(from_y, to_y, progress));
+ result->Skew(BlendSkMScalars(from_x, to_x, progress),
+ BlendSkMScalars(from_y, to_y, progress));
break;
}
case TransformOperation::TRANSFORM_OPERATION_PERSPECTIVE: {
diff --git a/chromium/cc/animation/transform_operations.cc b/chromium/cc/animation/transform_operations.cc
index 6631a2a980b..29a3d90626b 100644
--- a/chromium/cc/animation/transform_operations.cc
+++ b/chromium/cc/animation/transform_operations.cc
@@ -224,8 +224,7 @@ void TransformOperations::AppendScale(SkMScalar x, SkMScalar y, SkMScalar z) {
void TransformOperations::AppendSkew(SkMScalar x, SkMScalar y) {
TransformOperation to_add;
- to_add.matrix.SkewX(x);
- to_add.matrix.SkewY(y);
+ to_add.matrix.Skew(x, y);
to_add.type = TransformOperation::TRANSFORM_OPERATION_SKEW;
to_add.skew.x = x;
to_add.skew.y = y;
@@ -277,9 +276,10 @@ bool TransformOperations::BlendInternal(const TransformOperations& from,
for (size_t i = 0; i < num_operations; ++i) {
gfx::Transform blended;
if (!TransformOperation::BlendTransformOperations(
- from.operations_.size() <= i ? 0 : &from.operations_[i],
- operations_.size() <= i ? 0 : &operations_[i], progress,
- &blended))
+ from_identity ? 0 : &from.operations_[i],
+ to_identity ? 0 : &operations_[i],
+ progress,
+ &blended))
return false;
result->PreconcatTransform(blended);
}
diff --git a/chromium/cc/animation/transform_operations_unittest.cc b/chromium/cc/animation/transform_operations_unittest.cc
index a5cf7ec9619..572ab47ec7a 100644
--- a/chromium/cc/animation/transform_operations_unittest.cc
+++ b/chromium/cc/animation/transform_operations_unittest.cc
@@ -209,8 +209,7 @@ TEST(TransformOperationTest, ApplySkew) {
TransformOperations operations;
operations.AppendSkew(x, y);
gfx::Transform expected;
- expected.SkewX(x);
- expected.SkewY(y);
+ expected.Skew(x, y);
EXPECT_TRANSFORMATION_MATRIX_EQ(expected, operations.Apply());
}
@@ -441,7 +440,7 @@ TEST(TransformOperationTest, LargeRotationsWithDifferentAxes) {
expected, operations_to.Blend(operations_from, progress));
}
-TEST(TransformOperationTest, RotationWithSlerpFromZeroDeg) {
+TEST(TransformOperationTest, RotationFromZeroDegDifferentAxes) {
TransformOperations operations_from;
operations_from.AppendRotate(0, 0, 1, 0);
@@ -449,20 +448,13 @@ TEST(TransformOperationTest, RotationWithSlerpFromZeroDeg) {
operations_to.AppendRotate(0, 1, 0, 450);
SkMScalar progress = 0.5f;
- gfx::Transform matrix_from;
- matrix_from.RotateAbout(gfx::Vector3dF(0, 0, 1), 0);
-
- gfx::Transform matrix_to;
- matrix_to.RotateAbout(gfx::Vector3dF(0, 1, 0), 90);
-
- gfx::Transform expected = matrix_to;
- expected.Blend(matrix_from, progress);
-
+ gfx::Transform expected;
+ expected.RotateAbout(gfx::Vector3dF(0, 1, 0), 225);
EXPECT_TRANSFORMATION_MATRIX_EQ(
expected, operations_to.Blend(operations_from, progress));
}
-TEST(TransformOperationTest, RotationWithoutSlerpFromZeroDeg) {
+TEST(TransformOperationTest, RotationFromZeroDegSameAxes) {
TransformOperations operations_from;
operations_from.AppendRotate(0, 0, 1, 0);
@@ -472,7 +464,34 @@ TEST(TransformOperationTest, RotationWithoutSlerpFromZeroDeg) {
SkMScalar progress = 0.5f;
gfx::Transform expected;
expected.RotateAbout(gfx::Vector3dF(0, 0, 1), 225);
+ EXPECT_TRANSFORMATION_MATRIX_EQ(
+ expected, operations_to.Blend(operations_from, progress));
+}
+
+TEST(TransformOperationTest, RotationToZeroDegDifferentAxes) {
+ TransformOperations operations_from;
+ operations_from.AppendRotate(0, 1, 0, 450);
+
+ TransformOperations operations_to;
+ operations_to.AppendRotate(0, 0, 1, 0);
+
+ SkMScalar progress = 0.5f;
+ gfx::Transform expected;
+ expected.RotateAbout(gfx::Vector3dF(0, 1, 0), 225);
+ EXPECT_TRANSFORMATION_MATRIX_EQ(
+ expected, operations_to.Blend(operations_from, progress));
+}
+TEST(TransformOperationTest, RotationToZeroDegSameAxes) {
+ TransformOperations operations_from;
+ operations_from.AppendRotate(0, 0, 1, 450);
+
+ TransformOperations operations_to;
+ operations_to.AppendRotate(0, 0, 1, 0);
+
+ SkMScalar progress = 0.5f;
+ gfx::Transform expected;
+ expected.RotateAbout(gfx::Vector3dF(0, 0, 1), 225);
EXPECT_TRANSFORMATION_MATRIX_EQ(
expected, operations_to.Blend(operations_from, progress));
}
@@ -588,8 +607,7 @@ TEST(TransformOperationTest, BlendSkewFromEmpty) {
SkMScalar progress = 0.5f;
gfx::Transform expected;
- expected.SkewX(1);
- expected.SkewY(1);
+ expected.Skew(1, 1);
EXPECT_TRANSFORMATION_MATRIX_EQ(expected,
operations.Blend(empty_operation, progress));
@@ -597,8 +615,7 @@ TEST(TransformOperationTest, BlendSkewFromEmpty) {
progress = -0.5f;
expected.MakeIdentity();
- expected.SkewX(-1);
- expected.SkewY(-1);
+ expected.Skew(-1, -1);
EXPECT_TRANSFORMATION_MATRIX_EQ(expected,
operations.Blend(empty_operation, progress));
@@ -606,8 +623,7 @@ TEST(TransformOperationTest, BlendSkewFromEmpty) {
progress = 1.5f;
expected.MakeIdentity();
- expected.SkewX(3);
- expected.SkewY(3);
+ expected.Skew(3, 3);
EXPECT_TRANSFORMATION_MATRIX_EQ(expected,
operations.Blend(empty_operation, progress));
@@ -694,8 +710,7 @@ TEST(TransformOperationTest, BlendSkewToEmpty) {
SkMScalar progress = 0.5f;
gfx::Transform expected;
- expected.SkewX(1);
- expected.SkewY(1);
+ expected.Skew(1, 1);
EXPECT_TRANSFORMATION_MATRIX_EQ(expected,
empty_operation.Blend(operations, progress));
diff --git a/chromium/cc/base/BUILD.gn b/chromium/cc/base/BUILD.gn
index 98a5d4ad1e6..c6dc603c836 100644
--- a/chromium/cc/base/BUILD.gn
+++ b/chromium/cc/base/BUILD.gn
@@ -13,19 +13,22 @@ source_set("base") {
"histograms.h",
"invalidation_region.cc",
"invalidation_region.h",
- "list_container.cc",
"list_container.h",
+ "list_container_helper.cc",
+ "list_container_helper.h",
"math_util.cc",
"math_util.h",
+ "random_access_list_container.h",
"region.cc",
"region.h",
"resource_id.h",
"rolling_time_delta_history.cc",
"rolling_time_delta_history.h",
+ "rtree.cc",
+ "rtree.h",
"scoped_ptr_algorithm.h",
"scoped_ptr_deque.h",
"scoped_ptr_vector.h",
- "sidecar_list_container.h",
"simple_enclosed_region.cc",
"simple_enclosed_region.h",
"switches.cc",
@@ -49,7 +52,7 @@ source_set("base") {
defines = [ "CC_IMPLEMENTATION=1" ]
if (!is_debug && (is_win || is_android)) {
- configs -= [ "//build/config/compiler:optimize" ]
+ configs -= [ "//build/config/compiler:default_optimization" ]
configs += [ "//build/config/compiler:optimize_max" ]
}
}
diff --git a/chromium/cc/base/float_quad_unittest.cc b/chromium/cc/base/float_quad_unittest.cc
index 6d9ce02f862..64c448c0d5a 100644
--- a/chromium/cc/base/float_quad_unittest.cc
+++ b/chromium/cc/base/float_quad_unittest.cc
@@ -18,8 +18,8 @@ TEST(FloatQuadTest, IsRectilinearTest) {
rectilinear_trans[1].Rotate(90.f);
rectilinear_trans[2].Rotate(180.f);
rectilinear_trans[3].Rotate(270.f);
- rectilinear_trans[4].SkewX(0.00000000001f);
- rectilinear_trans[5].SkewY(0.00000000001f);
+ rectilinear_trans[4].Skew(0.00000000001f, 0.0f);
+ rectilinear_trans[5].Skew(0.0f, 0.00000000001f);
rectilinear_trans[6].Scale(0.00001f, 0.00001f);
rectilinear_trans[6].Rotate(180.f);
rectilinear_trans[7].Scale(100000.f, 100000.f);
@@ -46,8 +46,8 @@ TEST(FloatQuadTest, IsRectilinearTest) {
non_rectilinear_trans[5].Rotate(180.00001f);
non_rectilinear_trans[6].Rotate(269.9999f);
non_rectilinear_trans[7].Rotate(270.0001f);
- non_rectilinear_trans[8].SkewX(0.00001f);
- non_rectilinear_trans[9].SkewY(0.00001f);
+ non_rectilinear_trans[8].Skew(0.00001f, 0.0f);
+ non_rectilinear_trans[9].Skew(0.0f, 0.00001f);
for (int i = 0; i < kNumNonRectilinear; ++i) {
bool clipped = false;
diff --git a/chromium/cc/base/histograms.cc b/chromium/cc/base/histograms.cc
index 9fe1515bc2a..ba6f4f66794 100644
--- a/chromium/cc/base/histograms.cc
+++ b/chromium/cc/base/histograms.cc
@@ -6,12 +6,51 @@
#include <algorithm>
#include <cmath>
+#include <cstring>
#include <limits>
+#include "base/lazy_instance.h"
+#include "base/logging.h"
#include "base/numerics/safe_conversions.h"
+#include "base/synchronization/lock.h"
namespace cc {
+// Global data tracking the client name that was set.
+// Both of these variables are protected by the lock.
+static base::LazyInstance<base::Lock>::Leaky g_client_name_lock =
+ LAZY_INSTANCE_INITIALIZER;
+static const char* g_client_name = nullptr;
+static bool g_multiple_client_names_set = false;
+
+void SetClientNameForMetrics(const char* client_name) {
+ base::AutoLock auto_lock(g_client_name_lock.Get());
+
+ // Only warn once.
+ if (g_multiple_client_names_set)
+ return;
+
+ // If a different name is set, return nullptr from now on and log a warning.
+ const char* old_client_name = g_client_name;
+ if (old_client_name && strcmp(old_client_name, client_name)) {
+ g_client_name = nullptr;
+ g_multiple_client_names_set = true;
+ LOG(WARNING) << "Started multiple compositor clients (" << old_client_name
+ << ", " << client_name
+ << ") in one process. Some metrics will be disabled.";
+ return;
+ }
+
+ // If the client name is being set for the first time, store it.
+ if (!old_client_name)
+ g_client_name = client_name;
+}
+
+const char* GetClientNameForMetrics() {
+ base::AutoLock auto_lock(g_client_name_lock.Get());
+ return g_client_name;
+}
+
// Minimum elapsed time of 1us to limit weighting of fast calls.
static const int64 kMinimumTimeMicroseconds = 1;
diff --git a/chromium/cc/base/histograms.h b/chromium/cc/base/histograms.h
index 0c8a2bc8532..8c8b4672a09 100644
--- a/chromium/cc/base/histograms.h
+++ b/chromium/cc/base/histograms.h
@@ -9,44 +9,69 @@
#include "base/metrics/histogram_base.h"
#include "base/metrics/histogram_macros.h"
#include "base/numerics/safe_math.h"
+#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "base/timer/elapsed_timer.h"
#include "cc/base/cc_export.h"
namespace cc {
+// Supplies a client name to be inserted into histogram names.
+// These are known so far: Renderer, Browser
+//
+// We currently assume that there is only one distinct client per process.
+// Not thread-safe. If called multiple times, warns and skips metrics.
+CC_EXPORT void SetClientNameForMetrics(const char* client_name);
+
+// Returns the client name, for use by applicable cc metrics code.
+// May return null, in which case no clients, or at least two clients, set the
+// client name, and these metrics should be omitted.
+//
+// This method guarantees that it will never return two distinct non-null
+// values over the lifetime of the process.
+const char* GetClientNameForMetrics();
+
// Emits UMA histogram trackers for time spent as well as area (in pixels)
// processed per unit time. Time is measured in microseconds, and work in
-// pixels per millisecond.
+// pixels per millisecond. Histogram name should include a %s to grab the client
+// name.
//
// Usage:
// // Outside of a method, perhaps in a namespace.
-// DEFINE_SCOPED_UMA_HISTOGRAM_AREA_TIMER(ScopedReticulateSplinesTimer,
-// "ReticulateSplinesUs",
-// "ReticulateSplinesPixelsPerMs");
+// DEFINE_SCOPED_UMA_HISTOGRAM_AREA_TIMER(
+// ScopedReticulateSplinesTimer,
+// "Compositing.%s.ReticulateSplinesUs",
+// "Compositing.%s.ReticulateSplinesPixelsPerMs");
//
// // Inside a method.
// ScopedReticulateSplinesTimer timer;
// timer.AddArea(some_rect.size().GetArea());
-#define DEFINE_SCOPED_UMA_HISTOGRAM_AREA_TIMER(class_name, time_histogram, \
- area_histogram) \
- class class_name : public ::cc::ScopedUMAHistogramAreaTimerBase { \
- public: \
- ~class_name(); \
- }; \
- class_name::~class_name() { \
- Sample time_sample; \
- Sample area_sample; \
- if (GetHistogramValues(&time_sample, &area_sample)) { \
- UMA_HISTOGRAM_COUNTS(time_histogram, time_sample); \
- UMA_HISTOGRAM_COUNTS(area_histogram, area_sample); \
- } \
+//
+#define DEFINE_SCOPED_UMA_HISTOGRAM_AREA_TIMER(class_name, time_histogram, \
+ area_histogram) \
+ class class_name : public ::cc::ScopedUMAHistogramAreaTimerBase { \
+ public: \
+ ~class_name(); \
+ }; \
+ class_name::~class_name() { \
+ Sample time_sample; \
+ Sample area_sample; \
+ const char* client_name = ::cc::GetClientNameForMetrics(); \
+ if (client_name && GetHistogramValues(&time_sample, &area_sample)) { \
+ /* GetClientNameForMetrics only returns one non-null value over */ \
+ /* the lifetime of the process, so these histogram names are */ \
+ /* runtime constant. */ \
+ UMA_HISTOGRAM_COUNTS(base::StringPrintf(time_histogram, client_name), \
+ time_sample); \
+ UMA_HISTOGRAM_COUNTS(base::StringPrintf(area_histogram, client_name), \
+ area_sample); \
+ } \
}
class CC_EXPORT ScopedUMAHistogramAreaTimerBase {
public:
- void AddArea(int area) { area_ += area; }
- void SetArea(int area) { area_ = area; }
+ void AddArea(const base::CheckedNumeric<int>& area) { area_ += area; }
+ void SetArea(const base::CheckedNumeric<int>& area) { area_ = area; }
protected:
using Sample = base::HistogramBase::Sample;
diff --git a/chromium/cc/base/list_container.h b/chromium/cc/base/list_container.h
index ae7afa92e5b..d5907407c0a 100644
--- a/chromium/cc/base/list_container.h
+++ b/chromium/cc/base/list_container.h
@@ -9,6 +9,7 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "cc/base/cc_export.h"
+#include "cc/base/list_container_helper.h"
namespace cc {
@@ -20,188 +21,27 @@ namespace cc {
// contain SharedQuadState or DrawQuad. Since the size of each DrawQuad varies,
// to hold DrawQuads, the allocations size of each element in this class is
// LargestDrawQuadSize while BaseElementType is DrawQuad.
-
-// Base class for non-templated logic. All methods are protected, and only
-// exposed by ListContainer<BaseElementType>.
-// For usage, see comments in ListContainer.
-class CC_EXPORT ListContainerBase {
- protected:
- explicit ListContainerBase(size_t max_size_for_derived_class);
- ListContainerBase(size_t max_size_for_derived_class,
- size_t num_of_elements_to_reserve_for);
- ~ListContainerBase();
-
- // This class deals only with char* and void*. It does allocation and passing
- // out raw pointers, as well as memory deallocation when being destroyed.
- class ListContainerCharAllocator;
-
- // This class points to a certain position inside memory of
- // ListContainerCharAllocator. It is a base class for ListContainer iterators.
- struct CC_EXPORT PositionInListContainerCharAllocator {
- ListContainerCharAllocator* ptr_to_container;
- size_t vector_index;
- char* item_iterator;
-
- PositionInListContainerCharAllocator(
- const PositionInListContainerCharAllocator& other);
-
- PositionInListContainerCharAllocator(ListContainerCharAllocator* container,
- size_t vector_ind,
- char* item_iter);
-
- bool operator==(const PositionInListContainerCharAllocator& other) const;
- bool operator!=(const PositionInListContainerCharAllocator& other) const;
-
- PositionInListContainerCharAllocator Increment();
- PositionInListContainerCharAllocator ReverseIncrement();
- };
-
- // Iterator classes that can be used to access data.
- /////////////////////////////////////////////////////////////////
- class CC_EXPORT Iterator : public PositionInListContainerCharAllocator {
- // This class is only defined to forward iterate through
- // ListContainerCharAllocator.
- public:
- Iterator(ListContainerCharAllocator* container,
- size_t vector_ind,
- char* item_iter,
- size_t index);
- ~Iterator();
-
- size_t index() const;
-
- protected:
- // This is used to track how many increment has happened since begin(). It
- // is used to avoid double increment at places an index reference is
- // needed. For iterator this means begin() corresponds to index 0 and end()
- // corresponds to index |size|.
- size_t index_;
- };
-
- class CC_EXPORT ConstIterator : public PositionInListContainerCharAllocator {
- // This class is only defined to forward iterate through
- // ListContainerCharAllocator.
- public:
- ConstIterator(ListContainerCharAllocator* container,
- size_t vector_ind,
- char* item_iter,
- size_t index);
- ConstIterator(const Iterator& other); // NOLINT
- ~ConstIterator();
-
- size_t index() const;
-
- protected:
- // This is used to track how many increment has happened since begin(). It
- // is used to avoid double increment at places an index reference is
- // needed. For iterator this means begin() corresponds to index 0 and end()
- // corresponds to index |size|.
- size_t index_;
- };
-
- class CC_EXPORT ReverseIterator
- : public PositionInListContainerCharAllocator {
- // This class is only defined to reverse iterate through
- // ListContainerCharAllocator.
- public:
- ReverseIterator(ListContainerCharAllocator* container,
- size_t vector_ind,
- char* item_iter,
- size_t index);
- ~ReverseIterator();
-
- size_t index() const;
-
- protected:
- // This is used to track how many increment has happened since rbegin(). It
- // is used to avoid double increment at places an index reference is
- // needed. For reverse iterator this means rbegin() corresponds to index 0
- // and rend() corresponds to index |size|.
- size_t index_;
- };
-
- class CC_EXPORT ConstReverseIterator
- : public PositionInListContainerCharAllocator {
- // This class is only defined to reverse iterate through
- // ListContainerCharAllocator.
- public:
- ConstReverseIterator(ListContainerCharAllocator* container,
- size_t vector_ind,
- char* item_iter,
- size_t index);
- ConstReverseIterator(const ReverseIterator& other); // NOLINT
- ~ConstReverseIterator();
-
- size_t index() const;
-
- protected:
- // This is used to track how many increment has happened since rbegin(). It
- // is used to avoid double increment at places an index reference is
- // needed. For reverse iterator this means rbegin() corresponds to index 0
- // and rend() corresponds to index |size|.
- size_t index_;
- };
-
- // Unlike the ListContainer methods, these do not invoke element destructors.
- void RemoveLast();
- void EraseAndInvalidateAllPointers(Iterator position);
-
- ConstReverseIterator crbegin() const;
- ConstReverseIterator crend() const;
- ReverseIterator rbegin();
- ReverseIterator rend();
- ConstIterator cbegin() const;
- ConstIterator cend() const;
- Iterator begin();
- Iterator end();
-
- Iterator IteratorAt(size_t index);
- ConstIterator IteratorAt(size_t index) const;
-
- size_t size() const;
- bool empty() const;
-
- size_t MaxSizeForDerivedClass() const;
-
- size_t GetCapacityInBytes() const;
-
- // Unlike the ListContainer method, this one does not invoke element
- // destructors.
- void clear();
-
- size_t AvailableSizeWithoutAnotherAllocationForTesting() const;
-
- // Hands out memory location for an element at the end of data structure.
- void* Allocate(size_t size_of_actual_element_in_bytes);
-
- scoped_ptr<ListContainerCharAllocator> data_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ListContainerBase);
-};
-
template <class BaseElementType>
-class ListContainer : public ListContainerBase {
+class ListContainer {
public:
// BaseElementType is the type of raw pointers this class hands out; however,
// its derived classes might require different memory sizes.
// max_size_for_derived_class the largest memory size required for all the
// derived classes to use for allocation.
explicit ListContainer(size_t max_size_for_derived_class)
- : ListContainerBase(max_size_for_derived_class) {}
+ : helper_(max_size_for_derived_class) {}
// This constructor omits input variable for max_size_for_derived_class. This
// is used when there is no derived classes from BaseElementType we need to
// worry about, and allocation size is just sizeof(BaseElementType).
- ListContainer() : ListContainerBase(sizeof(BaseElementType)) {}
+ ListContainer() : helper_(sizeof(BaseElementType)) {}
// This constructor reserves the requested memory up front so only single
// allocation is needed. When num_of_elements_to_reserve_for is zero, use the
// default size.
ListContainer(size_t max_size_for_derived_class,
size_t num_of_elements_to_reserve_for)
- : ListContainerBase(max_size_for_derived_class,
- num_of_elements_to_reserve_for) {}
+ : helper_(max_size_for_derived_class, num_of_elements_to_reserve_for) {}
~ListContainer() {
for (Iterator i = begin(); i != end(); ++i) {
@@ -219,40 +59,36 @@ class ListContainer : public ListContainerBase {
void RemoveLast() {
DCHECK(!empty());
back()->~BaseElementType();
- ListContainerBase::RemoveLast();
+ helper_.RemoveLast();
}
// When called, all raw pointers that have been handed out are no longer
// valid. Use with caution.
+ // Returns a valid Iterator pointing to the element after the erased element.
// This function does not deallocate memory.
- void EraseAndInvalidateAllPointers(Iterator position) {
+ Iterator EraseAndInvalidateAllPointers(Iterator position) {
BaseElementType* item = *position;
item->~BaseElementType();
- ListContainerBase::EraseAndInvalidateAllPointers(position);
+ helper_.EraseAndInvalidateAllPointers(&position);
+ return empty() ? end() : position;
}
ConstReverseIterator crbegin() const {
- return ConstReverseIterator(ListContainerBase::crbegin());
+ return ConstReverseIterator(helper_.crbegin());
}
ConstReverseIterator crend() const {
- return ConstReverseIterator(ListContainerBase::crend());
+ return ConstReverseIterator(helper_.crend());
}
ConstReverseIterator rbegin() const { return crbegin(); }
ConstReverseIterator rend() const { return crend(); }
- ReverseIterator rbegin() {
- return ReverseIterator(ListContainerBase::rbegin());
- }
- ReverseIterator rend() { return ReverseIterator(ListContainerBase::rend()); }
- ConstIterator cbegin() const {
- return ConstIterator(ListContainerBase::cbegin());
- }
- ConstIterator cend() const {
- return ConstIterator(ListContainerBase::cend());
- }
+ ReverseIterator rbegin() { return ReverseIterator(helper_.rbegin()); }
+ ReverseIterator rend() { return ReverseIterator(helper_.rend()); }
+ ConstIterator cbegin() const { return ConstIterator(helper_.cbegin()); }
+ ConstIterator cend() const { return ConstIterator(helper_.cend()); }
ConstIterator begin() const { return cbegin(); }
ConstIterator end() const { return cend(); }
- Iterator begin() { return Iterator(ListContainerBase::begin()); }
- Iterator end() { return Iterator(ListContainerBase::end()); }
+ Iterator begin() { return Iterator(helper_.begin()); }
+ Iterator end() { return Iterator(helper_.end()); }
// TODO(weiliangc): front(), back() and ElementAt() function should return
// reference, consistent with container-of-object.
@@ -262,24 +98,25 @@ class ListContainer : public ListContainerBase {
const BaseElementType* back() const { return *rbegin(); }
BaseElementType* ElementAt(size_t index) {
- return *Iterator(IteratorAt(index));
+ return *Iterator(helper_.IteratorAt(index));
}
const BaseElementType* ElementAt(size_t index) const {
- return *ConstIterator(IteratorAt(index));
+ return *ConstIterator(helper_.IteratorAt(index));
}
// Take in derived element type and construct it at location generated by
// Allocate().
template <typename DerivedElementType>
DerivedElementType* AllocateAndConstruct() {
- return new (Allocate(sizeof(DerivedElementType))) DerivedElementType;
+ return new (helper_.Allocate(sizeof(DerivedElementType)))
+ DerivedElementType;
}
// Take in derived element type and copy construct it at location generated by
// Allocate().
template <typename DerivedElementType>
DerivedElementType* AllocateAndCopyFrom(const DerivedElementType* source) {
- return new (Allocate(sizeof(DerivedElementType)))
+ return new (helper_.Allocate(sizeof(DerivedElementType)))
DerivedElementType(*source);
}
@@ -287,12 +124,26 @@ class ListContainer : public ListContainerBase {
template <typename DerivedElementType>
DerivedElementType* ReplaceExistingElement(Iterator at) {
at->~BaseElementType();
- return new (*at) DerivedElementType();
+ return new (at.item_iterator) DerivedElementType();
+ }
+
+ // Insert |count| new elements of |DerivedElementType| before |at|. This will
+ // invalidate all outstanding pointers and iterators. Return a valid iterator
+ // for the beginning of the newly inserted segment.
+ template <typename DerivedElementType>
+ Iterator InsertBeforeAndInvalidateAllPointers(Iterator at, size_t count) {
+ helper_.InsertBeforeAndInvalidateAllPointers(&at, count);
+ Iterator result = at;
+ for (size_t i = 0; i < count; ++i) {
+ new (at.item_iterator) DerivedElementType();
+ ++at;
+ }
+ return result;
}
template <typename DerivedElementType>
void swap(ListContainer<DerivedElementType>& other) {
- data_.swap(other.data_);
+ helper_.data_.swap(other.helper_.data_);
}
// Appends a new item without copying. The original item will not be
@@ -302,39 +153,43 @@ class ListContainer : public ListContainerBase {
// the moved element is returned.
template <typename DerivedElementType>
DerivedElementType* AppendByMoving(DerivedElementType* item) {
- size_t max_size_for_derived_class = MaxSizeForDerivedClass();
- void* new_item = Allocate(max_size_for_derived_class);
+ size_t max_size_for_derived_class = helper_.MaxSizeForDerivedClass();
+ void* new_item = helper_.Allocate(max_size_for_derived_class);
memcpy(new_item, static_cast<void*>(item), max_size_for_derived_class);
// Construct a new element in-place so it can be destructed safely.
new (item) DerivedElementType;
return static_cast<DerivedElementType*>(new_item);
}
- using ListContainerBase::size;
- using ListContainerBase::empty;
- using ListContainerBase::GetCapacityInBytes;
+ size_t size() const { return helper_.size(); }
+ bool empty() const { return helper_.empty(); }
+ size_t GetCapacityInBytes() const { return helper_.GetCapacityInBytes(); }
void clear() {
for (Iterator i = begin(); i != end(); ++i) {
i->~BaseElementType();
}
- ListContainerBase::clear();
+ helper_.clear();
}
- using ListContainerBase::AvailableSizeWithoutAnotherAllocationForTesting;
+ size_t AvailableSizeWithoutAnotherAllocationForTesting() const {
+ return helper_.AvailableSizeWithoutAnotherAllocationForTesting();
+ }
// Iterator classes that can be used to access data.
/////////////////////////////////////////////////////////////////
- class Iterator : public ListContainerBase::Iterator {
+ class Iterator : public ListContainerHelper::Iterator {
// This class is only defined to forward iterate through
- // ListContainerCharAllocator.
+ // CharAllocator.
public:
- Iterator(ListContainerCharAllocator* container,
+ Iterator(ListContainerHelper::CharAllocator* container,
size_t vector_ind,
char* item_iter,
size_t index)
- : ListContainerBase::Iterator(container, vector_ind, item_iter, index) {
- }
+ : ListContainerHelper::Iterator(container,
+ vector_ind,
+ item_iter,
+ index) {}
BaseElementType* operator->() const {
return reinterpret_cast<BaseElementType*>(item_iterator);
}
@@ -353,28 +208,28 @@ class ListContainer : public ListContainerBase {
}
private:
- explicit Iterator(const ListContainerBase::Iterator& base_iterator)
- : ListContainerBase::Iterator(base_iterator) {}
+ explicit Iterator(const ListContainerHelper::Iterator& base_iterator)
+ : ListContainerHelper::Iterator(base_iterator) {}
friend Iterator ListContainer<BaseElementType>::begin();
friend Iterator ListContainer<BaseElementType>::end();
friend BaseElementType* ListContainer<BaseElementType>::ElementAt(
size_t index);
};
- class ConstIterator : public ListContainerBase::ConstIterator {
+ class ConstIterator : public ListContainerHelper::ConstIterator {
// This class is only defined to forward iterate through
- // ListContainerCharAllocator.
+ // CharAllocator.
public:
- ConstIterator(ListContainerCharAllocator* container,
+ ConstIterator(ListContainerHelper::CharAllocator* container,
size_t vector_ind,
char* item_iter,
size_t index)
- : ListContainerBase::ConstIterator(container,
- vector_ind,
- item_iter,
- index) {}
+ : ListContainerHelper::ConstIterator(container,
+ vector_ind,
+ item_iter,
+ index) {}
ConstIterator(const Iterator& other) // NOLINT
- : ListContainerBase::ConstIterator(other) {}
+ : ListContainerHelper::ConstIterator(other) {}
const BaseElementType* operator->() const {
return reinterpret_cast<const BaseElementType*>(item_iterator);
}
@@ -394,26 +249,26 @@ class ListContainer : public ListContainerBase {
private:
explicit ConstIterator(
- const ListContainerBase::ConstIterator& base_iterator)
- : ListContainerBase::ConstIterator(base_iterator) {}
+ const ListContainerHelper::ConstIterator& base_iterator)
+ : ListContainerHelper::ConstIterator(base_iterator) {}
friend ConstIterator ListContainer<BaseElementType>::cbegin() const;
friend ConstIterator ListContainer<BaseElementType>::cend() const;
friend const BaseElementType* ListContainer<BaseElementType>::ElementAt(
size_t index) const;
};
- class ReverseIterator : public ListContainerBase::ReverseIterator {
+ class ReverseIterator : public ListContainerHelper::ReverseIterator {
// This class is only defined to reverse iterate through
- // ListContainerCharAllocator.
+ // CharAllocator.
public:
- ReverseIterator(ListContainerCharAllocator* container,
+ ReverseIterator(ListContainerHelper::CharAllocator* container,
size_t vector_ind,
char* item_iter,
size_t index)
- : ListContainerBase::ReverseIterator(container,
- vector_ind,
- item_iter,
- index) {}
+ : ListContainerHelper::ReverseIterator(container,
+ vector_ind,
+ item_iter,
+ index) {}
BaseElementType* operator->() const {
return reinterpret_cast<BaseElementType*>(item_iterator);
}
@@ -432,26 +287,27 @@ class ListContainer : public ListContainerBase {
}
private:
- explicit ReverseIterator(ListContainerBase::ReverseIterator base_iterator)
- : ListContainerBase::ReverseIterator(base_iterator) {}
+ explicit ReverseIterator(ListContainerHelper::ReverseIterator base_iterator)
+ : ListContainerHelper::ReverseIterator(base_iterator) {}
friend ReverseIterator ListContainer<BaseElementType>::rbegin();
friend ReverseIterator ListContainer<BaseElementType>::rend();
};
- class ConstReverseIterator : public ListContainerBase::ConstReverseIterator {
+ class ConstReverseIterator
+ : public ListContainerHelper::ConstReverseIterator {
// This class is only defined to reverse iterate through
- // ListContainerCharAllocator.
+ // CharAllocator.
public:
- ConstReverseIterator(ListContainerCharAllocator* container,
+ ConstReverseIterator(ListContainerHelper::CharAllocator* container,
size_t vector_ind,
char* item_iter,
size_t index)
- : ListContainerBase::ConstReverseIterator(container,
- vector_ind,
- item_iter,
- index) {}
+ : ListContainerHelper::ConstReverseIterator(container,
+ vector_ind,
+ item_iter,
+ index) {}
ConstReverseIterator(const ReverseIterator& other) // NOLINT
- : ListContainerBase::ConstReverseIterator(other) {}
+ : ListContainerHelper::ConstReverseIterator(other) {}
const BaseElementType* operator->() const {
return reinterpret_cast<const BaseElementType*>(item_iterator);
}
@@ -471,11 +327,16 @@ class ListContainer : public ListContainerBase {
private:
explicit ConstReverseIterator(
- ListContainerBase::ConstReverseIterator base_iterator)
- : ListContainerBase::ConstReverseIterator(base_iterator) {}
+ ListContainerHelper::ConstReverseIterator base_iterator)
+ : ListContainerHelper::ConstReverseIterator(base_iterator) {}
friend ConstReverseIterator ListContainer<BaseElementType>::crbegin() const;
friend ConstReverseIterator ListContainer<BaseElementType>::crend() const;
};
+
+ private:
+ ListContainerHelper helper_;
+
+ DISALLOW_COPY_AND_ASSIGN(ListContainer);
};
} // namespace cc
diff --git a/chromium/cc/base/list_container.cc b/chromium/cc/base/list_container_helper.cc
index d5cb4f03260..65be43adb38 100644
--- a/chromium/cc/base/list_container.cc
+++ b/chromium/cc/base/list_container_helper.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "cc/base/list_container.h"
+#include "cc/base/list_container_helper.h"
#include <algorithm>
#include <vector>
@@ -15,13 +15,13 @@ const size_t kDefaultNumElementTypesToReserve = 32;
namespace cc {
-// ListContainerCharAllocator
+// CharAllocator
////////////////////////////////////////////////////
// This class deals only with char* and void*. It does allocation and passing
// out raw pointers, as well as memory deallocation when being destroyed.
-class ListContainerBase::ListContainerCharAllocator {
+class ListContainerHelper::CharAllocator {
public:
- // ListContainerCharAllocator::InnerList
+ // CharAllocator::InnerList
/////////////////////////////////////////////
// This class holds the raw memory chunk, as well as information about its
// size and availability.
@@ -41,7 +41,7 @@ class ListContainerBase::ListContainerCharAllocator {
void Erase(char* position) {
// Confident that destructor is called by caller of this function. Since
- // ListContainerCharAllocator does not handle construction after
+ // CharAllocator does not handle construction after
// allocation, it doesn't handle desctrution before deallocation.
DCHECK_LE(position, LastElement());
DCHECK_GE(position, Begin());
@@ -53,6 +53,28 @@ class ListContainerBase::ListContainerCharAllocator {
--capacity;
}
+ void InsertBefore(char** position, size_t count) {
+ DCHECK_LE(*position, LastElement() + step);
+ DCHECK_GE(*position, Begin());
+
+ // Adjust the size and capacity
+ size_t old_size = size;
+ size += count;
+ capacity = size;
+
+ // Allocate the new data and update the iterator's pointer.
+ scoped_ptr<char[]> new_data(new char[size * step]);
+ size_t position_offset = *position - Begin();
+ *position = new_data.get() + position_offset;
+
+ // Copy the data before the inserted segment
+ memcpy(new_data.get(), data.get(), position_offset);
+ // Copy the data after the inserted segment.
+ memcpy(new_data.get() + position_offset + count * step,
+ data.get() + position_offset, old_size * step - position_offset);
+ new_data.swap(data);
+ }
+
bool IsEmpty() const { return !size; }
bool IsFull() { return capacity == size; }
size_t NumElementsAvailable() const { return capacity - size; }
@@ -77,7 +99,7 @@ class ListContainerBase::ListContainerCharAllocator {
DISALLOW_COPY_AND_ASSIGN(InnerList);
};
- explicit ListContainerCharAllocator(size_t element_size)
+ explicit CharAllocator(size_t element_size)
: element_size_(element_size),
size_(0),
last_list_index_(0),
@@ -86,7 +108,7 @@ class ListContainerBase::ListContainerCharAllocator {
last_list_ = storage_[last_list_index_];
}
- ListContainerCharAllocator(size_t element_size, size_t element_count)
+ CharAllocator(size_t element_size, size_t element_count)
: element_size_(element_size),
size_(0),
last_list_index_(0),
@@ -96,7 +118,7 @@ class ListContainerBase::ListContainerCharAllocator {
last_list_ = storage_[last_list_index_];
}
- ~ListContainerCharAllocator() {}
+ ~CharAllocator() {}
void* Allocate() {
if (last_list_->IsFull()) {
@@ -149,13 +171,41 @@ class ListContainerBase::ListContainerCharAllocator {
--size_;
}
- void Erase(PositionInListContainerCharAllocator position) {
- DCHECK_EQ(this, position.ptr_to_container);
- storage_[position.vector_index]->Erase(position.item_iterator);
+ void Erase(PositionInCharAllocator* position) {
+ DCHECK_EQ(this, position->ptr_to_container);
+
+ // Update |position| to point to the element after the erased element.
+ InnerList* list = storage_[position->vector_index];
+ char* item_iterator = position->item_iterator;
+ if (item_iterator == list->LastElement())
+ position->Increment();
+
+ list->Erase(item_iterator);
// TODO(weiliangc): Free the InnerList if it is empty.
--size_;
}
+ void InsertBefore(ListContainerHelper::Iterator* position, size_t count) {
+ if (!count)
+ return;
+
+ // If |position| is End(), then append |count| elements at the end. This
+ // will happen to not invalidate any iterators or memory.
+ if (!position->item_iterator) {
+ // Set |position| to be the first inserted element.
+ Allocate();
+ position->vector_index = storage_.size() - 1;
+ position->item_iterator = storage_[position->vector_index]->LastElement();
+ // Allocate the rest.
+ for (size_t i = 1; i < count; ++i)
+ Allocate();
+ } else {
+ storage_[position->vector_index]->InsertBefore(&position->item_iterator,
+ count);
+ size_ += count;
+ }
+ }
+
InnerList* InnerListById(size_t id) const {
DCHECK_LT(id, storage_.size());
return storage_[id];
@@ -208,46 +258,40 @@ class ListContainerBase::ListContainerCharAllocator {
// This is equivalent to |storage_[last_list_index_]|.
InnerList* last_list_;
- DISALLOW_COPY_AND_ASSIGN(ListContainerCharAllocator);
+ DISALLOW_COPY_AND_ASSIGN(CharAllocator);
};
-// PositionInListContainerCharAllocator
+// PositionInCharAllocator
//////////////////////////////////////////////////////
-ListContainerBase::PositionInListContainerCharAllocator::
- PositionInListContainerCharAllocator(
- const ListContainerBase::PositionInListContainerCharAllocator& other)
+ListContainerHelper::PositionInCharAllocator::PositionInCharAllocator(
+ const ListContainerHelper::PositionInCharAllocator& other)
: ptr_to_container(other.ptr_to_container),
vector_index(other.vector_index),
- item_iterator(other.item_iterator) {
-}
+ item_iterator(other.item_iterator) {}
-ListContainerBase::PositionInListContainerCharAllocator::
- PositionInListContainerCharAllocator(
- ListContainerBase::ListContainerCharAllocator* container,
- size_t vector_ind,
- char* item_iter)
+ListContainerHelper::PositionInCharAllocator::PositionInCharAllocator(
+ ListContainerHelper::CharAllocator* container,
+ size_t vector_ind,
+ char* item_iter)
: ptr_to_container(container),
vector_index(vector_ind),
- item_iterator(item_iter) {
-}
+ item_iterator(item_iter) {}
-bool ListContainerBase::PositionInListContainerCharAllocator::operator==(
- const ListContainerBase::PositionInListContainerCharAllocator& other)
- const {
+bool ListContainerHelper::PositionInCharAllocator::operator==(
+ const ListContainerHelper::PositionInCharAllocator& other) const {
DCHECK_EQ(ptr_to_container, other.ptr_to_container);
return vector_index == other.vector_index &&
item_iterator == other.item_iterator;
}
-bool ListContainerBase::PositionInListContainerCharAllocator::operator!=(
- const ListContainerBase::PositionInListContainerCharAllocator& other)
- const {
+bool ListContainerHelper::PositionInCharAllocator::operator!=(
+ const ListContainerHelper::PositionInCharAllocator& other) const {
return !(*this == other);
}
-ListContainerBase::PositionInListContainerCharAllocator
-ListContainerBase::PositionInListContainerCharAllocator::Increment() {
- ListContainerCharAllocator::InnerList* list =
+ListContainerHelper::PositionInCharAllocator
+ListContainerHelper::PositionInCharAllocator::Increment() {
+ CharAllocator::InnerList* list =
ptr_to_container->InnerListById(vector_index);
if (item_iterator == list->LastElement()) {
++vector_index;
@@ -266,9 +310,9 @@ ListContainerBase::PositionInListContainerCharAllocator::Increment() {
return *this;
}
-ListContainerBase::PositionInListContainerCharAllocator
-ListContainerBase::PositionInListContainerCharAllocator::ReverseIncrement() {
- ListContainerCharAllocator::InnerList* list =
+ListContainerHelper::PositionInCharAllocator
+ListContainerHelper::PositionInCharAllocator::ReverseIncrement() {
+ CharAllocator::InnerList* list =
ptr_to_container->InnerListById(vector_index);
if (item_iterator == list->Begin()) {
--vector_index;
@@ -292,31 +336,34 @@ ListContainerBase::PositionInListContainerCharAllocator::ReverseIncrement() {
return *this;
}
-// ListContainerBase
+// ListContainerHelper
////////////////////////////////////////////
-ListContainerBase::ListContainerBase(size_t max_size_for_derived_class)
- : data_(new ListContainerCharAllocator(max_size_for_derived_class)) {
-}
+ListContainerHelper::ListContainerHelper(size_t max_size_for_derived_class)
+ : data_(new CharAllocator(max_size_for_derived_class)) {}
-ListContainerBase::ListContainerBase(size_t max_size_for_derived_class,
- size_t num_of_elements_to_reserve_for)
- : data_(new ListContainerCharAllocator(max_size_for_derived_class,
- num_of_elements_to_reserve_for)) {
-}
+ListContainerHelper::ListContainerHelper(size_t max_size_for_derived_class,
+ size_t num_of_elements_to_reserve_for)
+ : data_(new CharAllocator(max_size_for_derived_class,
+ num_of_elements_to_reserve_for)) {}
-ListContainerBase::~ListContainerBase() {
-}
+ListContainerHelper::~ListContainerHelper() {}
-void ListContainerBase::RemoveLast() {
+void ListContainerHelper::RemoveLast() {
data_->RemoveLast();
}
-void ListContainerBase::EraseAndInvalidateAllPointers(
- ListContainerBase::Iterator position) {
+void ListContainerHelper::EraseAndInvalidateAllPointers(
+ ListContainerHelper::Iterator* position) {
data_->Erase(position);
}
-ListContainerBase::ConstReverseIterator ListContainerBase::crbegin() const {
+void ListContainerHelper::InsertBeforeAndInvalidateAllPointers(
+ ListContainerHelper::Iterator* position,
+ size_t count) {
+ data_->InsertBefore(position, count);
+}
+
+ListContainerHelper::ConstReverseIterator ListContainerHelper::crbegin() const {
if (data_->IsEmpty())
return crend();
@@ -325,12 +372,12 @@ ListContainerBase::ConstReverseIterator ListContainerBase::crbegin() const {
data_->InnerListById(id)->LastElement(), 0);
}
-ListContainerBase::ConstReverseIterator ListContainerBase::crend() const {
+ListContainerHelper::ConstReverseIterator ListContainerHelper::crend() const {
return ConstReverseIterator(data_.get(), static_cast<size_t>(-1), NULL,
size());
}
-ListContainerBase::ReverseIterator ListContainerBase::rbegin() {
+ListContainerHelper::ReverseIterator ListContainerHelper::rbegin() {
if (data_->IsEmpty())
return rend();
@@ -339,11 +386,11 @@ ListContainerBase::ReverseIterator ListContainerBase::rbegin() {
data_->InnerListById(id)->LastElement(), 0);
}
-ListContainerBase::ReverseIterator ListContainerBase::rend() {
+ListContainerHelper::ReverseIterator ListContainerHelper::rend() {
return ReverseIterator(data_.get(), static_cast<size_t>(-1), NULL, size());
}
-ListContainerBase::ConstIterator ListContainerBase::cbegin() const {
+ListContainerHelper::ConstIterator ListContainerHelper::cbegin() const {
if (data_->IsEmpty())
return cend();
@@ -351,7 +398,7 @@ ListContainerBase::ConstIterator ListContainerBase::cbegin() const {
return ConstIterator(data_.get(), id, data_->InnerListById(id)->Begin(), 0);
}
-ListContainerBase::ConstIterator ListContainerBase::cend() const {
+ListContainerHelper::ConstIterator ListContainerHelper::cend() const {
if (data_->IsEmpty())
return ConstIterator(data_.get(), 0, NULL, size());
@@ -359,7 +406,7 @@ ListContainerBase::ConstIterator ListContainerBase::cend() const {
return ConstIterator(data_.get(), id, NULL, size());
}
-ListContainerBase::Iterator ListContainerBase::begin() {
+ListContainerHelper::Iterator ListContainerHelper::begin() {
if (data_->IsEmpty())
return end();
@@ -367,7 +414,7 @@ ListContainerBase::Iterator ListContainerBase::begin() {
return Iterator(data_.get(), id, data_->InnerListById(id)->Begin(), 0);
}
-ListContainerBase::Iterator ListContainerBase::end() {
+ListContainerHelper::Iterator ListContainerHelper::end() {
if (data_->IsEmpty())
return Iterator(data_.get(), 0, NULL, size());
@@ -375,7 +422,7 @@ ListContainerBase::Iterator ListContainerBase::end() {
return Iterator(data_.get(), id, NULL, size());
}
-ListContainerBase::ConstIterator ListContainerBase::IteratorAt(
+ListContainerHelper::ConstIterator ListContainerHelper::IteratorAt(
size_t index) const {
DCHECK_LT(index, size());
size_t original_index = index;
@@ -391,7 +438,7 @@ ListContainerBase::ConstIterator ListContainerBase::IteratorAt(
original_index);
}
-ListContainerBase::Iterator ListContainerBase::IteratorAt(size_t index) {
+ListContainerHelper::Iterator ListContainerHelper::IteratorAt(size_t index) {
DCHECK_LT(index, size());
size_t original_index = index;
size_t list_index;
@@ -406,114 +453,102 @@ ListContainerBase::Iterator ListContainerBase::IteratorAt(size_t index) {
original_index);
}
-void* ListContainerBase::Allocate(size_t size_of_actual_element_in_bytes) {
+void* ListContainerHelper::Allocate(size_t size_of_actual_element_in_bytes) {
DCHECK_LE(size_of_actual_element_in_bytes, data_->element_size());
return data_->Allocate();
}
-size_t ListContainerBase::size() const {
+size_t ListContainerHelper::size() const {
return data_->size();
}
-bool ListContainerBase::empty() const {
+bool ListContainerHelper::empty() const {
return data_->IsEmpty();
}
-size_t ListContainerBase::MaxSizeForDerivedClass() const {
+size_t ListContainerHelper::MaxSizeForDerivedClass() const {
return data_->element_size();
}
-size_t ListContainerBase::GetCapacityInBytes() const {
+size_t ListContainerHelper::GetCapacityInBytes() const {
return data_->Capacity() * data_->element_size();
}
-void ListContainerBase::clear() {
+void ListContainerHelper::clear() {
data_->Clear();
}
-size_t ListContainerBase::AvailableSizeWithoutAnotherAllocationForTesting()
+size_t ListContainerHelper::AvailableSizeWithoutAnotherAllocationForTesting()
const {
return data_->NumAvailableElementsInLastList();
}
-// ListContainerBase::Iterator
+// ListContainerHelper::Iterator
/////////////////////////////////////////////////
-ListContainerBase::Iterator::Iterator(ListContainerCharAllocator* container,
- size_t vector_ind,
- char* item_iter,
- size_t index)
- : PositionInListContainerCharAllocator(container, vector_ind, item_iter),
- index_(index) {
-}
+ListContainerHelper::Iterator::Iterator(CharAllocator* container,
+ size_t vector_ind,
+ char* item_iter,
+ size_t index)
+ : PositionInCharAllocator(container, vector_ind, item_iter),
+ index_(index) {}
-ListContainerBase::Iterator::~Iterator() {
-}
+ListContainerHelper::Iterator::~Iterator() {}
-size_t ListContainerBase::Iterator::index() const {
+size_t ListContainerHelper::Iterator::index() const {
return index_;
}
-// ListContainerBase::ConstIterator
+// ListContainerHelper::ConstIterator
/////////////////////////////////////////////////
-ListContainerBase::ConstIterator::ConstIterator(
- const ListContainerBase::Iterator& other)
- : PositionInListContainerCharAllocator(other), index_(other.index()) {
-}
+ListContainerHelper::ConstIterator::ConstIterator(
+ const ListContainerHelper::Iterator& other)
+ : PositionInCharAllocator(other), index_(other.index()) {}
-ListContainerBase::ConstIterator::ConstIterator(
- ListContainerCharAllocator* container,
- size_t vector_ind,
- char* item_iter,
- size_t index)
- : PositionInListContainerCharAllocator(container, vector_ind, item_iter),
- index_(index) {
-}
+ListContainerHelper::ConstIterator::ConstIterator(CharAllocator* container,
+ size_t vector_ind,
+ char* item_iter,
+ size_t index)
+ : PositionInCharAllocator(container, vector_ind, item_iter),
+ index_(index) {}
-ListContainerBase::ConstIterator::~ConstIterator() {
-}
+ListContainerHelper::ConstIterator::~ConstIterator() {}
-size_t ListContainerBase::ConstIterator::index() const {
+size_t ListContainerHelper::ConstIterator::index() const {
return index_;
}
-// ListContainerBase::ReverseIterator
+// ListContainerHelper::ReverseIterator
/////////////////////////////////////////////////
-ListContainerBase::ReverseIterator::ReverseIterator(
- ListContainerCharAllocator* container,
- size_t vector_ind,
- char* item_iter,
- size_t index)
- : PositionInListContainerCharAllocator(container, vector_ind, item_iter),
- index_(index) {
-}
+ListContainerHelper::ReverseIterator::ReverseIterator(CharAllocator* container,
+ size_t vector_ind,
+ char* item_iter,
+ size_t index)
+ : PositionInCharAllocator(container, vector_ind, item_iter),
+ index_(index) {}
-ListContainerBase::ReverseIterator::~ReverseIterator() {
-}
+ListContainerHelper::ReverseIterator::~ReverseIterator() {}
-size_t ListContainerBase::ReverseIterator::index() const {
+size_t ListContainerHelper::ReverseIterator::index() const {
return index_;
}
-// ListContainerBase::ConstReverseIterator
+// ListContainerHelper::ConstReverseIterator
/////////////////////////////////////////////////
-ListContainerBase::ConstReverseIterator::ConstReverseIterator(
- const ListContainerBase::ReverseIterator& other)
- : PositionInListContainerCharAllocator(other), index_(other.index()) {
-}
+ListContainerHelper::ConstReverseIterator::ConstReverseIterator(
+ const ListContainerHelper::ReverseIterator& other)
+ : PositionInCharAllocator(other), index_(other.index()) {}
-ListContainerBase::ConstReverseIterator::ConstReverseIterator(
- ListContainerCharAllocator* container,
+ListContainerHelper::ConstReverseIterator::ConstReverseIterator(
+ CharAllocator* container,
size_t vector_ind,
char* item_iter,
size_t index)
- : PositionInListContainerCharAllocator(container, vector_ind, item_iter),
- index_(index) {
-}
+ : PositionInCharAllocator(container, vector_ind, item_iter),
+ index_(index) {}
-ListContainerBase::ConstReverseIterator::~ConstReverseIterator() {
-}
+ListContainerHelper::ConstReverseIterator::~ConstReverseIterator() {}
-size_t ListContainerBase::ConstReverseIterator::index() const {
+size_t ListContainerHelper::ConstReverseIterator::index() const {
return index_;
}
diff --git a/chromium/cc/base/list_container_helper.h b/chromium/cc/base/list_container_helper.h
new file mode 100644
index 00000000000..31b2310d49d
--- /dev/null
+++ b/chromium/cc/base/list_container_helper.h
@@ -0,0 +1,178 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_BASE_LIST_CONTAINER_HELPER_H_
+#define CC_BASE_LIST_CONTAINER_HELPER_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "cc/base/cc_export.h"
+
+namespace cc {
+
+// Helper class for ListContainer non-templated logic. All methods are private,
+// and only exposed to friend classes.
+// For usage, see comments in ListContainer (list_container.h).
+class CC_EXPORT ListContainerHelper final {
+ private:
+ template <typename T>
+ friend class ListContainer;
+
+ template <typename T>
+ friend class RandomAccessListContainer;
+
+ explicit ListContainerHelper(size_t max_size_for_derived_class);
+ ListContainerHelper(size_t max_size_for_derived_class,
+ size_t num_of_elements_to_reserve_for);
+ ~ListContainerHelper();
+
+ // This class deals only with char* and void*. It does allocation and passing
+ // out raw pointers, as well as memory deallocation when being destroyed.
+ class CharAllocator;
+
+ // This class points to a certain position inside memory of
+ // CharAllocator. It is a base class for ListContainer iterators.
+ struct CC_EXPORT PositionInCharAllocator {
+ CharAllocator* ptr_to_container;
+ size_t vector_index;
+ char* item_iterator;
+
+ PositionInCharAllocator(const PositionInCharAllocator& other);
+
+ PositionInCharAllocator(CharAllocator* container,
+ size_t vector_ind,
+ char* item_iter);
+
+ bool operator==(const PositionInCharAllocator& other) const;
+ bool operator!=(const PositionInCharAllocator& other) const;
+
+ PositionInCharAllocator Increment();
+ PositionInCharAllocator ReverseIncrement();
+ };
+
+ // Iterator classes that can be used to access data.
+ /////////////////////////////////////////////////////////////////
+ class CC_EXPORT Iterator : public PositionInCharAllocator {
+ // This class is only defined to forward iterate through
+ // CharAllocator.
+ public:
+ Iterator(CharAllocator* container,
+ size_t vector_ind,
+ char* item_iter,
+ size_t index);
+ ~Iterator();
+
+ size_t index() const;
+
+ protected:
+ // This is used to track how many increment has happened since begin(). It
+ // is used to avoid double increment at places an index reference is
+ // needed. For iterator this means begin() corresponds to index 0 and end()
+ // corresponds to index |size|.
+ size_t index_;
+ };
+
+ class CC_EXPORT ConstIterator : public PositionInCharAllocator {
+ // This class is only defined to forward iterate through
+ // CharAllocator.
+ public:
+ ConstIterator(CharAllocator* container,
+ size_t vector_ind,
+ char* item_iter,
+ size_t index);
+ ConstIterator(const Iterator& other); // NOLINT
+ ~ConstIterator();
+
+ size_t index() const;
+
+ protected:
+ // This is used to track how many increment has happened since begin(). It
+ // is used to avoid double increment at places an index reference is
+ // needed. For iterator this means begin() corresponds to index 0 and end()
+ // corresponds to index |size|.
+ size_t index_;
+ };
+
+ class CC_EXPORT ReverseIterator : public PositionInCharAllocator {
+ // This class is only defined to reverse iterate through
+ // CharAllocator.
+ public:
+ ReverseIterator(CharAllocator* container,
+ size_t vector_ind,
+ char* item_iter,
+ size_t index);
+ ~ReverseIterator();
+
+ size_t index() const;
+
+ protected:
+ // This is used to track how many increment has happened since rbegin(). It
+ // is used to avoid double increment at places an index reference is
+ // needed. For reverse iterator this means rbegin() corresponds to index 0
+ // and rend() corresponds to index |size|.
+ size_t index_;
+ };
+
+ class CC_EXPORT ConstReverseIterator : public PositionInCharAllocator {
+ // This class is only defined to reverse iterate through
+ // CharAllocator.
+ public:
+ ConstReverseIterator(CharAllocator* container,
+ size_t vector_ind,
+ char* item_iter,
+ size_t index);
+ ConstReverseIterator(const ReverseIterator& other); // NOLINT
+ ~ConstReverseIterator();
+
+ size_t index() const;
+
+ protected:
+ // This is used to track how many increment has happened since rbegin(). It
+ // is used to avoid double increment at places an index reference is
+ // needed. For reverse iterator this means rbegin() corresponds to index 0
+ // and rend() corresponds to index |size|.
+ size_t index_;
+ };
+
+ // Unlike the ListContainer methods, these do not invoke element destructors.
+ void RemoveLast();
+ void EraseAndInvalidateAllPointers(Iterator* position);
+ void InsertBeforeAndInvalidateAllPointers(Iterator* position,
+ size_t number_of_elements);
+
+ ConstReverseIterator crbegin() const;
+ ConstReverseIterator crend() const;
+ ReverseIterator rbegin();
+ ReverseIterator rend();
+ ConstIterator cbegin() const;
+ ConstIterator cend() const;
+ Iterator begin();
+ Iterator end();
+
+ Iterator IteratorAt(size_t index);
+ ConstIterator IteratorAt(size_t index) const;
+
+ size_t size() const;
+ bool empty() const;
+
+ size_t MaxSizeForDerivedClass() const;
+
+ size_t GetCapacityInBytes() const;
+
+ // Unlike the ListContainer method, this one does not invoke element
+ // destructors.
+ void clear();
+
+ size_t AvailableSizeWithoutAnotherAllocationForTesting() const;
+
+ // Hands out memory location for an element at the end of data structure.
+ void* Allocate(size_t size_of_actual_element_in_bytes);
+
+ scoped_ptr<CharAllocator> data_;
+
+ DISALLOW_COPY_AND_ASSIGN(ListContainerHelper);
+};
+
+} // namespace cc
+
+#endif // CC_BASE_LIST_CONTAINER_HELPER_H_
diff --git a/chromium/cc/base/list_container_unittest.cc b/chromium/cc/base/list_container_unittest.cc
index d1fb3fb9490..be0b2b75b4e 100644
--- a/chromium/cc/base/list_container_unittest.cc
+++ b/chromium/cc/base/list_container_unittest.cc
@@ -657,30 +657,154 @@ TEST(ListContainerTest, DeletionAllInAllocationReversed) {
}
}
-TEST(ListContainerTest, SimpleIterationAndManipulation) {
+TEST(ListContainerTest, DeletionWhileIterating) {
+ ListContainer<SimpleDerivedElement> list(kCurrentLargestDerivedElementSize);
+ for (int i = 0; i < 4; ++i)
+ list.AllocateAndConstruct<SimpleDerivedElement>()->set_value(i);
+
+ // Delete odd elements.
+ for (auto it = list.begin(); it != list.end();) {
+ if ((*it)->get_value() % 2)
+ it = list.EraseAndInvalidateAllPointers(it);
+ else
+ ++it;
+ }
+
+ EXPECT_EQ(2u, list.size());
+ EXPECT_EQ(0, list.front()->get_value());
+ EXPECT_EQ(2, list.back()->get_value());
+
+ // Erase all elements.
+ for (auto it = list.begin(); it != list.end();)
+ it = list.EraseAndInvalidateAllPointers(it);
+
+ EXPECT_TRUE(list.empty());
+}
+
+TEST(ListContainerTest, InsertBeforeBegin) {
ListContainer<DerivedElement> list(kCurrentLargestDerivedElementSize);
std::vector<SimpleDerivedElement*> sde_list;
- size_t size = 10;
+ const int size = 4;
+ for (int i = 0; i < size; ++i) {
+ sde_list.push_back(list.AllocateAndConstruct<SimpleDerivedElement>());
+ sde_list.back()->set_value(i);
+ }
+ EXPECT_EQ(static_cast<size_t>(size), list.size());
+
+ const int count = 2;
+ ListContainer<DerivedElement>::Iterator iter =
+ list.InsertBeforeAndInvalidateAllPointers<SimpleDerivedElement>(
+ list.begin(), count);
+ for (int i = 0; i < count; ++i) {
+ static_cast<SimpleDerivedElement*>(*iter)->set_value(100 + i);
+ ++iter;
+ }
+
+ const int expected_result[] = {100, 101, 0, 1, 2, 3};
+ int iter_index = 0;
+ for (iter = list.begin(); iter != list.end(); ++iter) {
+ EXPECT_EQ(expected_result[iter_index],
+ static_cast<SimpleDerivedElement*>(*iter)->get_value());
+ ++iter_index;
+ }
+ EXPECT_EQ(size + count, iter_index);
+}
+
+TEST(ListContainerTest, InsertBeforeEnd) {
+ ListContainer<DerivedElement> list(kCurrentLargestDerivedElementSize);
+ std::vector<SimpleDerivedElement*> sde_list;
+ const int size = 4;
+ for (int i = 0; i < size; ++i) {
+ sde_list.push_back(list.AllocateAndConstruct<SimpleDerivedElement>());
+ sde_list.back()->set_value(i);
+ }
+ EXPECT_EQ(static_cast<size_t>(size), list.size());
+
+ const int count = 3;
+ ListContainer<DerivedElement>::Iterator iter =
+ list.InsertBeforeAndInvalidateAllPointers<SimpleDerivedElement>(
+ list.end(), count);
+ for (int i = 0; i < count; ++i) {
+ static_cast<SimpleDerivedElement*>(*iter)->set_value(100 + i);
+ ++iter;
+ }
+
+ const int expected_result[] = {0, 1, 2, 3, 100, 101, 102};
+ int iter_index = 0;
+ for (iter = list.begin(); iter != list.end(); ++iter) {
+ EXPECT_EQ(expected_result[iter_index],
+ static_cast<SimpleDerivedElement*>(*iter)->get_value());
+ ++iter_index;
+ }
+ EXPECT_EQ(size + count, iter_index);
+}
+
+TEST(ListContainerTest, InsertBeforeEmpty) {
+ ListContainer<DerivedElement> list(kCurrentLargestDerivedElementSize);
+
+ const int count = 3;
+ ListContainer<DerivedElement>::Iterator iter =
+ list.InsertBeforeAndInvalidateAllPointers<SimpleDerivedElement>(
+ list.end(), count);
+ for (int i = 0; i < count; ++i) {
+ static_cast<SimpleDerivedElement*>(*iter)->set_value(100 + i);
+ ++iter;
+ }
+
+ const int expected_result[] = {100, 101, 102};
+ int iter_index = 0;
+ for (iter = list.begin(); iter != list.end(); ++iter) {
+ EXPECT_EQ(expected_result[iter_index],
+ static_cast<SimpleDerivedElement*>(*iter)->get_value());
+ ++iter_index;
+ }
+ EXPECT_EQ(count, iter_index);
+}
+
+TEST(ListContainerTest, InsertBeforeMany) {
+ ListContainer<DerivedElement> list(kCurrentLargestDerivedElementSize);
+ std::vector<SimpleDerivedElement*> sde_list;
+ // Create a partial list of 1,...,99.
+ int initial_list[] = {
+ 0, 1, 4, 5, 6, 7, 8, 9, 11, 12, 17, 18, 19, 20, 21, 22,
+ 23, 24, 25, 26, 27, 28, 29, 30, 32, 34, 36, 37, 51, 52, 54, 56,
+ 60, 64, 65, 70, 75, 76, 80, 81, 83, 86, 87, 90, 93, 95, 97, 98,
+ };
+ const size_t size = sizeof(initial_list) / sizeof(initial_list[0]);
for (size_t i = 0; i < size; ++i) {
- SimpleDerivedElement* simple_dq =
- list.AllocateAndConstruct<SimpleDerivedElement>();
- sde_list.push_back(simple_dq);
+ sde_list.push_back(list.AllocateAndConstruct<SimpleDerivedElement>());
+ sde_list.back()->set_value(initial_list[i]);
}
- EXPECT_EQ(size, list.size());
+ EXPECT_EQ(static_cast<size_t>(size), list.size());
+ // Insert the missing elements.
ListContainer<DerivedElement>::Iterator iter = list.begin();
- for (int i = 0; i < 10; ++i) {
- static_cast<SimpleDerivedElement*>(*iter)->set_value(i);
- ++iter;
+ while (iter != list.end()) {
+ ListContainer<DerivedElement>::Iterator iter_next = iter;
+ ++iter_next;
+
+ int value = static_cast<SimpleDerivedElement*>(*iter)->get_value();
+ int value_next =
+ iter_next != list.end()
+ ? static_cast<SimpleDerivedElement*>(*iter_next)->get_value()
+ : 100;
+ int count = value_next - value - 1;
+
+ iter = list.InsertBeforeAndInvalidateAllPointers<SimpleDerivedElement>(
+ iter_next, count);
+ for (int i = value + 1; i < value_next; ++i) {
+ static_cast<SimpleDerivedElement*>(*iter)->set_value(i);
+ ++iter;
+ }
}
- int i = 0;
- for (std::vector<SimpleDerivedElement*>::const_iterator sde_iter =
- sde_list.begin();
- sde_iter < sde_list.end(); ++sde_iter) {
- EXPECT_EQ(i, (*sde_iter)->get_value());
- ++i;
+ int iter_index = 0;
+ for (iter = list.begin(); iter != list.end(); ++iter) {
+ EXPECT_EQ(iter_index,
+ static_cast<SimpleDerivedElement*>(*iter)->get_value());
+ ++iter_index;
}
+ EXPECT_EQ(100, iter_index);
}
TEST(ListContainerTest, SimpleManipulationWithIndexSimpleDerivedElement) {
diff --git a/chromium/cc/base/math_util.cc b/chromium/cc/base/math_util.cc
index 969e52a6ed7..6e5ac0bd45d 100644
--- a/chromium/cc/base/math_util.cc
+++ b/chromium/cc/base/math_util.cc
@@ -26,18 +26,19 @@ const float MathUtil::kPiFloat = 3.14159265358979323846f;
static HomogeneousCoordinate ProjectHomogeneousPoint(
const gfx::Transform& transform,
const gfx::PointF& p) {
+ SkMScalar z =
+ -(transform.matrix().get(2, 0) * p.x() +
+ transform.matrix().get(2, 1) * p.y() + transform.matrix().get(2, 3)) /
+ transform.matrix().get(2, 2);
+
// In this case, the layer we are trying to project onto is perpendicular to
// ray (point p and z-axis direction) that we are trying to project. This
// happens when the layer is rotated so that it is infinitesimally thin, or
// when it is co-planar with the camera origin -- i.e. when the layer is
// invisible anyway.
- if (!transform.matrix().get(2, 2))
+ if (!std::isfinite(z))
return HomogeneousCoordinate(0.0, 0.0, 0.0, 1.0);
- SkMScalar z = -(transform.matrix().get(2, 0) * p.x() +
- transform.matrix().get(2, 1) * p.y() +
- transform.matrix().get(2, 3)) /
- transform.matrix().get(2, 2);
HomogeneousCoordinate result(p.x(), p.y(), z, 1.0);
transform.matrix().mapMScalars(result.vec, result.vec);
return result;
@@ -126,7 +127,14 @@ gfx::Rect MathUtil::MapEnclosingClippedRect(const gfx::Transform& transform,
static_cast<int>(transform.matrix().getFloat(1, 3)));
return src_rect + offset;
}
- return gfx::ToEnclosingRect(MapClippedRect(transform, gfx::RectF(src_rect)));
+ gfx::RectF mapped_rect = MapClippedRect(transform, gfx::RectF(src_rect));
+
+ // gfx::ToEnclosingRect crashes if called on a RectF with any NaN coordinate.
+ if (std::isnan(mapped_rect.x()) || std::isnan(mapped_rect.y()) ||
+ std::isnan(mapped_rect.right()) || std::isnan(mapped_rect.bottom()))
+ return gfx::Rect();
+
+ return gfx::ToEnclosingRect(mapped_rect);
}
gfx::RectF MathUtil::MapClippedRect(const gfx::Transform& transform,
@@ -166,8 +174,15 @@ gfx::Rect MathUtil::ProjectEnclosingClippedRect(const gfx::Transform& transform,
static_cast<int>(transform.matrix().getFloat(1, 3)));
return src_rect + offset;
}
- return gfx::ToEnclosingRect(
- ProjectClippedRect(transform, gfx::RectF(src_rect)));
+ gfx::RectF projected_rect =
+ ProjectClippedRect(transform, gfx::RectF(src_rect));
+
+ // gfx::ToEnclosingRect crashes if called on a RectF with any NaN coordinate.
+ if (std::isnan(projected_rect.x()) || std::isnan(projected_rect.y()) ||
+ std::isnan(projected_rect.right()) || std::isnan(projected_rect.bottom()))
+ return gfx::Rect();
+
+ return gfx::ToEnclosingRect(projected_rect);
}
gfx::RectF MathUtil::ProjectClippedRect(const gfx::Transform& transform,
@@ -201,7 +216,7 @@ gfx::Rect MathUtil::MapEnclosedRectWith2dAxisAlignedTransform(
if (transform.IsIdentityOrTranslation()) {
gfx::Vector2dF offset(transform.matrix().getFloat(0, 3),
transform.matrix().getFloat(1, 3));
- return gfx::ToEnclosedRect(rect + offset);
+ return gfx::ToEnclosedRect(gfx::RectF(rect) + offset);
}
SkMScalar quad[2 * 2]; // input: 2 x 2D points
diff --git a/chromium/cc/base/math_util.h b/chromium/cc/base/math_util.h
index 4c40e8ef9a4..a83ab4fdce3 100644
--- a/chromium/cc/base/math_util.h
+++ b/chromium/cc/base/math_util.h
@@ -30,6 +30,7 @@ namespace gfx {
class QuadF;
class Rect;
class RectF;
+class SizeF;
class Transform;
class Vector2dF;
class Vector2d;
@@ -96,27 +97,62 @@ class CC_EXPORT MathUtil {
return (d > 0.0) ? std::floor(d + 0.5) : std::ceil(d - 0.5);
}
- // RoundUp rounds up a given |n| to be a multiple of |mul|.
+ // Returns true if rounded up value does not overflow, false otherwise.
+ template <typename T>
+ static bool VerifyRoundup(T n, T mul) {
+ return mul && (n <= (std::numeric_limits<T>::max() -
+ (std::numeric_limits<T>::max() % mul)));
+ }
+
+ // Rounds up a given |n| to be a multiple of |mul|, but may overflow.
// Examples:
// - RoundUp(123, 50) returns 150.
// - RoundUp(-123, 50) returns -100.
template <typename T>
- static T RoundUp(T n, T mul) {
+ static T UncheckedRoundUp(T n, T mul) {
static_assert(std::numeric_limits<T>::is_integer,
"T must be an integer type");
- return (n > 0) ? ((n + mul - 1) / mul) * mul : (n / mul) * mul;
+ DCHECK(VerifyRoundup(n, mul));
+ return RoundUpInternal(n, mul);
+ }
+
+ // Similar to UncheckedRoundUp(), but dies with a CRASH() if rounding up a
+ // given |n| overflows T.
+ template <typename T>
+ static T CheckedRoundUp(T n, T mul) {
+ static_assert(std::numeric_limits<T>::is_integer,
+ "T must be an integer type");
+ CHECK(VerifyRoundup(n, mul));
+ return RoundUpInternal(n, mul);
}
- // RoundDown rounds down a given |n| to be a multiple of |mul|.
+ // Returns true if rounded down value does not underflow, false otherwise.
+ template <typename T>
+ static bool VerifyRoundDown(T n, T mul) {
+ return mul && (n >= (std::numeric_limits<T>::min() -
+ (std::numeric_limits<T>::min() % mul)));
+ }
+
+ // Rounds down a given |n| to be a multiple of |mul|, but may underflow.
// Examples:
// - RoundDown(123, 50) returns 100.
// - RoundDown(-123, 50) returns -150.
template <typename T>
- static T RoundDown(T n, T mul) {
+ static T UncheckedRoundDown(T n, T mul) {
static_assert(std::numeric_limits<T>::is_integer,
"T must be an integer type");
- return (n > 0) ? (n / mul) * mul : (n == 0) ? 0
- : ((n - mul + 1) / mul) * mul;
+ DCHECK(VerifyRoundDown(n, mul));
+ return RoundDownInternal(n, mul);
+ }
+
+ // Similar to UncheckedRoundDown(), but dies with a CRASH() if rounding down a
+ // given |n| underflows T.
+ template <typename T>
+ static T CheckedRoundDown(T n, T mul) {
+ static_assert(std::numeric_limits<T>::is_integer,
+ "T must be an integer type");
+ CHECK(VerifyRoundDown(n, mul));
+ return RoundDownInternal(n, mul);
}
template <typename T> static T ClampToRange(T value, T min, T max) {
@@ -270,6 +306,18 @@ class CC_EXPORT MathUtil {
// Returns vector that y axis (0,1,0) transforms to under given transform.
static gfx::Vector3dF GetYAxis(const gfx::Transform& transform);
+
+ private:
+ template <typename T>
+ static T RoundUpInternal(T n, T mul) {
+ return (n > 0) ? ((n + mul - 1) / mul) * mul : (n / mul) * mul;
+ }
+
+ template <typename T>
+ static T RoundDownInternal(T n, T mul) {
+ return (n > 0) ? (n / mul) * mul : (n == 0) ? 0
+ : ((n - mul + 1) / mul) * mul;
+ }
};
} // namespace cc
diff --git a/chromium/cc/base/math_util_unittest.cc b/chromium/cc/base/math_util_unittest.cc
index 1d43e0f2129..9d44fba8ac0 100644
--- a/chromium/cc/base/math_util_unittest.cc
+++ b/chromium/cc/base/math_util_unittest.cc
@@ -32,6 +32,32 @@ TEST(MathUtilTest, ProjectionOfPerpendicularPlane) {
EXPECT_TRUE(projected_rect.IsEmpty());
}
+TEST(MathUtilTest, ProjectionOfAlmostPerpendicularPlane) {
+ // In this case, the m33() element of the transform becomes almost zero, which
+ // could cause a divide-by-zero when projecting points/quads.
+
+ gfx::Transform transform;
+ // The transform is from an actual test page:
+ // [ +1.0000 +0.0000 -1.0000 +3144132.0000
+ // +0.0000 +1.0000 +0.0000 +0.0000
+ // +16331238407143424.0000 +0.0000 -0.0000 +51346917453137000267776.0000
+ // +0.0000 +0.0000 +0.0000 +1.0000 ]
+ transform.MakeIdentity();
+ transform.matrix().set(0, 2, static_cast<SkMScalar>(-1));
+ transform.matrix().set(0, 3, static_cast<SkMScalar>(3144132.0));
+ transform.matrix().set(2, 0, static_cast<SkMScalar>(16331238407143424.0));
+ transform.matrix().set(2, 2, static_cast<SkMScalar>(-1e-33));
+ transform.matrix().set(2, 3,
+ static_cast<SkMScalar>(51346917453137000267776.0));
+
+ gfx::RectF rect = gfx::RectF(0, 0, 1, 1);
+ gfx::RectF projected_rect = MathUtil::ProjectClippedRect(transform, rect);
+
+ EXPECT_EQ(0, projected_rect.x());
+ EXPECT_EQ(0, projected_rect.y());
+ EXPECT_TRUE(projected_rect.IsEmpty()) << projected_rect.ToString();
+}
+
TEST(MathUtilTest, EnclosingClippedRectUsesCorrectInitialBounds) {
HomogeneousCoordinate h1(-100, -100, 0, 1);
HomogeneousCoordinate h2(-10, -10, 0, 1);
@@ -193,6 +219,104 @@ TEST(MathUtilTest, MapEnclosedRectWith2dAxisAlignedTransform) {
EXPECT_EQ(gfx::Rect(2, 4, 6, 8), output);
}
+TEST(MathUtilTest, MapEnclosingRectWithLargeTransforms) {
+ gfx::Rect input(1, 2, 100, 200);
+ gfx::Rect output;
+
+ gfx::Transform large_x_scale;
+ large_x_scale.Scale(SkDoubleToMScalar(1e37), 1.0);
+
+ gfx::Transform infinite_x_scale;
+ infinite_x_scale = large_x_scale * large_x_scale;
+
+ gfx::Transform large_y_scale;
+ large_y_scale.Scale(1.0, SkDoubleToMScalar(1e37));
+
+ gfx::Transform infinite_y_scale;
+ infinite_y_scale = large_y_scale * large_y_scale;
+
+ gfx::Transform rotation;
+ rotation.RotateAboutYAxis(170.0);
+
+ int max_int = std::numeric_limits<int>::max();
+
+ output = MathUtil::MapEnclosingClippedRect(large_x_scale, input);
+ EXPECT_EQ(gfx::Rect(max_int, 2, 0, 200), output);
+
+ output = MathUtil::MapEnclosingClippedRect(large_x_scale * rotation, input);
+ EXPECT_EQ(gfx::Rect(), output);
+
+ output = MathUtil::MapEnclosingClippedRect(infinite_x_scale, input);
+ EXPECT_EQ(gfx::Rect(max_int, 2, 0, 200), output);
+
+ output =
+ MathUtil::MapEnclosingClippedRect(infinite_x_scale * rotation, input);
+ EXPECT_EQ(gfx::Rect(), output);
+
+ output = MathUtil::MapEnclosingClippedRect(large_y_scale, input);
+ EXPECT_EQ(gfx::Rect(1, max_int, 100, 0), output);
+
+ output = MathUtil::MapEnclosingClippedRect(large_y_scale * rotation, input);
+ EXPECT_EQ(gfx::Rect(-100, max_int, 100, 0), output);
+
+ output = MathUtil::MapEnclosingClippedRect(infinite_y_scale, input);
+ EXPECT_EQ(gfx::Rect(1, max_int, 100, 0), output);
+
+ output =
+ MathUtil::MapEnclosingClippedRect(infinite_y_scale * rotation, input);
+ EXPECT_EQ(gfx::Rect(), output);
+}
+
+TEST(MathUtilTest, ProjectEnclosingRectWithLargeTransforms) {
+ gfx::Rect input(1, 2, 100, 200);
+ gfx::Rect output;
+
+ gfx::Transform large_x_scale;
+ large_x_scale.Scale(SkDoubleToMScalar(1e37), 1.0);
+
+ gfx::Transform infinite_x_scale;
+ infinite_x_scale = large_x_scale * large_x_scale;
+
+ gfx::Transform large_y_scale;
+ large_y_scale.Scale(1.0, SkDoubleToMScalar(1e37));
+
+ gfx::Transform infinite_y_scale;
+ infinite_y_scale = large_y_scale * large_y_scale;
+
+ gfx::Transform rotation;
+ rotation.RotateAboutYAxis(170.0);
+
+ int max_int = std::numeric_limits<int>::max();
+
+ output = MathUtil::ProjectEnclosingClippedRect(large_x_scale, input);
+ EXPECT_EQ(gfx::Rect(max_int, 2, 0, 200), output);
+
+ output =
+ MathUtil::ProjectEnclosingClippedRect(large_x_scale * rotation, input);
+ EXPECT_EQ(gfx::Rect(), output);
+
+ output = MathUtil::ProjectEnclosingClippedRect(infinite_x_scale, input);
+ EXPECT_EQ(gfx::Rect(max_int, 2, 0, 200), output);
+
+ output =
+ MathUtil::ProjectEnclosingClippedRect(infinite_x_scale * rotation, input);
+ EXPECT_EQ(gfx::Rect(), output);
+
+ output = MathUtil::ProjectEnclosingClippedRect(large_y_scale, input);
+ EXPECT_EQ(gfx::Rect(1, max_int, 100, 0), output);
+
+ output =
+ MathUtil::ProjectEnclosingClippedRect(large_y_scale * rotation, input);
+ EXPECT_EQ(gfx::Rect(-103, max_int, 102, 0), output);
+
+ output = MathUtil::ProjectEnclosingClippedRect(infinite_y_scale, input);
+ EXPECT_EQ(gfx::Rect(1, max_int, 100, 0), output);
+
+ output =
+ MathUtil::ProjectEnclosingClippedRect(infinite_y_scale * rotation, input);
+ EXPECT_EQ(gfx::Rect(), output);
+}
+
TEST(MathUtilTest, RoundUp) {
for (int multiplier = 1; multiplier <= 10; ++multiplier) {
// Try attempts in descending order, so that we can
@@ -201,7 +325,7 @@ TEST(MathUtilTest, RoundUp) {
for (int attempt = 5 * multiplier; attempt >= -5 * multiplier; --attempt) {
if ((attempt % multiplier) == 0)
correct = attempt;
- EXPECT_EQ(correct, MathUtil::RoundUp(attempt, multiplier))
+ EXPECT_EQ(correct, MathUtil::UncheckedRoundUp(attempt, multiplier))
<< "attempt=" << attempt << " multiplier=" << multiplier;
}
}
@@ -213,14 +337,20 @@ TEST(MathUtilTest, RoundUp) {
for (unsigned attempt = 5 * multiplier; attempt > 0; --attempt) {
if ((attempt % multiplier) == 0)
correct = attempt;
- EXPECT_EQ(correct, MathUtil::RoundUp(attempt, multiplier))
+ EXPECT_EQ(correct, MathUtil::UncheckedRoundUp(attempt, multiplier))
<< "attempt=" << attempt << " multiplier=" << multiplier;
}
- EXPECT_EQ(0u, MathUtil::RoundUp(0u, multiplier))
+ EXPECT_EQ(0u, MathUtil::UncheckedRoundUp(0u, multiplier))
<< "attempt=0 multiplier=" << multiplier;
}
}
+TEST(MathUtilTest, RoundUpOverflow) {
+ // Rounding up 123 by 50 is 150, which overflows int8_t, but fits in uint8_t.
+ EXPECT_FALSE(MathUtil::VerifyRoundup<int8_t>(123, 50));
+ EXPECT_TRUE(MathUtil::VerifyRoundup<uint8_t>(123, 50));
+}
+
TEST(MathUtilTest, RoundDown) {
for (int multiplier = 1; multiplier <= 10; ++multiplier) {
// Try attempts in ascending order, so that we can
@@ -229,7 +359,7 @@ TEST(MathUtilTest, RoundDown) {
for (int attempt = -5 * multiplier; attempt <= 5 * multiplier; ++attempt) {
if ((attempt % multiplier) == 0)
correct = attempt;
- EXPECT_EQ(correct, MathUtil::RoundDown(attempt, multiplier))
+ EXPECT_EQ(correct, MathUtil::UncheckedRoundDown(attempt, multiplier))
<< "attempt=" << attempt << " multiplier=" << multiplier;
}
}
@@ -241,11 +371,18 @@ TEST(MathUtilTest, RoundDown) {
for (unsigned attempt = 0; attempt <= 5 * multiplier; ++attempt) {
if ((attempt % multiplier) == 0)
correct = attempt;
- EXPECT_EQ(correct, MathUtil::RoundDown(attempt, multiplier))
+ EXPECT_EQ(correct, MathUtil::UncheckedRoundDown(attempt, multiplier))
<< "attempt=" << attempt << " multiplier=" << multiplier;
}
}
}
+TEST(MathUtilTest, RoundDownUnderflow) {
+ // Rounding down -123 by 50 is -150, which underflows int8_t, but fits in
+ // int16_t.
+ EXPECT_FALSE(MathUtil::VerifyRoundDown<int8_t>(-123, 50));
+ EXPECT_TRUE(MathUtil::VerifyRoundDown<int16_t>(-123, 50));
+}
+
} // namespace
} // namespace cc
diff --git a/chromium/cc/base/random_access_list_container.h b/chromium/cc/base/random_access_list_container.h
new file mode 100644
index 00000000000..b2baf3064d2
--- /dev/null
+++ b/chromium/cc/base/random_access_list_container.h
@@ -0,0 +1,94 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_BASE_RANDOM_ACCESS_LIST_CONTAINER_H_
+#define CC_BASE_RANDOM_ACCESS_LIST_CONTAINER_H_
+
+#include <vector>
+
+#include "base/logging.h"
+#include "cc/base/list_container_helper.h"
+
+namespace cc {
+
+// RandomAccessListContainer is a container similar to ListContainer (see
+// list_container.h), but it allows random access into its elements via
+// operator[]. In order to have efficient support for random access, some
+// functionality is not available for RandomAccessListContainers, such as
+// insert/deletes in the middle of the list.
+template <class BaseElementType>
+class RandomAccessListContainer {
+ public:
+ // BaseElementType is the type of raw pointers this class hands out; however,
+ // its derived classes might require different memory sizes.
+ // max_size_for_derived_class the largest memory size required for all the
+ // derived classes to use for allocation.
+ explicit RandomAccessListContainer(size_t max_size_for_derived_class)
+ : helper_(max_size_for_derived_class) {}
+
+ // This constructor reserves the requested memory up front so only a single
+ // allocation is needed. When num_of_elements_to_reserve_for is zero, use the
+ // default size.
+ RandomAccessListContainer(size_t max_size_for_derived_class,
+ size_t num_of_elements_to_reserve_for)
+ : helper_(max_size_for_derived_class, num_of_elements_to_reserve_for) {
+ items_.reserve(num_of_elements_to_reserve_for);
+ }
+
+ ~RandomAccessListContainer() {
+ for (BaseElementType* item : items_)
+ item->~BaseElementType();
+ }
+
+ void clear() {
+ for (BaseElementType* item : items_)
+ item->~BaseElementType();
+ helper_.clear();
+ items_.clear();
+ }
+
+ bool empty() const { return helper_.empty(); }
+ size_t size() const { return helper_.size(); }
+ size_t GetCapacityInBytes() const { return helper_.GetCapacityInBytes(); }
+
+ template <typename DerivedElementType>
+ DerivedElementType* AllocateAndConstruct() {
+ auto* value =
+ new (helper_.Allocate(sizeof(DerivedElementType))) DerivedElementType;
+ items_.push_back(value);
+ return value;
+ }
+
+ void RemoveLast() {
+ items_.back()->~BaseElementType();
+ items_.pop_back();
+ helper_.RemoveLast();
+ }
+
+ const BaseElementType* operator[](size_t index) const {
+ DCHECK_GE(index, 0u);
+ DCHECK_LT(index, items_.size());
+ return items_[index];
+ }
+
+ BaseElementType* operator[](size_t index) {
+ DCHECK_GE(index, 0u);
+ DCHECK_LT(index, items_.size());
+ return items_[index];
+ }
+
+ // Note that although BaseElementType objects can change, the pointer itself
+ // (in the vector) cannot. So this class only supports a const iterator.
+ using ConstIterator = typename std::vector<BaseElementType*>::const_iterator;
+ ConstIterator begin() const { return items_.begin(); }
+ ConstIterator end() const { return items_.end(); }
+
+ private:
+ ListContainerHelper helper_;
+ std::vector<BaseElementType*> items_;
+};
+
+} // namespace cc
+
+#endif // CC_BASE_RANDOM_ACCESS_LIST_CONTAINER_H_
diff --git a/chromium/cc/base/random_access_list_container_unittest.cc b/chromium/cc/base/random_access_list_container_unittest.cc
new file mode 100644
index 00000000000..78004b4a8f4
--- /dev/null
+++ b/chromium/cc/base/random_access_list_container_unittest.cc
@@ -0,0 +1,107 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/base/random_access_list_container.h"
+
+#include <algorithm>
+#include <vector>
+
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace cc {
+namespace {
+
+class Base {
+ public:
+ virtual ~Base() {}
+ int get_value() const { return value_; }
+
+ protected:
+ explicit Base(int value) : value_(value) {}
+
+ int value_;
+};
+
+const int kMagicNumberOne = 1;
+const int kMagicNumberTwo = 2;
+const int kMagicNumberThree = 3;
+
+class Derived1 : public Base {
+ public:
+ Derived1() : Base(kMagicNumberOne) {}
+};
+
+class Derived2 : public Base {
+ public:
+ Derived2() : Base(kMagicNumberTwo) {}
+};
+
+class Derived3 : public Base {
+ public:
+ Derived3() : Base(kMagicNumberThree) {}
+};
+
+size_t LargestDerivedElementSize() {
+ static_assert(sizeof(Derived1) >= sizeof(Derived2),
+ "Derived2 is larger than Derived1");
+ static_assert(sizeof(Derived1) >= sizeof(Derived3),
+ "Derived3 is larger than Derived1");
+ return sizeof(Derived1);
+}
+
+TEST(RandomAccessListContainerTest, RandomAccess) {
+ RandomAccessListContainer<Base> list(LargestDerivedElementSize(), 1);
+
+ list.AllocateAndConstruct<Derived1>();
+ list.AllocateAndConstruct<Derived2>();
+ list.AllocateAndConstruct<Derived3>();
+ list.AllocateAndConstruct<Derived1>();
+ list.AllocateAndConstruct<Derived2>();
+ list.AllocateAndConstruct<Derived3>();
+
+ EXPECT_EQ(kMagicNumberOne, list[0]->get_value());
+ EXPECT_EQ(kMagicNumberTwo, list[1]->get_value());
+ EXPECT_EQ(kMagicNumberThree, list[2]->get_value());
+ EXPECT_EQ(kMagicNumberOne, list[3]->get_value());
+ EXPECT_EQ(kMagicNumberTwo, list[4]->get_value());
+ EXPECT_EQ(kMagicNumberThree, list[5]->get_value());
+
+ list.RemoveLast();
+ list.RemoveLast();
+ list.RemoveLast();
+
+ EXPECT_EQ(kMagicNumberOne, list[0]->get_value());
+ EXPECT_EQ(kMagicNumberTwo, list[1]->get_value());
+ EXPECT_EQ(kMagicNumberThree, list[2]->get_value());
+
+ list.AllocateAndConstruct<Derived3>();
+ list.AllocateAndConstruct<Derived2>();
+ list.AllocateAndConstruct<Derived1>();
+
+ EXPECT_EQ(kMagicNumberOne, list[0]->get_value());
+ EXPECT_EQ(kMagicNumberTwo, list[1]->get_value());
+ EXPECT_EQ(kMagicNumberThree, list[2]->get_value());
+ EXPECT_EQ(kMagicNumberThree, list[3]->get_value());
+ EXPECT_EQ(kMagicNumberTwo, list[4]->get_value());
+ EXPECT_EQ(kMagicNumberOne, list[5]->get_value());
+}
+
+TEST(RandomAccessListContainerTest, Clear) {
+ RandomAccessListContainer<Base> list(LargestDerivedElementSize(), 1);
+
+ list.AllocateAndConstruct<Derived1>();
+ list.AllocateAndConstruct<Derived2>();
+
+ EXPECT_EQ(kMagicNumberOne, list[0]->get_value());
+ EXPECT_EQ(kMagicNumberTwo, list[1]->get_value());
+
+ list.clear();
+ list.AllocateAndConstruct<Derived3>();
+
+ EXPECT_EQ(kMagicNumberThree, list[0]->get_value());
+}
+
+} // namespace
+} // namespace cc
diff --git a/chromium/cc/base/rtree.cc b/chromium/cc/base/rtree.cc
new file mode 100644
index 00000000000..ca64e87dfe1
--- /dev/null
+++ b/chromium/cc/base/rtree.cc
@@ -0,0 +1,111 @@
+// Copyright (c) 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/base/rtree.h"
+
+#include <cmath>
+
+#include "base/logging.h"
+
+namespace cc {
+
+RTree::RTree() : num_data_elements_(0u) {}
+
+RTree::~RTree() {}
+
+RTree::Node* RTree::AllocateNodeAtLevel(int level) {
+ nodes_.push_back(Node());
+ Node& node = nodes_.back();
+ node.num_children = 0;
+ node.level = level;
+ return &node;
+}
+
+RTree::Branch RTree::BuildRecursive(std::vector<Branch>* branches, int level) {
+ // Only one branch. It will be the root.
+ if (branches->size() == 1)
+ return (*branches)[0];
+
+ // TODO(vmpstr): Investigate if branches should be sorted in y.
+ // The comment from Skia reads:
+ // We might sort our branches here, but we expect Blink gives us a reasonable
+ // x,y order. Skipping a call to sort (in Y) here resulted in a 17% win for
+ // recording with negligible difference in playback speed.
+ int num_branches = static_cast<int>(branches->size() / MAX_CHILDREN);
+ int remainder = static_cast<int>(branches->size() % MAX_CHILDREN);
+
+ if (remainder > 0) {
+ ++num_branches;
+ // If the remainder isn't enough to fill a node, we'll add fewer nodes to
+ // other branches.
+ if (remainder >= MIN_CHILDREN)
+ remainder = 0;
+ else
+ remainder = MIN_CHILDREN - remainder;
+ }
+
+ int num_strips = static_cast<int>(std::ceil(std::sqrt(num_branches)));
+ int num_tiles = static_cast<int>(
+ std::ceil(num_branches / static_cast<float>(num_strips)));
+ size_t current_branch = 0;
+
+ size_t new_branch_index = 0;
+ for (int i = 0; i < num_strips; ++i) {
+ // Might be worth sorting by X here too.
+ for (int j = 0; j < num_tiles && current_branch < branches->size(); ++j) {
+ int increment_by = MAX_CHILDREN;
+ if (remainder != 0) {
+ // if need be, omit some nodes to make up for remainder
+ if (remainder <= MAX_CHILDREN - MIN_CHILDREN) {
+ increment_by -= remainder;
+ remainder = 0;
+ } else {
+ increment_by = MIN_CHILDREN;
+ remainder -= MAX_CHILDREN - MIN_CHILDREN;
+ }
+ }
+ Node* node = AllocateNodeAtLevel(level);
+ node->num_children = 1;
+ node->children[0] = (*branches)[current_branch];
+
+ Branch branch;
+ branch.bounds = (*branches)[current_branch].bounds;
+ branch.subtree = node;
+ ++current_branch;
+ for (int k = 1; k < increment_by && current_branch < branches->size();
+ ++k) {
+ branch.bounds.Union((*branches)[current_branch].bounds);
+ node->children[k] = (*branches)[current_branch];
+ ++node->num_children;
+ ++current_branch;
+ }
+ DCHECK_LT(new_branch_index, current_branch);
+ (*branches)[new_branch_index] = branch;
+ ++new_branch_index;
+ }
+ }
+ branches->resize(new_branch_index);
+ return BuildRecursive(branches, level + 1);
+}
+
+void RTree::Search(const gfx::RectF& query,
+ std::vector<size_t>* results) const {
+ if (num_data_elements_ > 0 && query.Intersects(root_.bounds))
+ SearchRecursive(root_.subtree, query, results);
+}
+
+void RTree::SearchRecursive(Node* node,
+ const gfx::RectF& query,
+ std::vector<size_t>* results) const {
+ for (uint16_t i = 0; i < node->num_children; ++i) {
+ if (query.Intersects(node->children[i].bounds)) {
+ if (node->level == 0)
+ results->push_back(node->children[i].index);
+ else
+ SearchRecursive(node->children[i].subtree, query, results);
+ }
+ }
+}
+
+} // namespace cc
diff --git a/chromium/cc/base/rtree.h b/chromium/cc/base/rtree.h
new file mode 100644
index 00000000000..f765c3534ff
--- /dev/null
+++ b/chromium/cc/base/rtree.h
@@ -0,0 +1,118 @@
+// Copyright (c) 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_BASE_RTREE_H_
+#define CC_BASE_RTREE_H_
+
+#include <deque>
+#include <vector>
+
+#include "cc/base/cc_export.h"
+#include "ui/gfx/geometry/rect_f.h"
+
+namespace cc {
+
+// The following description and most of the implementation is borrowed from
+// Skia's SkRTree implementation.
+//
+// An R-Tree implementation. In short, it is a balanced n-ary tree containing a
+// hierarchy of bounding rectangles.
+//
+// It only supports bulk-loading, i.e. creation from a batch of bounding
+// rectangles. This performs a bottom-up bulk load using the STR
+// (sort-tile-recursive) algorithm.
+//
+// Things to do: Experiment with other bulk-load algorithms (in particular the
+// Hilbert pack variant, which groups rects by position on the Hilbert curve, is
+// probably worth a look). There also exist top-down bulk load variants
+// (VAMSplit, TopDownGreedy, etc).
+//
+// For more details see:
+//
+// Beckmann, N.; Kriegel, H. P.; Schneider, R.; Seeger, B. (1990).
+// "The R*-tree: an efficient and robust access method for points and
+// rectangles"
+class CC_EXPORT RTree {
+ public:
+ RTree();
+ ~RTree();
+
+ template <typename Container, typename Functor>
+ void Build(const Container& items, const Functor& bounds_getter) {
+ DCHECK_EQ(0u, num_data_elements_);
+
+ std::vector<Branch> branches;
+ branches.reserve(items.size());
+
+ for (size_t i = 0; i < items.size(); i++) {
+ const gfx::RectF& bounds = bounds_getter(items[i]);
+ if (bounds.IsEmpty())
+ continue;
+
+ branches.push_back(Branch());
+ Branch& branch = branches.back();
+ branch.bounds = bounds;
+ branch.index = i;
+ }
+
+ num_data_elements_ = branches.size();
+ if (num_data_elements_ == 1u) {
+ Node* node = AllocateNodeAtLevel(0);
+ node->num_children = 1;
+ node->children[0] = branches[0];
+ root_.subtree = node;
+ root_.bounds = branches[0].bounds;
+ } else if (num_data_elements_ > 1u) {
+ root_ = BuildRecursive(&branches, 0);
+ }
+ }
+
+ template <typename Container>
+ void Build(const Container& items) {
+ Build(items, [](const gfx::RectF& bounds) { return bounds; });
+ }
+
+ void Search(const gfx::RectF& query, std::vector<size_t>* results) const;
+
+ private:
+ // These values were empirically determined to produce reasonable performance
+ // in most cases.
+ enum { MIN_CHILDREN = 6, MAX_CHILDREN = 11 };
+
+ struct Node;
+ struct Branch {
+ // When the node level is 0, then the node is a leaf and the branch has a
+ // valid index pointing to an element in the vector that was used to build
+ // this rtree. When the level is not 0, it's an internal node and it has a
+ // valid subtree pointer.
+ union {
+ Node* subtree;
+ size_t index;
+ };
+ gfx::RectF bounds;
+ };
+
+ struct Node {
+ uint16_t num_children;
+ uint16_t level;
+ Branch children[MAX_CHILDREN];
+ };
+
+ void SearchRecursive(Node* root,
+ const gfx::RectF& query,
+ std::vector<size_t>* results) const;
+
+ // Consumes the input array.
+ Branch BuildRecursive(std::vector<Branch>* branches, int level);
+ Node* AllocateNodeAtLevel(int level);
+
+ // This is the count of data elements (rather than total nodes in the tree)
+ size_t num_data_elements_;
+ Branch root_;
+ std::deque<Node> nodes_;
+};
+
+} // namespace cc
+
+#endif // CC_BASE_RTREE_H_
diff --git a/chromium/cc/base/rtree_unittest.cc b/chromium/cc/base/rtree_unittest.cc
new file mode 100644
index 00000000000..b703a173b8e
--- /dev/null
+++ b/chromium/cc/base/rtree_unittest.cc
@@ -0,0 +1,68 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/base/rtree.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace cc {
+
+TEST(RTreeTest, NoOverlap) {
+ std::vector<gfx::RectF> rects;
+ for (int y = 0; y < 50; ++y) {
+ for (int x = 0; x < 50; ++x) {
+ rects.push_back(gfx::RectF(x, y, 1.f, 1.f));
+ }
+ }
+
+ RTree rtree;
+ rtree.Build(rects);
+
+ std::vector<size_t> results;
+ rtree.Search(gfx::RectF(0.f, 0.f, 50.f, 50.f), &results);
+ ASSERT_EQ(2500u, results.size());
+ for (size_t i = 0; i < 2500; ++i) {
+ ASSERT_EQ(results[i], i);
+ }
+
+ results.clear();
+ rtree.Search(gfx::RectF(0.f, 0.f, 50.f, 49.f), &results);
+ ASSERT_EQ(2450u, results.size());
+ for (size_t i = 0; i < 2450; ++i) {
+ ASSERT_EQ(results[i], i);
+ }
+
+ results.clear();
+ rtree.Search(gfx::RectF(5.2f, 6.3f, 0.1f, 0.2f), &results);
+ ASSERT_EQ(1u, results.size());
+ EXPECT_EQ(6u * 50 + 5u, results[0]);
+}
+
+TEST(RTreeTest, Overlap) {
+ std::vector<gfx::RectF> rects;
+ for (int h = 1; h <= 50; ++h) {
+ for (int w = 1; w <= 50; ++w) {
+ rects.push_back(gfx::RectF(0, 0, w, h));
+ }
+ }
+
+ RTree rtree;
+ rtree.Build(rects);
+
+ std::vector<size_t> results;
+ rtree.Search(gfx::RectF(0.f, 0.f, 1.f, 1.f), &results);
+ ASSERT_EQ(2500u, results.size());
+ for (size_t i = 0; i < 2500; ++i) {
+ ASSERT_EQ(results[i], i);
+ }
+
+ results.clear();
+ rtree.Search(gfx::RectF(0.f, 49.f, 1.f, 1.f), &results);
+ ASSERT_EQ(50u, results.size());
+ for (size_t i = 0; i < 50; ++i) {
+ EXPECT_EQ(results[i], 2450u + i);
+ }
+}
+
+} // namespace cc
diff --git a/chromium/cc/base/sidecar_list_container.h b/chromium/cc/base/sidecar_list_container.h
deleted file mode 100644
index 5135ab1d7d2..00000000000
--- a/chromium/cc/base/sidecar_list_container.h
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CC_BASE_SIDECAR_LIST_CONTAINER_H_
-#define CC_BASE_SIDECAR_LIST_CONTAINER_H_
-
-#include "base/logging.h"
-#include "cc/base/list_container.h"
-
-namespace cc {
-
-// This is a container, based on ListContainer, which allocates space in a
-// contiguous block for objects subclassing BaseElementType, as well as an
-// additional "sidecar" of opaque type.
-//
-// It takes a pointer to a function for tearing down sidecar objects, which must
-// free any resources held by it as its memory will be deallocated by the
-// container afterwards. When an element is constructed, callers are expected to
-// immediately construct the sidecar as well (such that the sidecar destroyer
-// will run safely and successfully).
-//
-// TODO(jbroman): It would be nice to be clear about the memory alignment
-// constraints here, but that probably requires closer inspection of
-// ListContainer first.
-template <class BaseElementType>
-class SidecarListContainer {
- public:
- using SidecarDestroyer = void (*)(void* sidecar);
- using Iterator = typename ListContainer<BaseElementType>::Iterator;
- using ConstIterator = typename ListContainer<BaseElementType>::ConstIterator;
- using ReverseIterator =
- typename ListContainer<BaseElementType>::ReverseIterator;
- using ConstReverseIterator =
- typename ListContainer<BaseElementType>::ConstReverseIterator;
-
- explicit SidecarListContainer(size_t max_size_for_derived_class,
- size_t max_size_for_sidecar,
- size_t num_of_elements_to_reserve_for,
- SidecarDestroyer destroyer)
- : list_(max_size_for_derived_class + max_size_for_sidecar,
- num_of_elements_to_reserve_for),
- destroyer_(destroyer),
- sidecar_offset_(max_size_for_derived_class) {}
- ~SidecarListContainer() { DestroyAllSidecars(); }
-
- // Forward most of the reading logic to ListContainer.
- bool empty() const { return list_.empty(); }
- size_t size() const { return list_.size(); }
- size_t GetCapacityInBytes() const { return list_.GetCapacityInBytes(); }
- ConstIterator begin() const { return list_.begin(); }
- ConstIterator end() const { return list_.end(); }
-
- template <typename DerivedElementType>
- DerivedElementType* AllocateAndConstruct() {
- return list_.template AllocateAndConstruct<DerivedElementType>();
- }
- template <typename DerivedElementType>
- DerivedElementType* AllocateAndCopyFrom(const DerivedElementType* source) {
- return list_.template AllocateAndCopyFrom<DerivedElementType>(source);
- }
-
- void clear() {
- DestroyAllSidecars();
- list_.clear();
- }
-
- void RemoveLast() {
- destroyer_(GetSidecar(*list_.rbegin()));
- list_.RemoveLast();
- }
-
- // This permits a client to exchange a pointer to an element to a pointer to
- // its corresponding sidecar.
- void* GetSidecar(BaseElementType* element) {
- DCHECK_GT(sidecar_offset_, 0u);
- return reinterpret_cast<char*>(element) + sidecar_offset_;
- }
- const void* GetSidecar(const BaseElementType* element) {
- DCHECK_GT(sidecar_offset_, 0u);
- return reinterpret_cast<const char*>(element) + sidecar_offset_;
- }
-
- private:
- void DestroyAllSidecars() {
- for (auto* element : list_)
- destroyer_(GetSidecar(element));
- }
-
- ListContainer<BaseElementType> list_;
- SidecarDestroyer destroyer_;
- size_t sidecar_offset_;
-};
-
-} // namespace cc
-
-#endif // CC_BASE_SIDECAR_LIST_CONTAINER_H_
diff --git a/chromium/cc/base/sidecar_list_container_unittest.cc b/chromium/cc/base/sidecar_list_container_unittest.cc
deleted file mode 100644
index 0012014df8f..00000000000
--- a/chromium/cc/base/sidecar_list_container_unittest.cc
+++ /dev/null
@@ -1,198 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cc/base/sidecar_list_container.h"
-
-#include <algorithm>
-
-#include "base/logging.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace cc {
-namespace {
-
-const size_t kNumInitiallyReservedElements = 2;
-const size_t kNumElementsForTest = 100;
-
-class DestructionNotifier {
- public:
- DestructionNotifier() : flag_(nullptr) {}
- explicit DestructionNotifier(bool* flag) { set_flag(flag); }
- ~DestructionNotifier() {
- if (flag_)
- *flag_ = true;
- }
- void set_flag(bool* flag) {
- if (flag)
- DCHECK(!*flag);
- flag_ = flag;
- }
-
- private:
- bool* flag_;
-};
-
-class TestElement {
- public:
- TestElement() {}
- virtual ~TestElement() {}
- void set_destruction_flag(bool* flag) { notifier_.set_flag(flag); }
-
- private:
- DestructionNotifier notifier_;
-};
-
-class DerivedTestElement : public TestElement {
- public:
- int additional_field = 0;
-};
-
-class TestSidecar {
- public:
- TestSidecar() {}
- explicit TestSidecar(bool* destruction_flag) : notifier_(destruction_flag) {}
-
- static void Destroy(void* sidecar) {
- static_cast<TestSidecar*>(sidecar)->~TestSidecar();
- }
-
- protected:
- virtual ~TestSidecar() {}
-
- private:
- DestructionNotifier notifier_;
-};
-
-class DerivedTestSidecar : public TestSidecar {
- public:
- DerivedTestSidecar() {}
- explicit DerivedTestSidecar(bool* destruction_flag)
- : TestSidecar(destruction_flag) {}
- int additional_field = 0;
-
- private:
- ~DerivedTestSidecar() override {}
-};
-
-class TestContainer : public SidecarListContainer<TestElement> {
- public:
- TestContainer()
- : SidecarListContainer(
- std::max(sizeof(TestElement), sizeof(DerivedTestElement)),
- std::max(sizeof(TestSidecar), sizeof(DerivedTestSidecar)),
- kNumInitiallyReservedElements,
- &TestSidecar::Destroy) {}
-};
-
-TEST(SidecarListContainerTest, Destructor) {
- bool element_destroyed = false;
- bool sidecar_destroyed = false;
-
- {
- TestContainer container;
-
- TestElement* element = container.AllocateAndConstruct<TestElement>();
- TestSidecar* sidecar =
- new (container.GetSidecar(element)) TestSidecar(&sidecar_destroyed);
- element->set_destruction_flag(&element_destroyed);
-
- // They shouldn't be destroyed yet. And they shouldn't overlap in memory.
- ASSERT_FALSE(element_destroyed);
- ASSERT_FALSE(sidecar_destroyed);
- ASSERT_GE(reinterpret_cast<char*>(sidecar),
- reinterpret_cast<char*>(element) + sizeof(TestElement));
- }
-
- // They should, however, be destroyed when going out of scope.
- ASSERT_TRUE(element_destroyed);
- ASSERT_TRUE(sidecar_destroyed);
-}
-
-TEST(SidecarListContainerTest, Clear) {
- bool element_destroyed = false;
- bool sidecar_destroyed = false;
-
- TestContainer container;
-
- TestElement* element = container.AllocateAndConstruct<TestElement>();
- new (container.GetSidecar(element)) TestSidecar(&sidecar_destroyed);
- element->set_destruction_flag(&element_destroyed);
-
- // They shouldn't be destroyed yet.
- ASSERT_FALSE(element_destroyed);
- ASSERT_FALSE(sidecar_destroyed);
-
- // They should, however, be destroyed after clearing.
- container.clear();
- EXPECT_TRUE(element_destroyed);
- EXPECT_TRUE(sidecar_destroyed);
-}
-
-TEST(SidecarListContainerTest, DerivedTypes) {
- bool element_destroyed = false;
- bool sidecar_destroyed = false;
-
- {
- TestContainer container;
-
- DerivedTestElement* element =
- container.AllocateAndConstruct<DerivedTestElement>();
- DerivedTestSidecar* sidecar = new (container.GetSidecar(element))
- DerivedTestSidecar(&sidecar_destroyed);
- element->set_destruction_flag(&element_destroyed);
- element->additional_field = 12;
- sidecar->additional_field = 13;
-
- // They shouldn't be destroyed yet.
- ASSERT_FALSE(element_destroyed);
- ASSERT_FALSE(sidecar_destroyed);
- }
-
- // They should, however, be destroyed when going out of scope.
- EXPECT_TRUE(element_destroyed);
- EXPECT_TRUE(sidecar_destroyed);
-}
-
-TEST(SidecarListContainerTest, AddingAndRemovingElements) {
- TestContainer container;
- EXPECT_TRUE(container.empty());
- EXPECT_EQ(0u, container.size());
- EXPECT_EQ(container.end(), container.begin());
-
- for (size_t i = 1; i <= kNumElementsForTest; i++) {
- TestElement* element = container.AllocateAndConstruct<TestElement>();
- new (container.GetSidecar(element)) TestSidecar();
-
- ASSERT_FALSE(container.empty());
- ASSERT_EQ(i, container.size());
- ASSERT_NE(container.end(), container.begin());
- }
-
- size_t num_elements = 0;
- for (const auto* element : container) {
- (void)element;
- num_elements++;
- }
- EXPECT_EQ(kNumElementsForTest, num_elements);
-
- container.clear();
- EXPECT_TRUE(container.empty());
- EXPECT_EQ(0u, container.size());
- EXPECT_EQ(container.end(), container.begin());
-}
-
-TEST(SidecarListContainerTest, RemoveLast) {
- // We need only ensure that the sidecar is also destroyed on RemoveLast.
- // The rest is logic already present in ListContainer.
- bool sidecar_destroyed = false;
- TestContainer container;
- TestElement* element = container.AllocateAndConstruct<TestElement>();
- new (container.GetSidecar(element)) TestSidecar(&sidecar_destroyed);
- ASSERT_FALSE(sidecar_destroyed);
- container.RemoveLast();
- ASSERT_TRUE(sidecar_destroyed);
-}
-
-} // namespace
-} // namespace cc
diff --git a/chromium/cc/base/switches.cc b/chromium/cc/base/switches.cc
index 0a27205d9d3..0db15030d5b 100644
--- a/chromium/cc/base/switches.cc
+++ b/chromium/cc/base/switches.cc
@@ -35,18 +35,6 @@ const char kTopControlsShowThreshold[] = "top-controls-show-threshold";
// complete, such as --slow-down-raster-scale-factor=25.
const char kSlowDownRasterScaleFactor[] = "slow-down-raster-scale-factor";
-// Max tiles allowed for each tilings interest area.
-const char kMaxTilesForInterestArea[] = "max-tiles-for-interest-area";
-
-// The amount of unused resource memory compositor is allowed to keep around.
-const char kMaxUnusedResourceMemoryUsagePercentage[] =
- "max-unused-resource-memory-usage-percentage";
-
-// Causes the compositor to render to textures which are then sent to the parent
-// through the texture mailbox mechanism.
-// Requires --enable-compositor-frame-message.
-const char kCompositeToMailbox[] = "composite-to-mailbox";
-
// Check that property changes during paint do not occur.
const char kStrictLayerPropertyChangeChecking[] =
"strict-layer-property-change-checking";
diff --git a/chromium/cc/base/switches.h b/chromium/cc/base/switches.h
index cd5e3678824..3bce14e892e 100644
--- a/chromium/cc/base/switches.h
+++ b/chromium/cc/base/switches.h
@@ -24,9 +24,6 @@ CC_EXPORT extern const char kJankInsteadOfCheckerboard[];
CC_EXPORT extern const char kTopControlsHideThreshold[];
CC_EXPORT extern const char kTopControlsShowThreshold[];
CC_EXPORT extern const char kSlowDownRasterScaleFactor[];
-CC_EXPORT extern const char kCompositeToMailbox[];
-CC_EXPORT extern const char kMaxTilesForInterestArea[];
-CC_EXPORT extern const char kMaxUnusedResourceMemoryUsagePercentage[];
CC_EXPORT extern const char kStrictLayerPropertyChangeChecking[];
CC_EXPORT extern const char kEnablePropertyTreeVerification[];
diff --git a/chromium/cc/blink/BUILD.gn b/chromium/cc/blink/BUILD.gn
index c39498fe73a..4ee8862a9ae 100644
--- a/chromium/cc/blink/BUILD.gn
+++ b/chromium/cc/blink/BUILD.gn
@@ -43,8 +43,6 @@ component("blink") {
"web_layer_impl.h",
"web_layer_impl_fixed_bounds.cc",
"web_layer_impl_fixed_bounds.h",
- "web_nine_patch_layer_impl.cc",
- "web_nine_patch_layer_impl.h",
"web_scroll_offset_animation_curve_impl.cc",
"web_scroll_offset_animation_curve_impl.h",
"web_scrollbar_layer_impl.cc",
diff --git a/chromium/cc/blink/cc_blink.gyp b/chromium/cc/blink/cc_blink.gyp
index c55213c5444..dc01cae456a 100644
--- a/chromium/cc/blink/cc_blink.gyp
+++ b/chromium/cc/blink/cc_blink.gyp
@@ -59,8 +59,6 @@
'web_layer_impl.h',
'web_layer_impl_fixed_bounds.cc',
'web_layer_impl_fixed_bounds.h',
- 'web_nine_patch_layer_impl.cc',
- 'web_nine_patch_layer_impl.h',
'web_scroll_offset_animation_curve_impl.cc',
'web_scroll_offset_animation_curve_impl.h',
'web_scrollbar_layer_impl.cc',
diff --git a/chromium/cc/blink/web_animation_impl.h b/chromium/cc/blink/web_animation_impl.h
index 585df6a827a..c1bdb0efdfa 100644
--- a/chromium/cc/blink/web_animation_impl.h
+++ b/chromium/cc/blink/web_animation_impl.h
@@ -26,26 +26,26 @@ class WebCompositorAnimationImpl : public blink::WebCompositorAnimation {
TargetProperty target,
int animation_id,
int group_id);
- virtual ~WebCompositorAnimationImpl();
+ ~WebCompositorAnimationImpl() override;
// blink::WebCompositorAnimation implementation
- virtual int id();
- virtual int group();
- virtual TargetProperty targetProperty() const;
- virtual double iterations() const;
- virtual void setIterations(double iterations);
- virtual double iterationStart() const;
- virtual void setIterationStart(double iteration_start);
- virtual double startTime() const;
- virtual void setStartTime(double monotonic_time);
- virtual double timeOffset() const;
- virtual void setTimeOffset(double monotonic_time);
- virtual Direction direction() const;
- virtual void setDirection(Direction);
- virtual double playbackRate() const;
- virtual void setPlaybackRate(double playback_rate);
- virtual FillMode fillMode() const;
- virtual void setFillMode(blink::WebCompositorAnimation::FillMode fill_mode);
+ int id() override;
+ int group() override;
+ TargetProperty targetProperty() const override;
+ double iterations() const override;
+ void setIterations(double iterations) override;
+ double iterationStart() const override;
+ void setIterationStart(double iteration_start) override;
+ double startTime() const override;
+ void setStartTime(double monotonic_time) override;
+ double timeOffset() const override;
+ void setTimeOffset(double monotonic_time) override;
+ Direction direction() const override;
+ void setDirection(Direction) override;
+ double playbackRate() const override;
+ void setPlaybackRate(double playback_rate) override;
+ FillMode fillMode() const override;
+ void setFillMode(blink::WebCompositorAnimation::FillMode fill_mode) override;
scoped_ptr<cc::Animation> PassAnimation();
private:
diff --git a/chromium/cc/blink/web_compositor_animation_player_impl.h b/chromium/cc/blink/web_compositor_animation_player_impl.h
index 9b5ea4475e7..1d4879b45a4 100644
--- a/chromium/cc/blink/web_compositor_animation_player_impl.h
+++ b/chromium/cc/blink/web_compositor_animation_player_impl.h
@@ -22,19 +22,19 @@ class WebCompositorAnimationPlayerImpl
: public blink::WebCompositorAnimationPlayer {
public:
CC_BLINK_EXPORT WebCompositorAnimationPlayerImpl();
- virtual ~WebCompositorAnimationPlayerImpl();
+ ~WebCompositorAnimationPlayerImpl() override;
CC_BLINK_EXPORT cc::AnimationPlayer* animation_player() const;
// blink::WebCompositorAnimationPlayer implementation
- virtual void setAnimationDelegate(
- blink::WebCompositorAnimationDelegate* delegate);
- virtual void attachLayer(blink::WebLayer* web_layer);
- virtual void detachLayer();
- virtual bool isLayerAttached() const;
- virtual void addAnimation(blink::WebCompositorAnimation* animation);
- virtual void removeAnimation(int animation_id);
- virtual void pauseAnimation(int animation_id, double time_offset);
+ void setAnimationDelegate(
+ blink::WebCompositorAnimationDelegate* delegate) override;
+ void attachLayer(blink::WebLayer* web_layer) override;
+ void detachLayer() override;
+ bool isLayerAttached() const override;
+ void addAnimation(blink::WebCompositorAnimation* animation) override;
+ void removeAnimation(int animation_id) override;
+ void pauseAnimation(int animation_id, double time_offset) override;
private:
scoped_refptr<cc::AnimationPlayer> animation_player_;
diff --git a/chromium/cc/blink/web_compositor_animation_timeline_impl.h b/chromium/cc/blink/web_compositor_animation_timeline_impl.h
index 65d05d83157..624d29fcec7 100644
--- a/chromium/cc/blink/web_compositor_animation_timeline_impl.h
+++ b/chromium/cc/blink/web_compositor_animation_timeline_impl.h
@@ -24,15 +24,15 @@ class WebCompositorAnimationTimelineImpl
: public blink::WebCompositorAnimationTimeline {
public:
CC_BLINK_EXPORT explicit WebCompositorAnimationTimelineImpl();
- virtual ~WebCompositorAnimationTimelineImpl();
+ ~WebCompositorAnimationTimelineImpl() override;
CC_BLINK_EXPORT cc::AnimationTimeline* animation_timeline() const;
// blink::WebCompositorAnimationTimeline implementation
- virtual void playerAttached(
- const blink::WebCompositorAnimationPlayerClient& client);
- virtual void playerDestroyed(
- const blink::WebCompositorAnimationPlayerClient& client);
+ void playerAttached(
+ const blink::WebCompositorAnimationPlayerClient& client) override;
+ void playerDestroyed(
+ const blink::WebCompositorAnimationPlayerClient& client) override;
private:
scoped_refptr<cc::AnimationTimeline> animation_timeline_;
diff --git a/chromium/cc/blink/web_compositor_support_impl.cc b/chromium/cc/blink/web_compositor_support_impl.cc
index 13a868d7ebf..74c5491d7db 100644
--- a/chromium/cc/blink/web_compositor_support_impl.cc
+++ b/chromium/cc/blink/web_compositor_support_impl.cc
@@ -17,7 +17,6 @@
#include "cc/blink/web_float_animation_curve_impl.h"
#include "cc/blink/web_image_layer_impl.h"
#include "cc/blink/web_layer_impl.h"
-#include "cc/blink/web_nine_patch_layer_impl.h"
#include "cc/blink/web_scroll_offset_animation_curve_impl.h"
#include "cc/blink/web_scrollbar_layer_impl.h"
#include "cc/blink/web_transform_animation_curve_impl.h"
@@ -38,7 +37,6 @@ using blink::WebFilterAnimationCurve;
using blink::WebFilterOperations;
using blink::WebFloatAnimationCurve;
using blink::WebImageLayer;
-using blink::WebNinePatchLayer;
using blink::WebLayer;
using blink::WebScrollbar;
using blink::WebScrollbarLayer;
@@ -74,10 +72,6 @@ blink::WebImageLayer* WebCompositorSupportImpl::createImageLayer() {
return new WebImageLayerImpl();
}
-blink::WebNinePatchLayer* WebCompositorSupportImpl::createNinePatchLayer() {
- return new WebNinePatchLayerImpl();
-}
-
WebScrollbarLayer* WebCompositorSupportImpl::createScrollbarLayer(
WebScrollbar* scrollbar,
WebScrollbarThemePainter painter,
@@ -133,10 +127,6 @@ WebFilterOperations* WebCompositorSupportImpl::createFilterOperations() {
return new WebFilterOperationsImpl();
}
-WebDisplayItemList* WebCompositorSupportImpl::createDisplayItemList() {
- return new WebDisplayItemListImpl();
-}
-
WebCompositorAnimationPlayer*
WebCompositorSupportImpl::createAnimationPlayer() {
return new WebCompositorAnimationPlayerImpl();
diff --git a/chromium/cc/blink/web_compositor_support_impl.h b/chromium/cc/blink/web_compositor_support_impl.h
index 989966989e6..0547a1492aa 100644
--- a/chromium/cc/blink/web_compositor_support_impl.h
+++ b/chromium/cc/blink/web_compositor_support_impl.h
@@ -23,43 +23,40 @@ class CC_BLINK_EXPORT WebCompositorSupportImpl
: public NON_EXPORTED_BASE(blink::WebCompositorSupport) {
public:
WebCompositorSupportImpl();
- virtual ~WebCompositorSupportImpl();
+ ~WebCompositorSupportImpl() override;
- virtual blink::WebLayer* createLayer();
- virtual blink::WebContentLayer* createContentLayer(
- blink::WebContentLayerClient* client);
- virtual blink::WebExternalTextureLayer* createExternalTextureLayer(
- blink::WebExternalTextureLayerClient* client);
- virtual blink::WebImageLayer* createImageLayer();
- virtual blink::WebNinePatchLayer* createNinePatchLayer();
- virtual blink::WebScrollbarLayer* createScrollbarLayer(
+ blink::WebLayer* createLayer() override;
+ blink::WebContentLayer* createContentLayer(
+ blink::WebContentLayerClient* client) override;
+ blink::WebExternalTextureLayer* createExternalTextureLayer(
+ blink::WebExternalTextureLayerClient* client) override;
+ blink::WebImageLayer* createImageLayer() override;
+ blink::WebScrollbarLayer* createScrollbarLayer(
blink::WebScrollbar* scrollbar,
blink::WebScrollbarThemePainter painter,
- blink::WebScrollbarThemeGeometry*);
- virtual blink::WebScrollbarLayer* createSolidColorScrollbarLayer(
+ blink::WebScrollbarThemeGeometry*) override;
+ blink::WebScrollbarLayer* createSolidColorScrollbarLayer(
blink::WebScrollbar::Orientation orientation,
int thumb_thickness,
int track_start,
- bool is_left_side_vertical_scrollbar);
- virtual blink::WebCompositorAnimation* createAnimation(
+ bool is_left_side_vertical_scrollbar) override;
+ blink::WebCompositorAnimation* createAnimation(
const blink::WebCompositorAnimationCurve& curve,
blink::WebCompositorAnimation::TargetProperty target,
int group_id,
- int animation_id);
- virtual blink::WebFilterAnimationCurve* createFilterAnimationCurve();
- virtual blink::WebFloatAnimationCurve* createFloatAnimationCurve();
- virtual blink::WebScrollOffsetAnimationCurve*
- createScrollOffsetAnimationCurve(
- blink::WebFloatPoint target_value,
- blink::WebCompositorAnimationCurve::TimingFunctionType
- timing_function);
- virtual blink::WebTransformAnimationCurve* createTransformAnimationCurve();
- virtual blink::WebTransformOperations* createTransformOperations();
- virtual blink::WebFilterOperations* createFilterOperations();
- virtual blink::WebDisplayItemList* createDisplayItemList();
+ int animation_id) override;
+ blink::WebFilterAnimationCurve* createFilterAnimationCurve() override;
+ blink::WebFloatAnimationCurve* createFloatAnimationCurve() override;
+ blink::WebScrollOffsetAnimationCurve* createScrollOffsetAnimationCurve(
+ blink::WebFloatPoint target_value,
+ blink::WebCompositorAnimationCurve::TimingFunctionType timing_function)
+ override;
+ blink::WebTransformAnimationCurve* createTransformAnimationCurve() override;
+ blink::WebTransformOperations* createTransformOperations() override;
+ blink::WebFilterOperations* createFilterOperations() override;
- virtual blink::WebCompositorAnimationPlayer* createAnimationPlayer();
- virtual blink::WebCompositorAnimationTimeline* createAnimationTimeline();
+ blink::WebCompositorAnimationPlayer* createAnimationPlayer() override;
+ blink::WebCompositorAnimationTimeline* createAnimationTimeline() override;
private:
DISALLOW_COPY_AND_ASSIGN(WebCompositorSupportImpl);
diff --git a/chromium/cc/blink/web_content_layer_impl.cc b/chromium/cc/blink/web_content_layer_impl.cc
index c9ca473cf8e..4ccd7639086 100644
--- a/chromium/cc/blink/web_content_layer_impl.cc
+++ b/chromium/cc/blink/web_content_layer_impl.cc
@@ -54,10 +54,6 @@ void WebContentLayerImpl::setDoubleSided(bool double_sided) {
layer_->layer()->SetDoubleSided(double_sided);
}
-void WebContentLayerImpl::setDrawCheckerboardForMissingTiles(bool enable) {
- layer_->layer()->SetDrawCheckerboardForMissingTiles(enable);
-}
-
void WebContentLayerImpl::PaintContents(
SkCanvas* canvas,
const gfx::Rect& clip,
@@ -89,4 +85,8 @@ bool WebContentLayerImpl::FillsBoundsCompletely() const {
return false;
}
+size_t WebContentLayerImpl::GetApproximateUnsharedMemoryUsage() const {
+ return client_->approximateUnsharedMemoryUsage();
+}
+
} // namespace cc_blink
diff --git a/chromium/cc/blink/web_content_layer_impl.h b/chromium/cc/blink/web_content_layer_impl.h
index 3e7b55c59a4..fb0fcb77732 100644
--- a/chromium/cc/blink/web_content_layer_impl.h
+++ b/chromium/cc/blink/web_content_layer_impl.h
@@ -28,12 +28,11 @@ class WebContentLayerImpl : public blink::WebContentLayer,
CC_BLINK_EXPORT explicit WebContentLayerImpl(blink::WebContentLayerClient*);
// WebContentLayer implementation.
- virtual blink::WebLayer* layer();
- virtual void setDoubleSided(bool double_sided);
- virtual void setDrawCheckerboardForMissingTiles(bool checkerboard);
+ blink::WebLayer* layer() override;
+ void setDoubleSided(bool double_sided) override;
protected:
- virtual ~WebContentLayerImpl();
+ ~WebContentLayerImpl() override;
// ContentLayerClient implementation.
void PaintContents(SkCanvas* canvas,
@@ -43,6 +42,7 @@ class WebContentLayerImpl : public blink::WebContentLayer,
const gfx::Rect& clip,
PaintingControlSetting painting_control) override;
bool FillsBoundsCompletely() const override;
+ size_t GetApproximateUnsharedMemoryUsage() const override;
scoped_ptr<WebLayerImpl> layer_;
blink::WebContentLayerClient* client_;
diff --git a/chromium/cc/blink/web_display_item_list_impl.cc b/chromium/cc/blink/web_display_item_list_impl.cc
index ffcd5e35df7..79d0972299e 100644
--- a/chromium/cc/blink/web_display_item_list_impl.cc
+++ b/chromium/cc/blink/web_display_item_list_impl.cc
@@ -31,7 +31,8 @@ namespace {
scoped_refptr<cc::DisplayItemList> CreateUncachedDisplayItemListForBlink() {
cc::DisplayItemListSettings settings;
settings.use_cached_picture = false;
- return cc::DisplayItemList::CreateWithoutCachedPicture(settings);
+ gfx::Rect layer_rect;
+ return cc::DisplayItemList::Create(layer_rect, settings);
}
} // namespace
diff --git a/chromium/cc/blink/web_display_item_list_impl.h b/chromium/cc/blink/web_display_item_list_impl.h
index d45d7d36d48..438bee0ded3 100644
--- a/chromium/cc/blink/web_display_item_list_impl.h
+++ b/chromium/cc/blink/web_display_item_list_impl.h
@@ -38,33 +38,33 @@ class WebDisplayItemListImpl : public blink::WebDisplayItemList {
CC_BLINK_EXPORT WebDisplayItemListImpl();
CC_BLINK_EXPORT explicit WebDisplayItemListImpl(
cc::DisplayItemList* display_list);
- virtual ~WebDisplayItemListImpl();
+ ~WebDisplayItemListImpl() override;
// blink::WebDisplayItemList implementation.
- virtual void appendDrawingItem(const SkPicture*);
- virtual void appendClipItem(
+ void appendDrawingItem(const SkPicture*) override;
+ void appendClipItem(
const blink::WebRect& clip_rect,
- const blink::WebVector<SkRRect>& rounded_clip_rects);
- virtual void appendEndClipItem();
- virtual void appendClipPathItem(const SkPath& clip_path,
- SkRegion::Op clip_op,
- bool antialias);
- virtual void appendEndClipPathItem();
- virtual void appendFloatClipItem(const blink::WebFloatRect& clip_rect);
- virtual void appendEndFloatClipItem();
- virtual void appendTransformItem(const SkMatrix44& matrix);
- virtual void appendEndTransformItem();
- virtual void appendCompositingItem(float opacity,
- SkXfermode::Mode,
- SkRect* bounds,
- SkColorFilter*);
- virtual void appendEndCompositingItem();
- virtual void appendFilterItem(const blink::WebFilterOperations& filters,
- const blink::WebFloatRect& bounds);
- virtual void appendEndFilterItem();
- virtual void appendScrollItem(const blink::WebSize& scrollOffset,
- ScrollContainerId);
- virtual void appendEndScrollItem();
+ const blink::WebVector<SkRRect>& rounded_clip_rects) override;
+ void appendEndClipItem() override;
+ void appendClipPathItem(const SkPath& clip_path,
+ SkRegion::Op clip_op,
+ bool antialias) override;
+ void appendEndClipPathItem() override;
+ void appendFloatClipItem(const blink::WebFloatRect& clip_rect) override;
+ void appendEndFloatClipItem() override;
+ void appendTransformItem(const SkMatrix44& matrix) override;
+ void appendEndTransformItem() override;
+ void appendCompositingItem(float opacity,
+ SkXfermode::Mode,
+ SkRect* bounds,
+ SkColorFilter*) override;
+ void appendEndCompositingItem() override;
+ void appendFilterItem(const blink::WebFilterOperations& filters,
+ const blink::WebFloatRect& bounds) override;
+ void appendEndFilterItem() override;
+ void appendScrollItem(const blink::WebSize& scrollOffset,
+ ScrollContainerId) override;
+ void appendEndScrollItem() override;
private:
scoped_refptr<cc::DisplayItemList> display_item_list_;
diff --git a/chromium/cc/blink/web_external_bitmap_impl.cc b/chromium/cc/blink/web_external_bitmap_impl.cc
index e2c67e42996..2301896027b 100644
--- a/chromium/cc/blink/web_external_bitmap_impl.cc
+++ b/chromium/cc/blink/web_external_bitmap_impl.cc
@@ -37,6 +37,13 @@ blink::WebSize WebExternalBitmapImpl::size() {
}
uint8* WebExternalBitmapImpl::pixels() {
+ if (!shared_bitmap_) {
+ // crbug.com/520417: not sure why a non-null WebExternalBitmap is
+ // being passed to prepareMailbox when the shared_bitmap_ is null.
+ // Best hypothesis is that the bitmap is zero-sized.
+ DCHECK(size_.isEmpty());
+ return nullptr;
+ }
return shared_bitmap_->pixels();
}
diff --git a/chromium/cc/blink/web_external_texture_layer_impl.cc b/chromium/cc/blink/web_external_texture_layer_impl.cc
index e9700c6c6d9..acc7df44e63 100644
--- a/chromium/cc/blink/web_external_texture_layer_impl.cc
+++ b/chromium/cc/blink/web_external_texture_layer_impl.cc
@@ -57,10 +57,6 @@ void WebExternalTextureLayerImpl::setBlendBackgroundColor(bool blend) {
static_cast<TextureLayer*>(layer_->layer())->SetBlendBackgroundColor(blend);
}
-void WebExternalTextureLayerImpl::setRateLimitContext(bool rate_limit) {
- static_cast<TextureLayer*>(layer_->layer())->SetRateLimitContext(rate_limit);
-}
-
void WebExternalTextureLayerImpl::setNearestNeighbor(bool nearest_neighbor) {
static_cast<TextureLayer*>(layer_->layer())
->SetNearestNeighbor(nearest_neighbor);
diff --git a/chromium/cc/blink/web_external_texture_layer_impl.h b/chromium/cc/blink/web_external_texture_layer_impl.h
index a12a00b8e37..5425ae53413 100644
--- a/chromium/cc/blink/web_external_texture_layer_impl.h
+++ b/chromium/cc/blink/web_external_texture_layer_impl.h
@@ -35,16 +35,15 @@ class WebExternalTextureLayerImpl
public:
CC_BLINK_EXPORT explicit WebExternalTextureLayerImpl(
blink::WebExternalTextureLayerClient*);
- virtual ~WebExternalTextureLayerImpl();
+ ~WebExternalTextureLayerImpl() override;
// blink::WebExternalTextureLayer implementation.
- virtual blink::WebLayer* layer();
- virtual void clearTexture();
- virtual void setOpaque(bool opaque);
- virtual void setPremultipliedAlpha(bool premultiplied);
- virtual void setBlendBackgroundColor(bool blend);
- virtual void setRateLimitContext(bool rate_limit);
- virtual void setNearestNeighbor(bool nearest_neighbor);
+ blink::WebLayer* layer() override;
+ void clearTexture() override;
+ void setOpaque(bool opaque) override;
+ void setPremultipliedAlpha(bool premultiplied) override;
+ void setBlendBackgroundColor(bool blend) override;
+ void setNearestNeighbor(bool nearest_neighbor) override;
// TextureLayerClient implementation.
bool PrepareTextureMailbox(
diff --git a/chromium/cc/blink/web_filter_animation_curve_impl.h b/chromium/cc/blink/web_filter_animation_curve_impl.h
index 93dae4ed052..e922ccbde22 100644
--- a/chromium/cc/blink/web_filter_animation_curve_impl.h
+++ b/chromium/cc/blink/web_filter_animation_curve_impl.h
@@ -23,30 +23,30 @@ namespace cc_blink {
class WebFilterAnimationCurveImpl : public blink::WebFilterAnimationCurve {
public:
CC_BLINK_EXPORT WebFilterAnimationCurveImpl();
- virtual ~WebFilterAnimationCurveImpl();
+ ~WebFilterAnimationCurveImpl() override;
// blink::WebCompositorAnimationCurve implementation.
- virtual AnimationCurveType type() const;
+ AnimationCurveType type() const override;
// blink::WebFilterAnimationCurve implementation.
- virtual void add(const blink::WebFilterKeyframe& keyframe,
- TimingFunctionType type);
- virtual void add(const blink::WebFilterKeyframe& keyframe,
- double x1,
- double y1,
- double x2,
- double y2);
- virtual void add(const blink::WebFilterKeyframe& keyframe,
- int steps,
- float steps_start_offset);
- virtual void setLinearTimingFunction();
- virtual void setCubicBezierTimingFunction(TimingFunctionType);
- virtual void setCubicBezierTimingFunction(double x1,
- double y1,
- double x2,
- double y2);
- virtual void setStepsTimingFunction(int number_of_steps,
- float steps_start_offset);
+ void add(const blink::WebFilterKeyframe& keyframe,
+ TimingFunctionType type) override;
+ void add(const blink::WebFilterKeyframe& keyframe,
+ double x1,
+ double y1,
+ double x2,
+ double y2) override;
+ void add(const blink::WebFilterKeyframe& keyframe,
+ int steps,
+ float steps_start_offset) override;
+ void setLinearTimingFunction() override;
+ void setCubicBezierTimingFunction(TimingFunctionType) override;
+ void setCubicBezierTimingFunction(double x1,
+ double y1,
+ double x2,
+ double y2) override;
+ void setStepsTimingFunction(int number_of_steps,
+ float steps_start_offset) override;
scoped_ptr<cc::AnimationCurve> CloneToAnimationCurve() const;
diff --git a/chromium/cc/blink/web_filter_operations_impl.h b/chromium/cc/blink/web_filter_operations_impl.h
index 36c3b4565cf..d1746cea9af 100644
--- a/chromium/cc/blink/web_filter_operations_impl.h
+++ b/chromium/cc/blink/web_filter_operations_impl.h
@@ -14,30 +14,30 @@ namespace cc_blink {
class WebFilterOperationsImpl : public blink::WebFilterOperations {
public:
CC_BLINK_EXPORT WebFilterOperationsImpl();
- virtual ~WebFilterOperationsImpl();
+ ~WebFilterOperationsImpl() override;
const cc::FilterOperations& AsFilterOperations() const;
// Implementation of blink::WebFilterOperations methods
- virtual void appendGrayscaleFilter(float amount);
- virtual void appendSepiaFilter(float amount);
- virtual void appendSaturateFilter(float amount);
- virtual void appendHueRotateFilter(float amount);
- virtual void appendInvertFilter(float amount);
- virtual void appendBrightnessFilter(float amount);
- virtual void appendContrastFilter(float amount);
- virtual void appendOpacityFilter(float amount);
- virtual void appendBlurFilter(float amount);
- virtual void appendDropShadowFilter(blink::WebPoint offset,
- float std_deviation,
- blink::WebColor color);
- virtual void appendColorMatrixFilter(SkScalar matrix[20]);
- virtual void appendZoomFilter(float amount, int inset);
- virtual void appendSaturatingBrightnessFilter(float amount);
- virtual void appendReferenceFilter(SkImageFilter* image_filter);
-
- virtual void clear();
- virtual bool isEmpty() const;
+ void appendGrayscaleFilter(float amount) override;
+ void appendSepiaFilter(float amount) override;
+ void appendSaturateFilter(float amount) override;
+ void appendHueRotateFilter(float amount) override;
+ void appendInvertFilter(float amount) override;
+ void appendBrightnessFilter(float amount) override;
+ void appendContrastFilter(float amount) override;
+ void appendOpacityFilter(float amount) override;
+ void appendBlurFilter(float amount) override;
+ void appendDropShadowFilter(blink::WebPoint offset,
+ float std_deviation,
+ blink::WebColor color) override;
+ void appendColorMatrixFilter(SkScalar matrix[20]) override;
+ void appendZoomFilter(float amount, int inset) override;
+ void appendSaturatingBrightnessFilter(float amount) override;
+ void appendReferenceFilter(SkImageFilter* image_filter) override;
+
+ void clear() override;
+ bool isEmpty() const override;
private:
cc::FilterOperations filter_operations_;
diff --git a/chromium/cc/blink/web_float_animation_curve_impl.h b/chromium/cc/blink/web_float_animation_curve_impl.h
index b5a97aa5db6..42bab59f82b 100644
--- a/chromium/cc/blink/web_float_animation_curve_impl.h
+++ b/chromium/cc/blink/web_float_animation_curve_impl.h
@@ -23,33 +23,33 @@ namespace cc_blink {
class WebFloatAnimationCurveImpl : public blink::WebFloatAnimationCurve {
public:
CC_BLINK_EXPORT WebFloatAnimationCurveImpl();
- virtual ~WebFloatAnimationCurveImpl();
+ ~WebFloatAnimationCurveImpl() override;
// WebCompositorAnimationCurve implementation.
- virtual AnimationCurveType type() const;
+ AnimationCurveType type() const override;
// WebFloatAnimationCurve implementation.
- virtual void add(const blink::WebFloatKeyframe& keyframe);
- virtual void add(const blink::WebFloatKeyframe& keyframe,
- TimingFunctionType type);
- virtual void add(const blink::WebFloatKeyframe& keyframe,
- double x1,
- double y1,
- double x2,
- double y2);
- virtual void add(const blink::WebFloatKeyframe& keyframe,
- int steps,
- float steps_start_offset);
- virtual void setLinearTimingFunction();
- virtual void setCubicBezierTimingFunction(TimingFunctionType);
- virtual void setCubicBezierTimingFunction(double x1,
- double y1,
- double x2,
- double y2);
- virtual void setStepsTimingFunction(int number_of_steps,
- float steps_start_offset);
+ void add(const blink::WebFloatKeyframe& keyframe) override;
+ void add(const blink::WebFloatKeyframe& keyframe,
+ TimingFunctionType type) override;
+ void add(const blink::WebFloatKeyframe& keyframe,
+ double x1,
+ double y1,
+ double x2,
+ double y2) override;
+ void add(const blink::WebFloatKeyframe& keyframe,
+ int steps,
+ float steps_start_offset) override;
+ void setLinearTimingFunction() override;
+ void setCubicBezierTimingFunction(TimingFunctionType) override;
+ void setCubicBezierTimingFunction(double x1,
+ double y1,
+ double x2,
+ double y2) override;
+ void setStepsTimingFunction(int number_of_steps,
+ float steps_start_offset) override;
- virtual float getValue(double time) const;
+ float getValue(double time) const override;
scoped_ptr<cc::AnimationCurve> CloneToAnimationCurve() const;
diff --git a/chromium/cc/blink/web_image_layer_impl.cc b/chromium/cc/blink/web_image_layer_impl.cc
index 55e28ef8152..efa4242b59e 100644
--- a/chromium/cc/blink/web_image_layer_impl.cc
+++ b/chromium/cc/blink/web_image_layer_impl.cc
@@ -7,6 +7,7 @@
#include "cc/blink/web_layer_impl.h"
#include "cc/blink/web_layer_impl_fixed_bounds.h"
#include "cc/layers/picture_image_layer.h"
+#include "third_party/skia/include/core/SkImage.h"
namespace cc_blink {
@@ -22,10 +23,12 @@ blink::WebLayer* WebImageLayerImpl::layer() {
return layer_.get();
}
-void WebImageLayerImpl::setImageBitmap(const SkBitmap& bitmap) {
- static_cast<cc::PictureImageLayer*>(layer_->layer())->SetBitmap(bitmap);
+void WebImageLayerImpl::setImage(const SkImage* image) {
+ skia::RefPtr<const SkImage> imageRef = skia::SharePtr(image);
+ static_cast<cc::PictureImageLayer*>(layer_->layer())
+ ->SetImage(imageRef.Pass());
static_cast<WebLayerImplFixedBounds*>(layer_.get())
- ->SetFixedBounds(gfx::Size(bitmap.width(), bitmap.height()));
+ ->SetFixedBounds(gfx::Size(image->width(), image->height()));
}
void WebImageLayerImpl::setNearestNeighbor(bool nearest_neighbor) {
diff --git a/chromium/cc/blink/web_image_layer_impl.h b/chromium/cc/blink/web_image_layer_impl.h
index 48c31ea80c7..74a8e76b5b1 100644
--- a/chromium/cc/blink/web_image_layer_impl.h
+++ b/chromium/cc/blink/web_image_layer_impl.h
@@ -8,7 +8,6 @@
#include "base/memory/scoped_ptr.h"
#include "cc/blink/cc_blink_export.h"
#include "third_party/WebKit/public/platform/WebImageLayer.h"
-#include "third_party/skia/include/core/SkBitmap.h"
namespace cc_blink {
@@ -17,12 +16,12 @@ class WebLayerImpl;
class WebImageLayerImpl : public blink::WebImageLayer {
public:
CC_BLINK_EXPORT WebImageLayerImpl();
- virtual ~WebImageLayerImpl();
+ ~WebImageLayerImpl() override;
// blink::WebImageLayer implementation.
- virtual blink::WebLayer* layer();
- virtual void setImageBitmap(const SkBitmap& bitmap);
- virtual void setNearestNeighbor(bool nearest_neighbor);
+ blink::WebLayer* layer() override;
+ void setImage(const SkImage* image) override;
+ void setNearestNeighbor(bool nearest_neighbor) override;
private:
scoped_ptr<WebLayerImpl> layer_;
diff --git a/chromium/cc/blink/web_layer_impl.cc b/chromium/cc/blink/web_layer_impl.cc
index 3ba9431171d..48f27008e98 100644
--- a/chromium/cc/blink/web_layer_impl.cc
+++ b/chromium/cc/blink/web_layer_impl.cc
@@ -51,18 +51,19 @@ base::LazyInstance<cc::LayerSettings> g_layer_settings =
} // namespace
-WebLayerImpl::WebLayerImpl() : layer_(Layer::Create(LayerSettings())) {
+WebLayerImpl::WebLayerImpl()
+ : layer_(Layer::Create(LayerSettings())), contents_opaque_is_fixed_(false) {
web_layer_client_ = nullptr;
layer_->SetLayerClient(this);
}
-WebLayerImpl::WebLayerImpl(scoped_refptr<Layer> layer) : layer_(layer) {
+WebLayerImpl::WebLayerImpl(scoped_refptr<Layer> layer)
+ : layer_(layer), contents_opaque_is_fixed_(false) {
web_layer_client_ = nullptr;
layer_->SetLayerClient(this);
}
WebLayerImpl::~WebLayerImpl() {
- layer_->ClearRenderSurface();
if (animation_delegate_adapter_.get())
layer_->set_layer_animation_delegate(nullptr);
web_layer_client_ = nullptr;
@@ -162,6 +163,8 @@ bool WebLayerImpl::isRootForIsolatedGroup() {
}
void WebLayerImpl::setOpaque(bool opaque) {
+ if (contents_opaque_is_fixed_)
+ return;
layer_->SetContentsOpaque(opaque);
}
@@ -537,4 +540,8 @@ Layer* WebLayerImpl::layer() const {
return layer_.get();
}
+void WebLayerImpl::SetContentsOpaqueIsFixed(bool fixed) {
+ contents_opaque_is_fixed_ = fixed;
+}
+
} // namespace cc_blink
diff --git a/chromium/cc/blink/web_layer_impl.h b/chromium/cc/blink/web_layer_impl.h
index eb049b8e711..44ef02e2210 100644
--- a/chromium/cc/blink/web_layer_impl.h
+++ b/chromium/cc/blink/web_layer_impl.h
@@ -50,7 +50,7 @@ class WebLayerImpl : public blink::WebLayer, public cc::LayerClient {
public:
CC_BLINK_EXPORT WebLayerImpl();
CC_BLINK_EXPORT explicit WebLayerImpl(scoped_refptr<cc::Layer>);
- virtual ~WebLayerImpl();
+ ~WebLayerImpl() override;
CC_BLINK_EXPORT static void SetLayerSettings(
const cc::LayerSettings& settings);
@@ -58,100 +58,108 @@ class WebLayerImpl : public blink::WebLayer, public cc::LayerClient {
CC_BLINK_EXPORT cc::Layer* layer() const;
+ // If set to true, content opaqueness cannot be changed using setOpaque.
+ // However, it can still be modified using SetContentsOpaque on the
+ // cc::Layer.
+ CC_BLINK_EXPORT void SetContentsOpaqueIsFixed(bool fixed);
+
// WebLayer implementation.
- virtual int id() const;
- virtual void invalidateRect(const blink::WebRect&);
- virtual void invalidate();
- virtual void addChild(blink::WebLayer* child);
- virtual void insertChild(blink::WebLayer* child, size_t index);
- virtual void replaceChild(blink::WebLayer* reference,
- blink::WebLayer* new_layer);
- virtual void removeFromParent();
- virtual void removeAllChildren();
- virtual void setBounds(const blink::WebSize& bounds);
- virtual blink::WebSize bounds() const;
- virtual void setMasksToBounds(bool masks_to_bounds);
- virtual bool masksToBounds() const;
- virtual void setMaskLayer(blink::WebLayer* mask);
- virtual void setReplicaLayer(blink::WebLayer* replica);
- virtual void setOpacity(float opacity);
- virtual float opacity() const;
- virtual void setBlendMode(blink::WebBlendMode blend_mode);
- virtual blink::WebBlendMode blendMode() const;
- virtual void setIsRootForIsolatedGroup(bool root);
- virtual bool isRootForIsolatedGroup();
- virtual void setOpaque(bool opaque);
- virtual bool opaque() const;
- virtual void setPosition(const blink::WebFloatPoint& position);
- virtual blink::WebFloatPoint position() const;
- virtual void setTransform(const SkMatrix44& transform);
- virtual void setTransformOrigin(const blink::WebFloatPoint3D& point);
- virtual blink::WebFloatPoint3D transformOrigin() const;
- virtual SkMatrix44 transform() const;
- virtual void setDrawsContent(bool draws_content);
- virtual bool drawsContent() const;
- virtual void setShouldFlattenTransform(bool flatten);
- virtual void setRenderingContext(int context);
- virtual void setUseParentBackfaceVisibility(bool visible);
- virtual void setBackgroundColor(blink::WebColor color);
- virtual blink::WebColor backgroundColor() const;
- virtual void setFilters(const blink::WebFilterOperations& filters);
- virtual void setBackgroundFilters(const blink::WebFilterOperations& filters);
- virtual void setAnimationDelegate(
- blink::WebCompositorAnimationDelegate* delegate);
- virtual bool addAnimation(blink::WebCompositorAnimation* animation);
- virtual void removeAnimation(int animation_id);
- virtual void removeAnimation(int animation_id,
- blink::WebCompositorAnimation::TargetProperty);
- virtual void pauseAnimation(int animation_id, double time_offset);
- virtual bool hasActiveAnimation();
- virtual void setForceRenderSurface(bool force);
- virtual void setScrollPositionDouble(blink::WebDoublePoint position);
- virtual blink::WebDoublePoint scrollPositionDouble() const;
- virtual void setScrollCompensationAdjustment(blink::WebDoublePoint position);
- virtual void setScrollClipLayer(blink::WebLayer* clip_layer);
- virtual bool scrollable() const;
- virtual void setUserScrollable(bool horizontal, bool vertical);
- virtual bool userScrollableHorizontal() const;
- virtual bool userScrollableVertical() const;
- virtual void setHaveWheelEventHandlers(bool have_wheel_event_handlers);
- virtual bool haveWheelEventHandlers() const;
- virtual void setHaveScrollEventHandlers(bool have_scroll_event_handlers);
- virtual bool haveScrollEventHandlers() const;
- virtual void setShouldScrollOnMainThread(bool scroll_on_main);
- virtual bool shouldScrollOnMainThread() const;
- virtual void setNonFastScrollableRegion(
- const blink::WebVector<blink::WebRect>& region);
- virtual blink::WebVector<blink::WebRect> nonFastScrollableRegion() const;
- virtual void setTouchEventHandlerRegion(
- const blink::WebVector<blink::WebRect>& region);
- virtual blink::WebVector<blink::WebRect> touchEventHandlerRegion() const;
- virtual void setScrollBlocksOn(blink::WebScrollBlocksOn);
- virtual blink::WebScrollBlocksOn scrollBlocksOn() const;
- virtual void setFrameTimingRequests(
- const blink::WebVector<std::pair<int64_t, blink::WebRect>>& requests);
- virtual blink::WebVector<std::pair<int64_t, blink::WebRect>>
- frameTimingRequests() const;
- virtual void setIsContainerForFixedPositionLayers(bool is_container);
- virtual bool isContainerForFixedPositionLayers() const;
- virtual void setPositionConstraint(
- const blink::WebLayerPositionConstraint& constraint);
- virtual blink::WebLayerPositionConstraint positionConstraint() const;
- virtual void setScrollClient(blink::WebLayerScrollClient* client);
- virtual bool isOrphan() const;
- virtual void setWebLayerClient(blink::WebLayerClient* client);
+ int id() const override;
+ void invalidateRect(const blink::WebRect&) override;
+ void invalidate() override;
+ void addChild(blink::WebLayer* child) override;
+ void insertChild(blink::WebLayer* child, size_t index) override;
+ void replaceChild(blink::WebLayer* reference,
+ blink::WebLayer* new_layer) override;
+ void removeFromParent() override;
+ void removeAllChildren() override;
+ void setBounds(const blink::WebSize& bounds) override;
+ blink::WebSize bounds() const override;
+ void setMasksToBounds(bool masks_to_bounds) override;
+ bool masksToBounds() const override;
+ void setMaskLayer(blink::WebLayer* mask) override;
+ void setReplicaLayer(blink::WebLayer* replica) override;
+ void setOpacity(float opacity) override;
+ float opacity() const override;
+ void setBlendMode(blink::WebBlendMode blend_mode) override;
+ blink::WebBlendMode blendMode() const override;
+ void setIsRootForIsolatedGroup(bool root) override;
+ bool isRootForIsolatedGroup() override;
+ void setOpaque(bool opaque) override;
+ bool opaque() const override;
+ void setPosition(const blink::WebFloatPoint& position) override;
+ blink::WebFloatPoint position() const override;
+ void setTransform(const SkMatrix44& transform) override;
+ void setTransformOrigin(const blink::WebFloatPoint3D& point) override;
+ blink::WebFloatPoint3D transformOrigin() const override;
+ SkMatrix44 transform() const override;
+ void setDrawsContent(bool draws_content) override;
+ bool drawsContent() const override;
+ void setShouldFlattenTransform(bool flatten) override;
+ void setRenderingContext(int context) override;
+ void setUseParentBackfaceVisibility(bool visible) override;
+ void setBackgroundColor(blink::WebColor color) override;
+ blink::WebColor backgroundColor() const override;
+ void setFilters(const blink::WebFilterOperations& filters) override;
+ void setBackgroundFilters(const blink::WebFilterOperations& filters) override;
+ void setAnimationDelegate(
+ blink::WebCompositorAnimationDelegate* delegate) override;
+ bool addAnimation(blink::WebCompositorAnimation* animation) override;
+ void removeAnimation(int animation_id) override;
+ void removeAnimation(int animation_id,
+ blink::WebCompositorAnimation::TargetProperty) override;
+ void pauseAnimation(int animation_id, double time_offset) override;
+ bool hasActiveAnimation() override;
+ void setForceRenderSurface(bool force) override;
+ void setScrollPositionDouble(blink::WebDoublePoint position) override;
+ blink::WebDoublePoint scrollPositionDouble() const override;
+ void setScrollCompensationAdjustment(blink::WebDoublePoint position) override;
+ void setScrollClipLayer(blink::WebLayer* clip_layer) override;
+ bool scrollable() const override;
+ void setUserScrollable(bool horizontal, bool vertical) override;
+ bool userScrollableHorizontal() const override;
+ bool userScrollableVertical() const override;
+ void setHaveWheelEventHandlers(bool have_wheel_event_handlers) override;
+ bool haveWheelEventHandlers() const override;
+ void setHaveScrollEventHandlers(bool have_scroll_event_handlers) override;
+ bool haveScrollEventHandlers() const override;
+ void setShouldScrollOnMainThread(bool scroll_on_main) override;
+ bool shouldScrollOnMainThread() const override;
+ void setNonFastScrollableRegion(
+ const blink::WebVector<blink::WebRect>& region) override;
+ blink::WebVector<blink::WebRect> nonFastScrollableRegion() const override;
+ void setTouchEventHandlerRegion(
+ const blink::WebVector<blink::WebRect>& region) override;
+ blink::WebVector<blink::WebRect> touchEventHandlerRegion() const override;
+ void setScrollBlocksOn(blink::WebScrollBlocksOn) override;
+ blink::WebScrollBlocksOn scrollBlocksOn() const override;
+ void setFrameTimingRequests(
+ const blink::WebVector<std::pair<int64_t, blink::WebRect>>& requests)
+ override;
+ blink::WebVector<std::pair<int64_t, blink::WebRect>> frameTimingRequests()
+ const override;
+ void setIsContainerForFixedPositionLayers(bool is_container) override;
+ bool isContainerForFixedPositionLayers() const override;
+ void setPositionConstraint(
+ const blink::WebLayerPositionConstraint& constraint) override;
+ blink::WebLayerPositionConstraint positionConstraint() const override;
+ void setScrollClient(blink::WebLayerScrollClient* client) override;
+ bool isOrphan() const override;
+ void setWebLayerClient(blink::WebLayerClient* client) override;
// LayerClient implementation.
scoped_refptr<base::trace_event::ConvertableToTraceFormat> TakeDebugInfo()
override;
- virtual void setScrollParent(blink::WebLayer* parent);
- virtual void setClipParent(blink::WebLayer* parent);
+ void setScrollParent(blink::WebLayer* parent) override;
+ void setClipParent(blink::WebLayer* parent) override;
protected:
scoped_refptr<cc::Layer> layer_;
blink::WebLayerClient* web_layer_client_;
+ bool contents_opaque_is_fixed_;
+
private:
scoped_ptr<WebToCCAnimationDelegateAdapter> animation_delegate_adapter_;
diff --git a/chromium/cc/blink/web_layer_impl_fixed_bounds.h b/chromium/cc/blink/web_layer_impl_fixed_bounds.h
index edfd4bbb558..328924542bb 100644
--- a/chromium/cc/blink/web_layer_impl_fixed_bounds.h
+++ b/chromium/cc/blink/web_layer_impl_fixed_bounds.h
@@ -21,7 +21,7 @@ class WebLayerImplFixedBounds : public WebLayerImpl {
CC_BLINK_EXPORT WebLayerImplFixedBounds();
CC_BLINK_EXPORT explicit WebLayerImplFixedBounds(
scoped_refptr<cc::Layer> layer);
- virtual ~WebLayerImplFixedBounds();
+ ~WebLayerImplFixedBounds() override;
// WebLayerImpl overrides.
void invalidateRect(const blink::WebRect& rect) override;
diff --git a/chromium/cc/blink/web_layer_impl_fixed_bounds_unittest.cc b/chromium/cc/blink/web_layer_impl_fixed_bounds_unittest.cc
index 26f445ae072..65433feb445 100644
--- a/chromium/cc/blink/web_layer_impl_fixed_bounds_unittest.cc
+++ b/chromium/cc/blink/web_layer_impl_fixed_bounds_unittest.cc
@@ -68,10 +68,10 @@ TEST(WebLayerImplFixedBoundsTest, BoundsScaleSimple) {
}
void ExpectEqualLayerRectsInTarget(cc::Layer* layer1, cc::Layer* layer2) {
- gfx::RectF layer1_rect_in_target(layer1->bounds());
+ gfx::RectF layer1_rect_in_target(gfx::SizeF(layer1->bounds()));
layer1->draw_transform().TransformRect(&layer1_rect_in_target);
- gfx::RectF layer2_rect_in_target(layer2->bounds());
+ gfx::RectF layer2_rect_in_target(gfx::SizeF(layer2->bounds()));
layer2->draw_transform().TransformRect(&layer2_rect_in_target);
EXPECT_FLOAT_RECT_EQ(layer1_rect_in_target, layer2_rect_in_target);
@@ -112,9 +112,8 @@ void CompareFixedBoundsLayerAndNormalLayer(const WebFloatPoint& anchor_point,
host->SetRootLayer(root_layer->layer());
{
- cc::RenderSurfaceLayerList render_surface_layer_list;
- cc::LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
- root_layer->layer(), kDeviceViewportSize, &render_surface_layer_list);
+ cc::LayerTreeHostCommon::CalcDrawPropsMainInputs inputs(
+ root_layer->layer(), kDeviceViewportSize);
inputs.device_scale_factor = kDeviceScaleFactor;
inputs.page_scale_factor = kPageScaleFactor;
inputs.page_scale_layer = root_layer->layer(),
@@ -129,9 +128,8 @@ void CompareFixedBoundsLayerAndNormalLayer(const WebFloatPoint& anchor_point,
gfx::Size(fixed_bounds.width() / 2, fixed_bounds.height() * 2));
{
- cc::RenderSurfaceLayerList render_surface_layer_list;
- cc::LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
- root_layer->layer(), kDeviceViewportSize, &render_surface_layer_list);
+ cc::LayerTreeHostCommon::CalcDrawPropsMainInputs inputs(
+ root_layer->layer(), kDeviceViewportSize);
inputs.device_scale_factor = kDeviceScaleFactor;
inputs.page_scale_factor = kPageScaleFactor;
inputs.page_scale_layer = root_layer->layer(),
diff --git a/chromium/cc/blink/web_nine_patch_layer_impl.cc b/chromium/cc/blink/web_nine_patch_layer_impl.cc
deleted file mode 100644
index 8dd9980f331..00000000000
--- a/chromium/cc/blink/web_nine_patch_layer_impl.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cc/blink/web_nine_patch_layer_impl.h"
-
-#include "base/command_line.h"
-#include "cc/base/switches.h"
-#include "cc/blink/web_layer_impl.h"
-#include "cc/blink/web_layer_impl_fixed_bounds.h"
-#include "cc/layers/nine_patch_layer.h"
-#include "cc/layers/picture_image_layer.h"
-
-namespace cc_blink {
-
-WebNinePatchLayerImpl::WebNinePatchLayerImpl() {
- layer_.reset(new WebLayerImpl(
- cc::NinePatchLayer::Create(WebLayerImpl::LayerSettings())));
-}
-
-WebNinePatchLayerImpl::~WebNinePatchLayerImpl() {
-}
-
-blink::WebLayer* WebNinePatchLayerImpl::layer() {
- return layer_.get();
-}
-
-void WebNinePatchLayerImpl::setBitmap(const SkBitmap& bitmap) {
- cc::NinePatchLayer* nine_patch =
- static_cast<cc::NinePatchLayer*>(layer_->layer());
- nine_patch->SetBitmap(bitmap);
-}
-
-void WebNinePatchLayerImpl::setAperture(const blink::WebRect& aperture) {
- cc::NinePatchLayer* nine_patch =
- static_cast<cc::NinePatchLayer*>(layer_->layer());
- nine_patch->SetAperture(gfx::Rect(aperture));
-}
-
-void WebNinePatchLayerImpl::setBorder(const blink::WebRect& border) {
- cc::NinePatchLayer* nine_patch =
- static_cast<cc::NinePatchLayer*>(layer_->layer());
- nine_patch->SetBorder(gfx::Rect(border));
-}
-
-} // namespace cc_blink
diff --git a/chromium/cc/blink/web_nine_patch_layer_impl.h b/chromium/cc/blink/web_nine_patch_layer_impl.h
deleted file mode 100644
index cbb39660cd5..00000000000
--- a/chromium/cc/blink/web_nine_patch_layer_impl.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CC_BLINK_WEB_NINE_PATCH_LAYER_IMPL_H_
-#define CC_BLINK_WEB_NINE_PATCH_LAYER_IMPL_H_
-
-#include "base/memory/scoped_ptr.h"
-#include "cc/blink/cc_blink_export.h"
-#include "third_party/WebKit/public/platform/WebNinePatchLayer.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-
-namespace cc_blink {
-
-class WebLayerImpl;
-
-class WebNinePatchLayerImpl : public blink::WebNinePatchLayer {
- public:
- CC_BLINK_EXPORT WebNinePatchLayerImpl();
- virtual ~WebNinePatchLayerImpl();
-
- // blink::WebNinePatchLayer implementation.
- virtual blink::WebLayer* layer();
-
- virtual void setBitmap(const SkBitmap& bitmap);
- virtual void setAperture(const blink::WebRect& aperture);
- virtual void setBorder(const blink::WebRect& border);
-
- private:
- scoped_ptr<WebLayerImpl> layer_;
-
- DISALLOW_COPY_AND_ASSIGN(WebNinePatchLayerImpl);
-};
-
-} // namespace cc_blink
-
-#endif // CC_BLINK_WEB_NINE_PATCH_LAYER_IMPL_H_
diff --git a/chromium/cc/blink/web_scroll_offset_animation_curve_impl.h b/chromium/cc/blink/web_scroll_offset_animation_curve_impl.h
index 5f914b9ca54..11a1635b2d2 100644
--- a/chromium/cc/blink/web_scroll_offset_animation_curve_impl.h
+++ b/chromium/cc/blink/web_scroll_offset_animation_curve_impl.h
@@ -22,15 +22,16 @@ class WebScrollOffsetAnimationCurveImpl
CC_BLINK_EXPORT WebScrollOffsetAnimationCurveImpl(
blink::WebFloatPoint target_value,
TimingFunctionType timing_function);
- virtual ~WebScrollOffsetAnimationCurveImpl();
+ ~WebScrollOffsetAnimationCurveImpl() override;
// blink::WebCompositorAnimationCurve implementation.
- virtual AnimationCurveType type() const;
+ AnimationCurveType type() const override;
// blink::WebScrollOffsetAnimationCurve implementation.
- virtual void setInitialValue(blink::WebFloatPoint initial_value);
- virtual blink::WebFloatPoint getValue(double time) const;
- virtual double duration() const;
+ void setInitialValue(blink::WebFloatPoint initial_value) override;
+ blink::WebFloatPoint getValue(double time) const override;
+ double duration() const override;
+
virtual blink::WebFloatPoint targetValue() const;
virtual void updateTarget(double time, blink::WebFloatPoint new_target);
diff --git a/chromium/cc/blink/web_scrollbar_layer_impl.h b/chromium/cc/blink/web_scrollbar_layer_impl.h
index 14ed66ebb96..d4963d99db3 100644
--- a/chromium/cc/blink/web_scrollbar_layer_impl.h
+++ b/chromium/cc/blink/web_scrollbar_layer_impl.h
@@ -30,12 +30,12 @@ class WebScrollbarLayerImpl : public blink::WebScrollbarLayer {
int thumb_thickness,
int track_start,
bool is_left_side_vertical_scrollbar);
- virtual ~WebScrollbarLayerImpl();
+ ~WebScrollbarLayerImpl() override;
// blink::WebScrollbarLayer implementation.
- virtual blink::WebLayer* layer();
- virtual void setScrollLayer(blink::WebLayer* layer);
- virtual void setClipLayer(blink::WebLayer* layer);
+ blink::WebLayer* layer() override;
+ void setScrollLayer(blink::WebLayer* layer) override;
+ void setClipLayer(blink::WebLayer* layer) override;
private:
scoped_ptr<WebLayerImpl> layer_;
diff --git a/chromium/cc/blink/web_transform_animation_curve_impl.h b/chromium/cc/blink/web_transform_animation_curve_impl.h
index 81ed6073fa7..9143d3cc019 100644
--- a/chromium/cc/blink/web_transform_animation_curve_impl.h
+++ b/chromium/cc/blink/web_transform_animation_curve_impl.h
@@ -24,31 +24,31 @@ class WebTransformAnimationCurveImpl
: public blink::WebTransformAnimationCurve {
public:
CC_BLINK_EXPORT WebTransformAnimationCurveImpl();
- virtual ~WebTransformAnimationCurveImpl();
+ ~WebTransformAnimationCurveImpl() override;
// blink::WebCompositorAnimationCurve implementation.
- virtual AnimationCurveType type() const;
+ AnimationCurveType type() const override;
// blink::WebTransformAnimationCurve implementation.
- virtual void add(const blink::WebTransformKeyframe& keyframe);
- virtual void add(const blink::WebTransformKeyframe& keyframe,
- TimingFunctionType type);
- virtual void add(const blink::WebTransformKeyframe& keyframe,
- double x1,
- double y1,
- double x2,
- double y2);
- virtual void add(const blink::WebTransformKeyframe& keyframe,
- int steps,
- float stepsStartOffset);
- virtual void setLinearTimingFunction();
- virtual void setCubicBezierTimingFunction(TimingFunctionType);
- virtual void setCubicBezierTimingFunction(double x1,
- double y1,
- double x2,
- double y2);
- virtual void setStepsTimingFunction(int number_of_steps,
- float steps_start_offset);
+ void add(const blink::WebTransformKeyframe& keyframe) override;
+ void add(const blink::WebTransformKeyframe& keyframe,
+ TimingFunctionType type) override;
+ void add(const blink::WebTransformKeyframe& keyframe,
+ double x1,
+ double y1,
+ double x2,
+ double y2) override;
+ void add(const blink::WebTransformKeyframe& keyframe,
+ int steps,
+ float stepsStartOffset) override;
+ void setLinearTimingFunction() override;
+ void setCubicBezierTimingFunction(TimingFunctionType) override;
+ void setCubicBezierTimingFunction(double x1,
+ double y1,
+ double x2,
+ double y2) override;
+ void setStepsTimingFunction(int number_of_steps,
+ float steps_start_offset) override;
scoped_ptr<cc::AnimationCurve> CloneToAnimationCurve() const;
diff --git a/chromium/cc/blink/web_transform_operations_impl.h b/chromium/cc/blink/web_transform_operations_impl.h
index 0c91e06289a..f8fe22b6d88 100644
--- a/chromium/cc/blink/web_transform_operations_impl.h
+++ b/chromium/cc/blink/web_transform_operations_impl.h
@@ -15,20 +15,20 @@ namespace cc_blink {
class WebTransformOperationsImpl : public blink::WebTransformOperations {
public:
CC_BLINK_EXPORT WebTransformOperationsImpl();
- virtual ~WebTransformOperationsImpl();
+ ~WebTransformOperationsImpl() override;
const cc::TransformOperations& AsTransformOperations() const;
// Implementation of blink::WebTransformOperations methods
- virtual bool canBlendWith(const blink::WebTransformOperations& other) const;
- virtual void appendTranslate(double x, double y, double z);
- virtual void appendRotate(double x, double y, double z, double degrees);
- virtual void appendScale(double x, double y, double z);
- virtual void appendSkew(double x, double y);
- virtual void appendPerspective(double depth);
- virtual void appendMatrix(const SkMatrix44&);
- virtual void appendIdentity();
- virtual bool isIdentity() const;
+ bool canBlendWith(const blink::WebTransformOperations& other) const override;
+ void appendTranslate(double x, double y, double z) override;
+ void appendRotate(double x, double y, double z, double degrees) override;
+ void appendScale(double x, double y, double z) override;
+ void appendSkew(double x, double y) override;
+ void appendPerspective(double depth) override;
+ void appendMatrix(const SkMatrix44&) override;
+ void appendIdentity() override;
+ bool isIdentity() const override;
private:
cc::TransformOperations transform_operations_;
diff --git a/chromium/cc/cc.gyp b/chromium/cc/cc.gyp
index d4a2ea02fe7..642ec7559e3 100644
--- a/chromium/cc/cc.gyp
+++ b/chromium/cc/cc.gyp
@@ -20,6 +20,7 @@
'<(DEPTH)/ui/events/events.gyp:events_base',
'<(DEPTH)/ui/gfx/gfx.gyp:gfx',
'<(DEPTH)/ui/gfx/gfx.gyp:gfx_geometry',
+ '<(DEPTH)/ui/gl/gl.gyp:gl',
],
'variables': {
'optimize': 'max',
@@ -79,19 +80,22 @@
'base/histograms.h',
'base/invalidation_region.cc',
'base/invalidation_region.h',
- 'base/list_container.cc',
'base/list_container.h',
+ 'base/list_container_helper.cc',
+ 'base/list_container_helper.h',
'base/math_util.cc',
'base/math_util.h',
+ 'base/random_access_list_container.h',
'base/region.cc',
'base/region.h',
'base/resource_id.h',
'base/rolling_time_delta_history.cc',
'base/rolling_time_delta_history.h',
+ 'base/rtree.cc',
+ 'base/rtree.h',
'base/scoped_ptr_algorithm.h',
'base/scoped_ptr_deque.h',
'base/scoped_ptr_vector.h',
- 'base/sidecar_list_container.h',
'base/simple_enclosed_region.cc',
'base/simple_enclosed_region.h',
'base/switches.cc',
@@ -131,12 +135,8 @@
'debug/micro_benchmark_controller_impl.h',
'debug/micro_benchmark_impl.cc',
'debug/micro_benchmark_impl.h',
- 'debug/paint_time_counter.cc',
- 'debug/paint_time_counter.h',
'debug/picture_debug_util.cc',
'debug/picture_debug_util.h',
- 'debug/picture_record_benchmark.cc',
- 'debug/picture_record_benchmark.h',
'debug/rasterize_and_record_benchmark.cc',
'debug/rasterize_and_record_benchmark.h',
'debug/rasterize_and_record_benchmark_impl.cc',
@@ -148,8 +148,6 @@
'debug/ring_buffer.h',
'debug/traced_display_item_list.cc',
'debug/traced_display_item_list.h',
- 'debug/traced_picture.cc',
- 'debug/traced_picture.h',
'debug/traced_value.cc',
'debug/traced_value.h',
'debug/unittest_only_benchmark.cc',
@@ -164,6 +162,8 @@
'input/page_scale_animation.h',
'input/scroll_elasticity_helper.cc',
'input/scroll_elasticity_helper.h',
+ 'input/scroll_state.cc',
+ 'input/scroll_state.h',
'input/selection_bound_type.h',
'input/selection.h',
'input/top_controls_manager.cc',
@@ -179,6 +179,7 @@
'layers/delegated_renderer_layer.h',
'layers/delegated_renderer_layer_impl.cc',
'layers/delegated_renderer_layer_impl.h',
+ 'layers/draw_properties.cc',
'layers/draw_properties.h',
'layers/heads_up_display_layer.cc',
'layers/heads_up_display_layer.h',
@@ -194,7 +195,6 @@
'layers/layer_impl.cc',
'layers/layer_impl.h',
'layers/layer_iterator.h',
- 'layers/layer_lists.cc',
'layers/layer_lists.h',
'layers/layer_position_constraint.cc',
'layers/layer_position_constraint.h',
@@ -218,8 +218,8 @@
'layers/picture_layer_impl.cc',
'layers/picture_layer_impl.h',
'layers/render_pass_sink.h',
- 'layers/render_surface.cc',
- 'layers/render_surface.h',
+ 'layers/render_surface_draw_properties.cc',
+ 'layers/render_surface_draw_properties.h',
'layers/render_surface_impl.cc',
'layers/render_surface_impl.h',
'layers/scrollbar_layer_impl_base.cc',
@@ -307,8 +307,12 @@
'output/overlay_candidate_validator.h',
'output/overlay_processor.cc',
'output/overlay_processor.h',
+ 'output/overlay_strategy_all_or_nothing.cc',
+ 'output/overlay_strategy_all_or_nothing.h',
'output/overlay_strategy_common.cc',
'output/overlay_strategy_common.h',
+ 'output/overlay_strategy_sandwich.cc',
+ 'output/overlay_strategy_sandwich.h',
'output/overlay_strategy_single_on_top.cc',
'output/overlay_strategy_single_on_top.h',
'output/overlay_strategy_underlay.cc',
@@ -325,8 +329,6 @@
'output/renderer_settings.h',
'output/shader.cc',
'output/shader.h',
- 'output/software_frame_data.cc',
- 'output/software_frame_data.h',
'output/software_output_device.cc',
'output/software_output_device.h',
'output/software_renderer.cc',
@@ -344,10 +346,14 @@
'playback/clip_path_display_item.h',
'playback/compositing_display_item.cc',
'playback/compositing_display_item.h',
+ 'playback/discardable_image_map.cc',
+ 'playback/discardable_image_map.h',
'playback/display_item.cc',
'playback/display_item.h',
'playback/display_item_list.cc',
'playback/display_item_list.h',
+ 'playback/display_item_list_bounds_calculator.cc',
+ 'playback/display_item_list_bounds_calculator.h',
'playback/display_item_list_settings.cc',
'playback/display_item_list_settings.h',
'playback/display_list_raster_source.cc',
@@ -362,22 +368,13 @@
'playback/float_clip_display_item.h',
'playback/largest_display_item.cc',
'playback/largest_display_item.h',
- 'playback/picture.cc',
- 'playback/picture.h',
- 'playback/picture_pile.cc',
- 'playback/picture_pile.h',
- 'playback/picture_pile_impl.cc',
- 'playback/picture_pile_impl.h',
- 'playback/pixel_ref_map.cc',
- 'playback/pixel_ref_map.h',
+ 'playback/position_image.h',
'playback/raster_source.h',
'playback/raster_source_helper.cc',
'playback/raster_source_helper.h',
'playback/recording_source.h',
'playback/transform_display_item.cc',
'playback/transform_display_item.h',
- 'quads/checkerboard_draw_quad.cc',
- 'quads/checkerboard_draw_quad.h',
'quads/content_draw_quad_base.cc',
'quads/content_draw_quad_base.h',
'quads/debug_border_draw_quad.cc',
@@ -420,8 +417,6 @@
'raster/gpu_tile_task_worker_pool.h',
'raster/one_copy_tile_task_worker_pool.cc',
'raster/one_copy_tile_task_worker_pool.h',
- 'raster/pixel_buffer_tile_task_worker_pool.cc',
- 'raster/pixel_buffer_tile_task_worker_pool.h',
'raster/raster_buffer.cc',
'raster/raster_buffer.h',
'raster/scoped_gpu_raster.cc',
@@ -449,6 +444,7 @@
'resources/resource_pool.h',
'resources/resource_provider.cc',
'resources/resource_provider.h',
+ 'resources/resource_util.h',
'resources/returned_resource.h',
'resources/scoped_resource.cc',
'resources/scoped_resource.h',
@@ -491,6 +487,8 @@
'scheduler/video_frame_controller.h',
'tiles/eviction_tile_priority_queue.cc',
'tiles/eviction_tile_priority_queue.h',
+ 'tiles/image_decode_controller.cc',
+ 'tiles/image_decode_controller.h',
'tiles/picture_layer_tiling.cc',
'tiles/picture_layer_tiling.h',
'tiles/picture_layer_tiling_set.cc',
@@ -519,6 +517,8 @@
'tiles/tiling_set_raster_queue_required.h',
'trees/blocking_task_runner.cc',
'trees/blocking_task_runner.h',
+ 'trees/channel_impl.h',
+ 'trees/channel_main.h',
'trees/damage_tracker.cc',
'trees/damage_tracker.h',
'trees/draw_property_utils.cc',
@@ -548,11 +548,15 @@
'trees/property_tree_builder.h',
'trees/proxy.cc',
'trees/proxy.h',
+ 'trees/proxy_impl.h',
+ 'trees/proxy_main.h',
'trees/scoped_abort_remaining_swap_promises.h',
'trees/single_thread_proxy.cc',
'trees/single_thread_proxy.h',
'trees/swap_promise_monitor.cc',
'trees/swap_promise_monitor.h',
+ 'trees/threaded_channel.cc',
+ 'trees/threaded_channel.h',
'trees/thread_proxy.cc',
'trees/thread_proxy.h',
'trees/tree_synchronizer.cc',
@@ -605,6 +609,8 @@
'surfaces/surface_factory.cc',
'surfaces/surface_factory.h',
'surfaces/surface_factory_client.h',
+ 'surfaces/surface_hittest.cc',
+ 'surfaces/surface_hittest.h',
'surfaces/surface_id.h',
'surfaces/surface_id_allocator.cc',
'surfaces/surface_id_allocator.h',
diff --git a/chromium/cc/cc_tests.gyp b/chromium/cc/cc_tests.gyp
index 5f5f4e418aa..419f68cd7ad 100644
--- a/chromium/cc/cc_tests.gyp
+++ b/chromium/cc/cc_tests.gyp
@@ -22,16 +22,18 @@
'base/histograms_unittest.cc',
'base/list_container_unittest.cc',
'base/math_util_unittest.cc',
+ 'base/random_access_list_container_unittest.cc',
'base/region_unittest.cc',
'base/rolling_time_delta_history_unittest.cc',
+ 'base/rtree_unittest.cc',
'base/scoped_ptr_vector_unittest.cc',
- 'base/sidecar_list_container_unittest.cc',
'base/simple_enclosed_region_unittest.cc',
'base/tiling_data_unittest.cc',
'base/unique_notifier_unittest.cc',
'debug/frame_timing_tracker_unittest.cc',
'debug/micro_benchmark_controller_unittest.cc',
'debug/rendering_stats_unittest.cc',
+ 'input/scroll_state_unittest.cc',
'input/top_controls_manager_unittest.cc',
'layers/delegated_frame_provider_unittest.cc',
'layers/delegated_frame_resource_collection_unittest.cc',
@@ -78,14 +80,10 @@
'output/shader_unittest.cc',
'output/software_renderer_unittest.cc',
'output/texture_mailbox_deleter_unittest.cc',
+ 'playback/discardable_image_map_unittest.cc',
'playback/display_item_list_unittest.cc',
'playback/display_list_raster_source_unittest.cc',
'playback/display_list_recording_source_unittest.cc',
- 'playback/picture_pile_impl_unittest.cc',
- 'playback/picture_pile_unittest.cc',
- 'playback/picture_unittest.cc',
- 'playback/pixel_ref_map_unittest.cc',
- 'playback/recording_source_unittest.cc',
'quads/draw_polygon_unittest.cc',
'quads/draw_quad_unittest.cc',
'quads/render_pass_unittest.cc',
@@ -96,6 +94,7 @@
'resources/platform_color_unittest.cc',
'resources/resource_pool_unittest.cc',
'resources/resource_provider_unittest.cc',
+ 'resources/resource_util_unittest.cc',
'resources/scoped_resource_unittest.cc',
'resources/video_resource_updater_unittest.cc',
'scheduler/begin_frame_source_unittest.cc',
@@ -146,6 +145,7 @@
'surfaces/surface_aggregator_unittest.cc',
'surfaces/surface_display_output_surface_unittest.cc',
'surfaces/surface_factory_unittest.cc',
+ 'surfaces/surface_hittest_unittest.cc',
'surfaces/surface_unittest.cc',
'surfaces/surfaces_pixeltest.cc',
],
@@ -164,6 +164,9 @@
'test/fake_delegated_renderer_layer.h',
'test/fake_delegated_renderer_layer_impl.cc',
'test/fake_delegated_renderer_layer_impl.h',
+ 'test/fake_display_list_raster_source.cc',
+ 'test/fake_display_list_raster_source.h',
+ 'test/fake_display_list_recording_source.cc',
'test/fake_display_list_recording_source.h',
'test/fake_external_begin_frame_source.cc',
'test/fake_external_begin_frame_source.h',
@@ -188,10 +191,6 @@
'test/fake_picture_layer_impl.h',
'test/fake_picture_layer_tiling_client.cc',
'test/fake_picture_layer_tiling_client.h',
- 'test/fake_picture_pile.cc',
- 'test/fake_picture_pile.h',
- 'test/fake_picture_pile_impl.cc',
- 'test/fake_picture_pile_impl.h',
'test/fake_proxy.cc',
'test/fake_proxy.h',
'test/fake_renderer_client.cc',
@@ -241,8 +240,6 @@
'test/pixel_test_software_output_device.h',
'test/pixel_test_utils.cc',
'test/pixel_test_utils.h',
- 'test/render_pass_test_common.cc',
- 'test/render_pass_test_common.h',
'test/render_pass_test_utils.cc',
'test/render_pass_test_utils.h',
'test/scheduler_test_common.cc',
@@ -353,7 +350,6 @@
# Note: sources list duplicated in GN build.
'layers/layer_perftest.cc',
'layers/picture_layer_impl_perftest.cc',
- 'playback/picture_pile_impl_perftest.cc',
'quads/draw_quad_perftest.cc',
'raster/task_graph_runner_perftest.cc',
'raster/texture_compressor_perftest.cc',
@@ -415,6 +411,7 @@
'../ui/gfx/gfx.gyp:gfx_geometry',
'../ui/gfx/gfx.gyp:gfx_test_support',
'../ui/gl/gl.gyp:gl',
+ '../ui/gl/gl.gyp:gl_test_support',
],
'sources': [
'<@(cc_tests_support_files)',
@@ -467,7 +464,7 @@
'conditions': [
# crbug.com/464062 xdisplaycheck is used to run cc_unittests_run on
# the linux try bots when using X11.
- ['OS=="linux" and use_ozone==0',
+ ['use_x11==1',
{
'dependencies': [
'../tools/xdisplaycheck/xdisplaycheck.gyp:xdisplaycheck',
diff --git a/chromium/cc/cc_unittests.isolate b/chromium/cc/cc_unittests.isolate
index 6a16fcd5e9c..09bfcf9e34a 100644
--- a/chromium/cc/cc_unittests.isolate
+++ b/chromium/cc/cc_unittests.isolate
@@ -39,7 +39,6 @@
'files': [
'test/data/',
'../testing/test_env.py',
- '<(PRODUCT_DIR)/cc_unittests<(EXECUTABLE_SUFFIX)',
],
},
}],
@@ -81,6 +80,6 @@
],
'includes': [
'../base/base.isolate',
- '../third_party/angle/angle.isolate',
+ '../ui/gl/gl.isolate',
],
}
diff --git a/chromium/cc/debug/devtools_instrumentation.h b/chromium/cc/debug/devtools_instrumentation.h
index 8f03f8c76fc..3a285799840 100644
--- a/chromium/cc/debug/devtools_instrumentation.h
+++ b/chromium/cc/debug/devtools_instrumentation.h
@@ -52,9 +52,10 @@ class ScopedLayerTask {
class ScopedImageDecodeTask {
public:
- explicit ScopedImageDecodeTask(void* pixelRef) {
+ explicit ScopedImageDecodeTask(const void* imagePtr) {
TRACE_EVENT_BEGIN1(internal::kCategory, internal::kImageDecodeTask,
- internal::kPixelRefId, reinterpret_cast<uint64>(pixelRef));
+ internal::kPixelRefId,
+ reinterpret_cast<uint64>(imagePtr));
}
~ScopedImageDecodeTask() {
TRACE_EVENT_END0(internal::kCategory, internal::kImageDecodeTask);
diff --git a/chromium/cc/debug/layer_tree_debug_state.cc b/chromium/cc/debug/layer_tree_debug_state.cc
index e840220ca6f..a084bf38d20 100644
--- a/chromium/cc/debug/layer_tree_debug_state.cc
+++ b/chromium/cc/debug/layer_tree_debug_state.cc
@@ -12,7 +12,6 @@ namespace cc {
LayerTreeDebugState::LayerTreeDebugState()
: show_fps_counter(false),
show_debug_borders(false),
- continuous_painting(false),
show_paint_rects(false),
show_property_changed_rects(false),
show_surface_damage_rects(false),
@@ -35,12 +34,11 @@ void LayerTreeDebugState::SetRecordRenderingStats(bool enabled) {
}
bool LayerTreeDebugState::RecordRenderingStats() const {
- return record_rendering_stats_ || continuous_painting;
+ return record_rendering_stats_;
}
bool LayerTreeDebugState::ShowHudInfo() const {
- return show_fps_counter || continuous_painting ||
- ShowHudRects();
+ return show_fps_counter || ShowHudRects();
}
bool LayerTreeDebugState::ShowHudRects() const {
@@ -52,7 +50,7 @@ bool LayerTreeDebugState::ShowHudRects() const {
}
bool LayerTreeDebugState::ShowMemoryStats() const {
- return show_fps_counter || continuous_painting;
+ return show_fps_counter;
}
bool LayerTreeDebugState::Equal(const LayerTreeDebugState& a,
@@ -60,7 +58,6 @@ bool LayerTreeDebugState::Equal(const LayerTreeDebugState& a,
return (
a.show_fps_counter == b.show_fps_counter &&
a.show_debug_borders == b.show_debug_borders &&
- a.continuous_painting == b.continuous_painting &&
a.show_paint_rects == b.show_paint_rects &&
a.show_property_changed_rects == b.show_property_changed_rects &&
a.show_surface_damage_rects == b.show_surface_damage_rects &&
@@ -84,7 +81,6 @@ LayerTreeDebugState LayerTreeDebugState::Unite(const LayerTreeDebugState& a,
r.show_fps_counter |= b.show_fps_counter;
r.show_debug_borders |= b.show_debug_borders;
- r.continuous_painting |= b.continuous_painting;
r.show_paint_rects |= b.show_paint_rects;
r.show_property_changed_rects |= b.show_property_changed_rects;
diff --git a/chromium/cc/debug/layer_tree_debug_state.h b/chromium/cc/debug/layer_tree_debug_state.h
index 4b71cd9bbbe..13db0ce4be9 100644
--- a/chromium/cc/debug/layer_tree_debug_state.h
+++ b/chromium/cc/debug/layer_tree_debug_state.h
@@ -17,7 +17,6 @@ class CC_EXPORT LayerTreeDebugState {
bool show_fps_counter;
bool show_debug_borders;
- bool continuous_painting;
bool show_paint_rects;
bool show_property_changed_rects;
diff --git a/chromium/cc/debug/micro_benchmark_controller.cc b/chromium/cc/debug/micro_benchmark_controller.cc
index a38e5ad01a3..a0dc306612f 100644
--- a/chromium/cc/debug/micro_benchmark_controller.cc
+++ b/chromium/cc/debug/micro_benchmark_controller.cc
@@ -11,7 +11,6 @@
#include "base/thread_task_runner_handle.h"
#include "base/values.h"
#include "cc/debug/invalidation_benchmark.h"
-#include "cc/debug/picture_record_benchmark.h"
#include "cc/debug/rasterize_and_record_benchmark.h"
#include "cc/debug/unittest_only_benchmark.h"
#include "cc/trees/layer_tree_host.h"
@@ -29,8 +28,6 @@ scoped_ptr<MicroBenchmark> CreateBenchmark(
const MicroBenchmark::DoneCallback& callback) {
if (name == "invalidation_benchmark") {
return make_scoped_ptr(new InvalidationBenchmark(value.Pass(), callback));
- } else if (name == "picture_record_benchmark") {
- return make_scoped_ptr(new PictureRecordBenchmark(value.Pass(), callback));
} else if (name == "rasterize_and_record_benchmark") {
return make_scoped_ptr(
new RasterizeAndRecordBenchmark(value.Pass(), callback));
diff --git a/chromium/cc/debug/paint_time_counter.cc b/chromium/cc/debug/paint_time_counter.cc
deleted file mode 100644
index 41ef1a334a6..00000000000
--- a/chromium/cc/debug/paint_time_counter.cc
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cc/debug/paint_time_counter.h"
-
-namespace cc {
-
-// static
-scoped_ptr<PaintTimeCounter> PaintTimeCounter::Create() {
- return make_scoped_ptr(new PaintTimeCounter());
-}
-
-PaintTimeCounter::PaintTimeCounter() {
-}
-
-void PaintTimeCounter::SavePaintTime(const base::TimeDelta& paint_time) {
- ring_buffer_.SaveToBuffer(paint_time);
-}
-
-void PaintTimeCounter::GetMinAndMaxPaintTime(base::TimeDelta* min,
- base::TimeDelta* max) const {
- *min = base::TimeDelta::FromDays(1);
- *max = base::TimeDelta();
-
- for (RingBufferType::Iterator it = ring_buffer_.Begin(); it; ++it) {
- const base::TimeDelta paint_time = **it;
-
- if (paint_time < *min)
- *min = paint_time;
- if (paint_time > *max)
- *max = paint_time;
- }
-
- if (*min > *max)
- *min = *max;
-}
-
-void PaintTimeCounter::ClearHistory() {
- ring_buffer_.Clear();
-}
-
-} // namespace cc
diff --git a/chromium/cc/debug/paint_time_counter.h b/chromium/cc/debug/paint_time_counter.h
deleted file mode 100644
index c93980bc836..00000000000
--- a/chromium/cc/debug/paint_time_counter.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CC_DEBUG_PAINT_TIME_COUNTER_H_
-#define CC_DEBUG_PAINT_TIME_COUNTER_H_
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/time/time.h"
-#include "cc/debug/ring_buffer.h"
-
-namespace cc {
-
-// Maintains a history of paint times for each frame
-class PaintTimeCounter {
- public:
- static scoped_ptr<PaintTimeCounter> Create();
-
- size_t HistorySize() const { return ring_buffer_.BufferSize(); }
-
- // n = 0 returns the oldest and
- // n = PaintTimeHistorySize() - 1 the most recent paint time.
- base::TimeDelta GetPaintTimeOfRecentFrame(const size_t& n) const;
-
- void SavePaintTime(const base::TimeDelta& total_paint_time);
- void GetMinAndMaxPaintTime(base::TimeDelta* min, base::TimeDelta* max) const;
-
- void ClearHistory();
-
- typedef RingBuffer<base::TimeDelta, 200> RingBufferType;
- RingBufferType::Iterator Begin() const { return ring_buffer_.Begin(); }
- RingBufferType::Iterator End() const { return ring_buffer_.End(); }
-
- private:
- PaintTimeCounter();
-
- RingBufferType ring_buffer_;
-
- DISALLOW_COPY_AND_ASSIGN(PaintTimeCounter);
-};
-
-} // namespace cc
-
-#endif // CC_DEBUG_PAINT_TIME_COUNTER_H_
diff --git a/chromium/cc/debug/picture_record_benchmark.cc b/chromium/cc/debug/picture_record_benchmark.cc
deleted file mode 100644
index 0f093ce1ecc..00000000000
--- a/chromium/cc/debug/picture_record_benchmark.cc
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cc/debug/picture_record_benchmark.h"
-
-#include <algorithm>
-
-#include "base/basictypes.h"
-#include "base/values.h"
-#include "cc/layers/layer.h"
-#include "cc/layers/picture_layer.h"
-#include "cc/playback/picture.h"
-#include "cc/trees/layer_tree_host.h"
-#include "cc/trees/layer_tree_host_common.h"
-#include "ui/gfx/geometry/rect.h"
-
-namespace cc {
-
-namespace {
-
-const int kPositionIncrement = 100;
-const int kTileGridSize = 512;
-
-} // namespace
-
-PictureRecordBenchmark::PictureRecordBenchmark(
- scoped_ptr<base::Value> value,
- const MicroBenchmark::DoneCallback& callback)
- : MicroBenchmark(callback) {
- if (!value)
- return;
-
- base::ListValue* list = nullptr;
- value->GetAsList(&list);
- if (!list)
- return;
-
- for (base::ListValue::iterator it = list->begin(); it != list->end(); ++it) {
- base::DictionaryValue* dictionary = nullptr;
- (*it)->GetAsDictionary(&dictionary);
- if (!dictionary ||
- !dictionary->HasKey("width") ||
- !dictionary->HasKey("height"))
- continue;
-
- int width, height;
- dictionary->GetInteger("width", &width);
- dictionary->GetInteger("height", &height);
-
- dimensions_.push_back(std::make_pair(width, height));
- }
-}
-
-PictureRecordBenchmark::~PictureRecordBenchmark() {}
-
-void PictureRecordBenchmark::DidUpdateLayers(LayerTreeHost* host) {
- LayerTreeHostCommon::CallFunctionForSubtree(
- host->root_layer(),
- [this](Layer* layer) { layer->RunMicroBenchmark(this); });
-
- scoped_ptr<base::ListValue> results(new base::ListValue());
- for (std::map<std::pair<int, int>, TotalTime>::iterator it = times_.begin();
- it != times_.end();
- ++it) {
- std::pair<int, int> dimensions = it->first;
- base::TimeDelta total_time = it->second.first;
- unsigned total_count = it->second.second;
-
- double average_time = 0.0;
- if (total_count > 0)
- average_time = total_time.InMillisecondsF() / total_count;
-
- scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue());
- result->SetInteger("width", dimensions.first);
- result->SetInteger("height", dimensions.second);
- result->SetInteger("samples_count", total_count);
- result->SetDouble("time_ms", average_time);
-
- results->Append(result.release());
- }
-
- NotifyDone(results.Pass());
-}
-
-void PictureRecordBenchmark::RunOnLayer(PictureLayer* layer) {
- ContentLayerClient* painter = layer->client();
- gfx::Size bounds = layer->bounds();
-
- gfx::Size tile_grid_size(kTileGridSize, kTileGridSize);
-
- for (size_t i = 0; i < dimensions_.size(); ++i) {
- std::pair<int, int> dimensions = dimensions_[i];
- int width = dimensions.first;
- int height = dimensions.second;
-
- int y_limit = std::max(1, bounds.height() - height);
- int x_limit = std::max(1, bounds.width() - width);
- for (int y = 0; y < y_limit; y += kPositionIncrement) {
- for (int x = 0; x < x_limit; x += kPositionIncrement) {
- gfx::Rect rect = gfx::Rect(x, y, width, height);
-
- base::TimeTicks start = base::TimeTicks::Now();
-
- scoped_refptr<Picture> picture =
- Picture::Create(rect, painter, tile_grid_size, false,
- RecordingSource::RECORD_NORMALLY);
-
- base::TimeTicks end = base::TimeTicks::Now();
- base::TimeDelta duration = end - start;
- TotalTime& total_time = times_[dimensions];
- total_time.first += duration;
- total_time.second++;
- }
- }
- }
-}
-
-} // namespace cc
diff --git a/chromium/cc/debug/picture_record_benchmark.h b/chromium/cc/debug/picture_record_benchmark.h
deleted file mode 100644
index 3710d83b21b..00000000000
--- a/chromium/cc/debug/picture_record_benchmark.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CC_DEBUG_PICTURE_RECORD_BENCHMARK_H_
-#define CC_DEBUG_PICTURE_RECORD_BENCHMARK_H_
-
-#include <map>
-#include <utility>
-#include <vector>
-
-#include "base/time/time.h"
-#include "cc/debug/micro_benchmark_controller.h"
-
-namespace cc {
-
-class LayerTreeHost;
-class Layer;
-class CC_EXPORT PictureRecordBenchmark : public MicroBenchmark {
- public:
- explicit PictureRecordBenchmark(scoped_ptr<base::Value> value,
- const MicroBenchmark::DoneCallback& callback);
- ~PictureRecordBenchmark() override;
-
- // Implements MicroBenchmark interface.
- void DidUpdateLayers(LayerTreeHost* host) override;
- void RunOnLayer(PictureLayer* layer) override;
-
- private:
- typedef std::pair<base::TimeDelta, unsigned> TotalTime;
- std::map<std::pair<int, int>, TotalTime> times_;
- std::vector<std::pair<int, int>> dimensions_;
-};
-
-} // namespace cc
-
-#endif // CC_DEBUG_PICTURE_RECORD_BENCHMARK_H_
diff --git a/chromium/cc/debug/rasterize_and_record_benchmark.cc b/chromium/cc/debug/rasterize_and_record_benchmark.cc
index b474e431fd2..9b958d3bd2e 100644
--- a/chromium/cc/debug/rasterize_and_record_benchmark.cc
+++ b/chromium/cc/debug/rasterize_and_record_benchmark.cc
@@ -17,9 +17,9 @@
#include "cc/layers/layer.h"
#include "cc/layers/picture_layer.h"
#include "cc/playback/display_item_list.h"
-#include "cc/playback/picture_pile.h"
#include "cc/trees/layer_tree_host.h"
#include "cc/trees/layer_tree_host_common.h"
+#include "skia/ext/analysis_canvas.h"
#include "third_party/skia/include/utils/SkPictureUtils.h"
#include "ui/gfx/geometry/rect.h"
@@ -113,66 +113,7 @@ void RasterizeAndRecordBenchmark::RunOnLayer(PictureLayer* layer) {
if (visible_layer_rect.IsEmpty())
return;
- if (host_->settings().use_display_lists) {
- RunOnDisplayListLayer(layer, visible_layer_rect);
- } else {
- RunOnPictureLayer(layer, visible_layer_rect);
- }
-}
-
-void RasterizeAndRecordBenchmark::RunOnPictureLayer(
- PictureLayer* layer,
- const gfx::Rect& visible_layer_rect) {
- ContentLayerClient* painter = layer->client();
-
- DCHECK(host_ && !host_->settings().use_display_lists);
-
- gfx::Size tile_grid_size = host_->settings().default_tile_size;
-
- for (int mode_index = 0; mode_index < RecordingSource::RECORDING_MODE_COUNT;
- mode_index++) {
- RecordingSource::RecordingMode mode =
- static_cast<RecordingSource::RecordingMode>(mode_index);
-
- // Not supported for SkPicture recording.
- if (mode == RecordingSource::RECORD_WITH_CONSTRUCTION_DISABLED)
- continue;
-
- base::TimeDelta min_time = base::TimeDelta::Max();
- size_t memory_used = 0;
-
- for (int i = 0; i < record_repeat_count_; ++i) {
- // Run for a minimum amount of time to avoid problems with timer
- // quantization when the layer is very small.
- LapTimer timer(kWarmupRuns,
- base::TimeDelta::FromMilliseconds(kTimeLimitMillis),
- kTimeCheckInterval);
- scoped_refptr<Picture> picture;
- do {
- picture = Picture::Create(visible_layer_rect, painter, tile_grid_size,
- false, mode);
- if (memory_used) {
- // Verify we are recording the same thing each time.
- DCHECK(memory_used == picture->ApproximateMemoryUsage());
- } else {
- memory_used = picture->ApproximateMemoryUsage();
- }
-
- timer.NextLap();
- } while (!timer.HasTimeLimitExpired());
- base::TimeDelta duration =
- base::TimeDelta::FromMillisecondsD(timer.MsPerLap());
- if (duration < min_time)
- min_time = duration;
- }
-
- if (mode == RecordingSource::RECORD_NORMALLY) {
- record_results_.bytes_used += memory_used;
- record_results_.pixels_recorded +=
- visible_layer_rect.width() * visible_layer_rect.height();
- }
- record_results_.total_best_time[mode_index] += min_time;
- }
+ RunOnDisplayListLayer(layer, visible_layer_rect);
}
void RasterizeAndRecordBenchmark::RunOnDisplayListLayer(
@@ -180,8 +121,6 @@ void RasterizeAndRecordBenchmark::RunOnDisplayListLayer(
const gfx::Rect& visible_layer_rect) {
ContentLayerClient* painter = layer->client();
- DCHECK(host_ && host_->settings().use_display_lists);
-
for (int mode_index = 0; mode_index < RecordingSource::RECORDING_MODE_COUNT;
mode_index++) {
ContentLayerClient::PaintingControlSetting painting_control =
@@ -220,6 +159,11 @@ void RasterizeAndRecordBenchmark::RunOnDisplayListLayer(
do {
display_list = painter->PaintContentsToDisplayList(visible_layer_rect,
painting_control);
+ if (display_list->ShouldBeAnalyzedForSolidColor()) {
+ gfx::Size layer_size = layer->paint_properties().bounds;
+ skia::AnalysisCanvas canvas(layer_size.width(), layer_size.height());
+ display_list->Raster(&canvas, nullptr, gfx::Rect(), 1.f);
+ }
if (memory_used) {
// Verify we are recording the same thing each time.
@@ -237,7 +181,8 @@ void RasterizeAndRecordBenchmark::RunOnDisplayListLayer(
}
if (mode_index == RecordingSource::RECORD_NORMALLY) {
- record_results_.bytes_used += memory_used;
+ record_results_.bytes_used +=
+ memory_used + painter->GetApproximateUnsharedMemoryUsage();
record_results_.pixels_recorded +=
visible_layer_rect.width() * visible_layer_rect.height();
}
diff --git a/chromium/cc/debug/rasterize_and_record_benchmark.h b/chromium/cc/debug/rasterize_and_record_benchmark.h
index 207254f24c6..97cecb15a53 100644
--- a/chromium/cc/debug/rasterize_and_record_benchmark.h
+++ b/chromium/cc/debug/rasterize_and_record_benchmark.h
@@ -13,7 +13,8 @@
#include "base/single_thread_task_runner.h"
#include "base/time/time.h"
#include "cc/debug/micro_benchmark_controller.h"
-#include "cc/playback/picture.h"
+#include "cc/playback/recording_source.h"
+#include "ui/gfx/geometry/rect.h"
namespace base {
class DictionaryValue;
@@ -40,8 +41,6 @@ class RasterizeAndRecordBenchmark : public MicroBenchmark {
private:
void RunOnDisplayListLayer(PictureLayer* layer,
const gfx::Rect& visible_layer_rect);
- void RunOnPictureLayer(PictureLayer* layer,
- const gfx::Rect& visible_layer_rect);
void RecordRasterResults(scoped_ptr<base::Value> results);
diff --git a/chromium/cc/debug/rasterize_and_record_benchmark_impl.cc b/chromium/cc/debug/rasterize_and_record_benchmark_impl.cc
index 1dc110b4fac..d798dc6705e 100644
--- a/chromium/cc/debug/rasterize_and_record_benchmark_impl.cc
+++ b/chromium/cc/debug/rasterize_and_record_benchmark_impl.cc
@@ -73,9 +73,8 @@ class FixedInvalidationPictureLayerTilingClient
const Region invalidation)
: base_client_(base_client), invalidation_(invalidation) {}
- ScopedTilePtr CreateTile(float contents_scale,
- const gfx::Rect& content_rect) override {
- return base_client_->CreateTile(contents_scale, content_rect);
+ ScopedTilePtr CreateTile(const Tile::CreateInfo& info) override {
+ return base_client_->CreateTile(info);
}
gfx::Size CalculateTileSize(const gfx::Size& content_bounds) const override {
@@ -171,12 +170,13 @@ void RasterizeAndRecordBenchmarkImpl::RunOnLayer(PictureLayerImpl* layer) {
// really matter.
const LayerTreeSettings& settings = layer->layer_tree_impl()->settings();
scoped_ptr<PictureLayerTilingSet> tiling_set = PictureLayerTilingSet::Create(
- layer->GetTree(), &client, settings.max_tiles_for_interest_area,
+ layer->GetTree(), &client, settings.tiling_interest_area_padding,
settings.skewport_target_time_in_seconds,
settings.skewport_extrapolation_limit_in_content_pixels);
PictureLayerTiling* tiling =
tiling_set->AddTiling(1.f, layer->GetRasterSource());
+ tiling->set_resolution(HIGH_RESOLUTION);
tiling->CreateAllTilesForTesting();
RasterSource* raster_source = tiling->raster_source();
for (PictureLayerTiling::CoverageIterator it(tiling, 1.f,
diff --git a/chromium/cc/debug/traced_picture.cc b/chromium/cc/debug/traced_picture.cc
deleted file mode 100644
index 3241871d8ee..00000000000
--- a/chromium/cc/debug/traced_picture.cc
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cc/debug/traced_picture.h"
-
-#include "base/json/json_writer.h"
-#include "base/strings/stringprintf.h"
-#include "base/values.h"
-
-namespace cc {
-
-TracedPicture::TracedPicture(scoped_refptr<const Picture> picture)
- : picture_(picture), is_alias_(false) {}
-
-TracedPicture::~TracedPicture() {
-}
-
-scoped_refptr<base::trace_event::ConvertableToTraceFormat>
-TracedPicture::AsTraceablePicture(const Picture* picture) {
- return scoped_refptr<base::trace_event::ConvertableToTraceFormat>(
- new TracedPicture(picture));
-}
-
-scoped_refptr<base::trace_event::ConvertableToTraceFormat>
-TracedPicture::AsTraceablePictureAlias(const Picture* original) {
- scoped_refptr<TracedPicture> ptr = new TracedPicture(original);
- ptr->is_alias_ = true;
- return scoped_refptr<base::trace_event::ConvertableToTraceFormat>(ptr);
-}
-
-void TracedPicture::AppendAsTraceFormat(std::string* out) const {
- if (is_alias_)
- AppendPictureAlias(out);
- else
- AppendPicture(out);
-}
-
-void TracedPicture::AppendPictureAlias(std::string* out) const {
- scoped_ptr<base::DictionaryValue> alias(new base::DictionaryValue());
- alias->SetString("id_ref", base::StringPrintf("%p", picture_.get()));
-
- base::DictionaryValue res;
- res.Set("alias", alias.release());
- std::string tmp;
- base::JSONWriter::Write(res, &tmp);
- out->append(tmp);
-}
-
-void TracedPicture::AppendPicture(std::string* out) const {
- std::string tmp;
- base::JSONWriter::Write(*picture_->AsValue(), &tmp);
- out->append(tmp);
-}
-
-} // namespace cc
diff --git a/chromium/cc/debug/traced_picture.h b/chromium/cc/debug/traced_picture.h
deleted file mode 100644
index 0cb044e7212..00000000000
--- a/chromium/cc/debug/traced_picture.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CC_DEBUG_TRACED_PICTURE_H_
-#define CC_DEBUG_TRACED_PICTURE_H_
-
-#include <string>
-
-#include "base/memory/scoped_ptr.h"
-#include "base/trace_event/trace_event.h"
-#include "cc/playback/picture.h"
-
-namespace cc {
-
-class TracedPicture : public base::trace_event::ConvertableToTraceFormat {
- public:
- explicit TracedPicture(scoped_refptr<const Picture>);
-
- static scoped_refptr<base::trace_event::ConvertableToTraceFormat>
- AsTraceablePicture(const Picture* picture);
-
- static scoped_refptr<base::trace_event::ConvertableToTraceFormat>
- AsTraceablePictureAlias(const Picture* original);
-
- void AppendAsTraceFormat(std::string* out) const override;
-
- private:
- ~TracedPicture() override;
-
- void AppendPicture(std::string* out) const;
- void AppendPictureAlias(std::string* out) const;
-
- scoped_refptr<const Picture> picture_;
- bool is_alias_;
-
- DISALLOW_COPY_AND_ASSIGN(TracedPicture);
-};
-
-} // namespace cc
-
-#endif // CC_DEBUG_TRACED_PICTURE_H_
diff --git a/chromium/cc/input/input_handler.h b/chromium/cc/input/input_handler.h
index 3401eceb553..4696fb5ceca 100644
--- a/chromium/cc/input/input_handler.h
+++ b/chromium/cc/input/input_handler.h
@@ -15,11 +15,15 @@
namespace gfx {
class Point;
class PointF;
+class ScrollOffset;
+class SizeF;
class Vector2d;
class Vector2dF;
}
-namespace ui { struct LatencyInfo; }
+namespace ui {
+class LatencyInfo;
+}
namespace cc {
@@ -49,6 +53,13 @@ class CC_EXPORT InputHandlerClient {
virtual void Animate(base::TimeTicks time) = 0;
virtual void MainThreadHasStoppedFlinging() = 0;
virtual void ReconcileElasticOverscrollAndRootScroll() = 0;
+ virtual void UpdateRootLayerStateForSynchronousInputHandler(
+ const gfx::ScrollOffset& total_scroll_offset,
+ const gfx::ScrollOffset& max_scroll_offset,
+ const gfx::SizeF& scrollable_size,
+ float page_scale_factor,
+ float min_page_scale_factor,
+ float max_page_scale_factor) = 0;
protected:
InputHandlerClient() {}
@@ -123,15 +134,14 @@ class CC_EXPORT InputHandler {
// returned SCROLL_STARTED.
virtual void ScrollEnd() = 0;
- virtual void SetRootLayerScrollOffsetDelegate(
- LayerScrollOffsetDelegate* root_layer_scroll_offset_delegate) = 0;
+ // Requests a callback to UpdateRootLayerStateForSynchronousInputHandler()
+ // giving the current root scroll and page scale information.
+ virtual void RequestUpdateForSynchronousInputHandler() = 0;
- // Called when the value returned by
- // LayerScrollOffsetDelegate.GetTotalScrollOffset has changed for reasons
- // other than a SetTotalScrollOffset call.
- // NOTE: This should only called after a valid delegate was set via a call to
- // SetRootLayerScrollOffsetDelegate.
- virtual void OnRootLayerDelegatedScrollOffsetChanged() = 0;
+ // Called when the root scroll offset has been changed in the synchronous
+ // input handler by the application (outside of input event handling).
+ virtual void SetSynchronousInputHandlerRootScrollOffset(
+ const gfx::ScrollOffset& root_offset) = 0;
virtual void PinchGestureBegin() = 0;
virtual void PinchGestureUpdate(float magnify_delta,
@@ -141,9 +151,13 @@ class CC_EXPORT InputHandler {
// Request another callback to InputHandlerClient::Animate().
virtual void SetNeedsAnimateInput() = 0;
+ // If there is a scroll active, this reports whether the scroll is on the
+ // root layer, or on some other sublayer.
+ virtual bool IsCurrentlyScrollingRoot() const = 0;
+
// Whether the layer under |viewport_point| is the currently scrolling layer.
virtual bool IsCurrentlyScrollingLayerAt(const gfx::Point& viewport_point,
- ScrollInputType type) = 0;
+ ScrollInputType type) const = 0;
virtual bool HaveWheelEventHandlersAt(const gfx::Point& viewport_point) = 0;
diff --git a/chromium/cc/input/layer_scroll_offset_delegate.h b/chromium/cc/input/layer_scroll_offset_delegate.h
deleted file mode 100644
index 0afc4db89e3..00000000000
--- a/chromium/cc/input/layer_scroll_offset_delegate.h
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CC_INPUT_LAYER_SCROLL_OFFSET_DELEGATE_H_
-#define CC_INPUT_LAYER_SCROLL_OFFSET_DELEGATE_H_
-
-#include "base/basictypes.h"
-#include "base/callback_forward.h"
-#include "base/time/time.h"
-#include "ui/gfx/geometry/scroll_offset.h"
-#include "ui/gfx/geometry/size_f.h"
-
-namespace cc {
-
-// The LayerScrollOffsetDelegate allows for the embedder to take ownership of
-// the scroll offset of the root layer.
-//
-// The LayerScrollOffsetDelegate is only used on the impl thread.
-class LayerScrollOffsetDelegate {
- public:
- // This is called by the compositor to query the current scroll offset of the
- // layer.
- // There is no requirement that the return values of this method are
- // stable in time (two subsequent calls may yield different results).
- // The return value is not required to be related to the values passed in to
- // the SetTotalScrollOffset method in any way however it is required to be no
- // more than the value passed to the most recent SetMaxScrollOffset call.
- virtual gfx::ScrollOffset GetTotalScrollOffset() = 0;
-
- // This is called by the compositor to notify the delegate of any change to
- // the following parameters:
- // |total_scroll_offset| current scroll offset of the root layer,
- // |max_scroll_offset| total scroll offset upper bound for the root layer,
- // |scrollable_size| root layer scrollable size,
- // |page_scale_factor| current page scale,
- // |min_page_scale_factor| page scale lower limit,
- // |max_page_scale_factor| page scale upper limit.
- virtual void UpdateRootLayerState(
- const gfx::ScrollOffset& total_scroll_offset,
- const gfx::ScrollOffset& max_scroll_offset,
- const gfx::SizeF& scrollable_size,
- float page_scale_factor,
- float min_page_scale_factor,
- float max_page_scale_factor) = 0;
-
- // This is called by the compositor to check whether a delegate-managed fling
- // is active or not.
- // TODO(hush): Remove after WebView's smooth scrolling path is unified with
- // Chrome's.
- virtual bool IsExternalScrollActive() const = 0;
-
- // This is called by the compositor when a fling hitting the root layer
- // requires a scheduled animation update.
- typedef base::Callback<void(base::TimeTicks)> AnimationCallback;
- virtual void SetNeedsAnimate(const AnimationCallback& animation) = 0;
-
- protected:
- LayerScrollOffsetDelegate() {}
- virtual ~LayerScrollOffsetDelegate() {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(LayerScrollOffsetDelegate);
-};
-
-} // namespace cc
-
-#endif // CC_INPUT_LAYER_SCROLL_OFFSET_DELEGATE_H_
diff --git a/chromium/cc/input/page_scale_animation.cc b/chromium/cc/input/page_scale_animation.cc
index 111502b95cd..1e2954419d3 100644
--- a/chromium/cc/input/page_scale_animation.cc
+++ b/chromium/cc/input/page_scale_animation.cc
@@ -147,7 +147,7 @@ void PageScaleAnimation::InferTargetAnchorFromScrollOffsets() {
void PageScaleAnimation::ClampTargetScrollOffset() {
gfx::Vector2dF max_scroll_offset =
gfx::RectF(root_layer_size_).bottom_right() -
- gfx::RectF(TargetViewportSize()).bottom_right();
+ gfx::RectF(gfx::SizeF(TargetViewportSize())).bottom_right();
target_scroll_offset_.SetToMax(gfx::Vector2dF());
target_scroll_offset_.SetToMin(max_scroll_offset);
}
diff --git a/chromium/cc/input/page_scale_animation.h b/chromium/cc/input/page_scale_animation.h
index 0e430c212fe..d73116c5d7d 100644
--- a/chromium/cc/input/page_scale_animation.h
+++ b/chromium/cc/input/page_scale_animation.h
@@ -9,7 +9,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
#include "cc/base/cc_export.h"
-#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/geometry/size_f.h"
#include "ui/gfx/geometry/vector2d.h"
#include "ui/gfx/geometry/vector2d_f.h"
diff --git a/chromium/cc/input/scroll_state.cc b/chromium/cc/input/scroll_state.cc
new file mode 100644
index 00000000000..52a0cca6943
--- /dev/null
+++ b/chromium/cc/input/scroll_state.cc
@@ -0,0 +1,46 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/input/scroll_state.h"
+
+#include "cc/layers/layer_impl.h"
+
+namespace cc {
+
+ScrollState::ScrollState(double delta_x,
+ double delta_y,
+ int start_position_x,
+ int start_position_y,
+ bool should_propagate,
+ bool delta_consumed_for_scroll_sequence,
+ bool is_direct_manipulation)
+ : delta_x_(delta_x),
+ delta_y_(delta_y),
+ start_position_x_(start_position_x),
+ start_position_y_(start_position_y),
+ should_propagate_(should_propagate),
+ delta_consumed_for_scroll_sequence_(delta_consumed_for_scroll_sequence),
+ is_direct_manipulation_(is_direct_manipulation),
+ caused_scroll_x_(false),
+ caused_scroll_y_(false) {}
+
+ScrollState::~ScrollState() {}
+
+void ScrollState::ConsumeDelta(double x, double y) {
+ delta_x_ -= x;
+ delta_y_ -= y;
+
+ if (x || y)
+ delta_consumed_for_scroll_sequence_ = true;
+}
+
+void ScrollState::DistributeToScrollChainDescendant() {
+ if (!scroll_chain_.empty()) {
+ LayerImpl* next = scroll_chain_.front();
+ scroll_chain_.pop_front();
+ next->DistributeScroll(this);
+ }
+}
+
+} // namespace cc
diff --git a/chromium/cc/input/scroll_state.h b/chromium/cc/input/scroll_state.h
new file mode 100644
index 00000000000..2cd437d0ea7
--- /dev/null
+++ b/chromium/cc/input/scroll_state.h
@@ -0,0 +1,108 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_INPUT_SCROLL_STATE_H_
+#define CC_INPUT_SCROLL_STATE_H_
+
+#include <list>
+
+#include "cc/base/cc_export.h"
+
+namespace cc {
+
+class LayerImpl;
+
+// ScrollState is based on the proposal for scroll customization in blink, found
+// here: https://goo.gl/1ipTpP.
+class CC_EXPORT ScrollState {
+ public:
+ ScrollState(double delta_x,
+ double delta_y,
+ int start_position_x,
+ int start_position_y,
+ bool should_propagate,
+ bool delta_consumed_for_scroll_sequence,
+ bool is_direct_manipulation);
+ ~ScrollState();
+
+ // Reduce deltas by x, y.
+ void ConsumeDelta(double x, double y);
+ // Pops the first layer off of |scroll_chain_| and calls
+ // |DistributeScroll| on it.
+ void DistributeToScrollChainDescendant();
+ // Positive when scrolling left.
+ double delta_x() const { return delta_x_; }
+ // Positive when scrolling up.
+ double delta_y() const { return delta_y_; }
+ // The location the scroll started at. For touch, the starting
+ // position of the finger. For mouse, the location of the cursor.
+ int start_position_x() const { return start_position_x_; }
+ int start_position_y() const { return start_position_y_; }
+
+ // True if this scroll is allowed to bubble upwards.
+ bool should_propagate() const { return should_propagate_; }
+ // True if the user interacts directly with the screen, e.g., via touch.
+ bool is_direct_manipulation() const { return is_direct_manipulation_; }
+
+ void set_scroll_chain(const std::list<LayerImpl*>& scroll_chain) {
+ scroll_chain_ = scroll_chain;
+ }
+
+ void set_current_native_scrolling_layer(LayerImpl* layer) {
+ current_native_scrolling_layer_ = layer;
+ }
+
+ LayerImpl* current_native_scrolling_layer() const {
+ return current_native_scrolling_layer_;
+ }
+
+ bool delta_consumed_for_scroll_sequence() const {
+ return delta_consumed_for_scroll_sequence_;
+ }
+
+ bool FullyConsumed() const { return !delta_x_ && !delta_y_; }
+
+ void set_caused_scroll(bool x, bool y) {
+ caused_scroll_x_ |= x;
+ caused_scroll_y_ |= y;
+ }
+
+ bool caused_scroll_x() const { return caused_scroll_x_; }
+ bool caused_scroll_y() const { return caused_scroll_y_; }
+
+ private:
+ ScrollState();
+ double delta_x_;
+ double delta_y_;
+ double start_position_x_;
+ double start_position_y_;
+
+ bool should_propagate_;
+
+ // The last layer to respond to a scroll, or null if none exists.
+ LayerImpl* current_native_scrolling_layer_;
+ // Whether the scroll sequence has had any delta consumed, in the
+ // current frame, or any child frames.
+ bool delta_consumed_for_scroll_sequence_;
+ // True if the user interacts directly with the display, e.g., via
+ // touch.
+ bool is_direct_manipulation_;
+ // TODO(tdresser): ScrollState shouldn't need to keep track of whether or not
+ // this ScrollState object has caused a scroll. Ideally, any native scroller
+ // consuming delta has caused a scroll. Currently, there are some cases where
+ // we consume delta without scrolling, such as in
+ // |Viewport::AdjustOverscroll|. Once these cases are fixed, we should get rid
+ // of |caused_scroll_*_|. See crbug.com/510045 for details.
+ bool caused_scroll_x_;
+ bool caused_scroll_y_;
+
+ // TODO(tdresser): Change LayerImpl* to an abstract scrollable type. See
+ // crbug.com/476553 for detail on the effort to unify impl and main thread
+ // scrolling, which will require an abstract scrollable type.
+ std::list<LayerImpl*> scroll_chain_;
+};
+
+} // namespace cc
+
+#endif // CC_INPUT_SCROLL_STATE_H_
diff --git a/chromium/cc/input/scroll_state_unittest.cc b/chromium/cc/input/scroll_state_unittest.cc
new file mode 100644
index 00000000000..5e091df685f
--- /dev/null
+++ b/chromium/cc/input/scroll_state_unittest.cc
@@ -0,0 +1,79 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/input/scroll_state.h"
+
+#include "cc/layers/layer_impl.h"
+#include "cc/test/fake_impl_proxy.h"
+#include "cc/test/fake_layer_tree_host_impl.h"
+#include "cc/test/test_shared_bitmap_manager.h"
+#include "cc/test/test_task_graph_runner.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace cc {
+
+class ScrollStateTest : public testing::Test {};
+
+TEST_F(ScrollStateTest, ConsumeDeltaNative) {
+ const float delta_x = 12.3f;
+ const float delta_y = 3.9f;
+
+ const float delta_x_to_consume = 1.2f;
+ const float delta_y_to_consume = 2.3f;
+
+ ScrollState scrollState(delta_x, delta_y, 0, 0, false /* should_propagate */,
+ false /* delta_consumed_for_scroll_sequence */,
+ false /* is_direct_manipulation */);
+ EXPECT_FLOAT_EQ(delta_x, scrollState.delta_x());
+ EXPECT_FLOAT_EQ(delta_y, scrollState.delta_y());
+ EXPECT_FALSE(scrollState.delta_consumed_for_scroll_sequence());
+ EXPECT_FALSE(scrollState.FullyConsumed());
+
+ scrollState.ConsumeDelta(0, 0);
+ EXPECT_FLOAT_EQ(delta_x, scrollState.delta_x());
+ EXPECT_FLOAT_EQ(delta_y, scrollState.delta_y());
+ EXPECT_FALSE(scrollState.delta_consumed_for_scroll_sequence());
+ EXPECT_FALSE(scrollState.FullyConsumed());
+
+ scrollState.ConsumeDelta(delta_x_to_consume, 0);
+ EXPECT_FLOAT_EQ(delta_x - delta_x_to_consume, scrollState.delta_x());
+ EXPECT_FLOAT_EQ(delta_y, scrollState.delta_y());
+ EXPECT_TRUE(scrollState.delta_consumed_for_scroll_sequence());
+ EXPECT_FALSE(scrollState.FullyConsumed());
+
+ scrollState.ConsumeDelta(0, delta_y_to_consume);
+ EXPECT_FLOAT_EQ(delta_x - delta_x_to_consume, scrollState.delta_x());
+ EXPECT_FLOAT_EQ(delta_y - delta_y_to_consume, scrollState.delta_y());
+ EXPECT_TRUE(scrollState.delta_consumed_for_scroll_sequence());
+ EXPECT_FALSE(scrollState.FullyConsumed());
+
+ scrollState.ConsumeDelta(scrollState.delta_x(), scrollState.delta_y());
+ EXPECT_TRUE(scrollState.delta_consumed_for_scroll_sequence());
+ EXPECT_TRUE(scrollState.FullyConsumed());
+}
+
+TEST_F(ScrollStateTest, CurrentNativeScrollingScrollable) {
+ ScrollState scrollState(0, 0, 0, 0, false, false, false);
+
+ FakeImplProxy proxy;
+ TestSharedBitmapManager shared_bitmap_manager;
+ TestTaskGraphRunner task_graph_runner;
+ FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager,
+ &task_graph_runner);
+
+ scoped_ptr<LayerImpl> layer_impl =
+ LayerImpl::Create(host_impl.active_tree(), 1);
+ scrollState.set_current_native_scrolling_layer(layer_impl.get());
+ EXPECT_EQ(layer_impl, scrollState.current_native_scrolling_layer());
+}
+
+TEST_F(ScrollStateTest, FullyConsumed) {
+ ScrollState scrollState(1, 3, 0, 0, 0, false, false);
+ EXPECT_FALSE(scrollState.FullyConsumed());
+
+ scrollState.ConsumeDelta(1, 3);
+ EXPECT_TRUE(scrollState.FullyConsumed());
+}
+} // namespace cc
diff --git a/chromium/cc/layers/content_layer_client.h b/chromium/cc/layers/content_layer_client.h
index 3a56263248d..deb9d619e32 100644
--- a/chromium/cc/layers/content_layer_client.h
+++ b/chromium/cc/layers/content_layer_client.h
@@ -37,6 +37,12 @@ class CC_EXPORT ContentLayerClient {
// because it will cover any uncleared data with content.
virtual bool FillsBoundsCompletely() const = 0;
+ // Returns an estimate of the current memory usage within this object,
+ // excluding memory shared with painting artifacts (i.e.,
+ // DisplayItemList). Should be invoked after PaintContentsToDisplayList,
+ // so that the result includes data cached internally during painting.
+ virtual size_t GetApproximateUnsharedMemoryUsage() const = 0;
+
protected:
virtual ~ContentLayerClient() {}
};
diff --git a/chromium/cc/layers/delegated_frame_provider.cc b/chromium/cc/layers/delegated_frame_provider.cc
index bae5e438c0a..5e016ebc6ac 100644
--- a/chromium/cc/layers/delegated_frame_provider.cc
+++ b/chromium/cc/layers/delegated_frame_provider.cc
@@ -33,7 +33,7 @@ void DelegatedFrameProvider::AddObserver(DelegatedRendererLayer* layer) {
DCHECK(observers_[i].layer != layer);
#endif
- observers_.push_back(Observer(layer, gfx::RectF(frame_size_)));
+ observers_.push_back(Observer(layer, gfx::Rect(frame_size_)));
DCHECK(frame_) << "Must have a frame when given to a DelegatedRendererLayer.";
}
@@ -80,15 +80,14 @@ void DelegatedFrameProvider::SetFrameData(
DelegatedFrameData* DelegatedFrameProvider::GetFrameDataAndRefResources(
DelegatedRendererLayer* observer,
- gfx::RectF* damage) {
-
+ gfx::Rect* damage) {
bool found_observer = false;
for (size_t i = 0; i < observers_.size(); ++i) {
if (observers_[i].layer != observer)
continue;
*damage = observers_[i].damage;
// The observer is now responsible for the damage.
- observers_[i].damage = gfx::RectF();
+ observers_[i].damage = gfx::Rect();
found_observer = true;
}
DCHECK(found_observer);
diff --git a/chromium/cc/layers/delegated_frame_provider.h b/chromium/cc/layers/delegated_frame_provider.h
index 3bcf91957c8..f3f93732a6e 100644
--- a/chromium/cc/layers/delegated_frame_provider.h
+++ b/chromium/cc/layers/delegated_frame_provider.h
@@ -12,7 +12,7 @@
#include "cc/base/cc_export.h"
#include "cc/resources/return_callback.h"
#include "cc/resources/returned_resource.h"
-#include "ui/gfx/geometry/rect_f.h"
+#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
namespace cc {
@@ -41,7 +41,7 @@ class CC_EXPORT DelegatedFrameProvider
// lose track of damage.
DelegatedFrameData* GetFrameDataAndRefResources(
DelegatedRendererLayer* observer,
- gfx::RectF* damage);
+ gfx::Rect* damage);
ReturnCallback GetReturnResourcesCallbackForImplThread();
void UnrefResourcesOnMainThread(const ReturnedResourceArray& unused);
@@ -58,9 +58,9 @@ class CC_EXPORT DelegatedFrameProvider
struct Observer {
DelegatedRendererLayer* layer;
- gfx::RectF damage;
+ gfx::Rect damage;
- Observer(DelegatedRendererLayer* layer, const gfx::RectF& damage)
+ Observer(DelegatedRendererLayer* layer, const gfx::Rect& damage)
: layer(layer), damage(damage) {}
};
std::vector<Observer> observers_;
diff --git a/chromium/cc/layers/delegated_frame_provider_unittest.cc b/chromium/cc/layers/delegated_frame_provider_unittest.cc
index 3aef0d18c7d..4248899641a 100644
--- a/chromium/cc/layers/delegated_frame_provider_unittest.cc
+++ b/chromium/cc/layers/delegated_frame_provider_unittest.cc
@@ -159,20 +159,20 @@ TEST_F(DelegatedFrameProviderTest, RefResources) {
scoped_refptr<DelegatedRendererLayer> observer2 =
DelegatedRendererLayer::Create(layer_settings_, frame_provider_);
- gfx::RectF damage;
+ gfx::Rect damage;
// Both observers get a full frame of damage on the first request.
frame_provider_->GetFrameDataAndRefResources(observer1.get(), &damage);
- EXPECT_EQ(gfx::RectF(5.f, 5.f).ToString(), damage.ToString());
+ EXPECT_EQ(gfx::Rect(5, 5), damage);
frame_provider_->GetFrameDataAndRefResources(observer2.get(), &damage);
- EXPECT_EQ(gfx::RectF(5.f, 5.f).ToString(), damage.ToString());
+ EXPECT_EQ(gfx::Rect(5, 5), damage);
// And both get no damage on the 2nd request. This adds a second ref to the
// resources.
frame_provider_->GetFrameDataAndRefResources(observer1.get(), &damage);
- EXPECT_EQ(gfx::RectF().ToString(), damage.ToString());
+ EXPECT_EQ(gfx::Rect(), damage);
frame_provider_->GetFrameDataAndRefResources(observer2.get(), &damage);
- EXPECT_EQ(gfx::RectF().ToString(), damage.ToString());
+ EXPECT_EQ(gfx::Rect(), damage);
EXPECT_FALSE(ReturnAndResetResourcesAvailable());
@@ -217,7 +217,7 @@ TEST_F(DelegatedFrameProviderTest, RefResourcesInFrameProvider) {
scoped_refptr<DelegatedRendererLayer> observer2 =
DelegatedRendererLayer::Create(layer_settings_, frame_provider_);
- gfx::RectF damage;
+ gfx::Rect damage;
// Take a ref on each observer.
frame_provider_->GetFrameDataAndRefResources(observer1.get(), &damage);
@@ -259,7 +259,7 @@ TEST_F(DelegatedFrameProviderTest, RefResourcesInFrameProviderUntilDestroy) {
scoped_refptr<DelegatedRendererLayer> observer2 =
DelegatedRendererLayer::Create(layer_settings_, frame_provider_);
- gfx::RectF damage;
+ gfx::Rect damage;
// Take a ref on each observer.
frame_provider_->GetFrameDataAndRefResources(observer1.get(), &damage);
@@ -303,19 +303,19 @@ TEST_F(DelegatedFrameProviderTest, Damage) {
scoped_refptr<DelegatedRendererLayer> observer2 =
DelegatedRendererLayer::Create(layer_settings_, frame_provider_);
- gfx::RectF damage;
+ gfx::Rect damage;
// Both observers get a full frame of damage on the first request.
frame_provider_->GetFrameDataAndRefResources(observer1.get(), &damage);
- EXPECT_EQ(gfx::RectF(5.f, 5.f).ToString(), damage.ToString());
+ EXPECT_EQ(gfx::Rect(5, 5), damage);
frame_provider_->GetFrameDataAndRefResources(observer2.get(), &damage);
- EXPECT_EQ(gfx::RectF(5.f, 5.f).ToString(), damage.ToString());
+ EXPECT_EQ(gfx::Rect(5, 5), damage);
// And both get no damage on the 2nd request.
frame_provider_->GetFrameDataAndRefResources(observer1.get(), &damage);
- EXPECT_EQ(gfx::RectF().ToString(), damage.ToString());
+ EXPECT_EQ(gfx::Rect(), damage);
frame_provider_->GetFrameDataAndRefResources(observer2.get(), &damage);
- EXPECT_EQ(gfx::RectF().ToString(), damage.ToString());
+ EXPECT_EQ(gfx::Rect(), damage);
frame = CreateFrameData(gfx::Rect(5, 5), gfx::Rect(2, 2));
AddTextureQuad(frame.get(), 555);
@@ -324,15 +324,15 @@ TEST_F(DelegatedFrameProviderTest, Damage) {
// Both observers get the damage for the new frame.
frame_provider_->GetFrameDataAndRefResources(observer1.get(), &damage);
- EXPECT_EQ(gfx::RectF(2.f, 2.f).ToString(), damage.ToString());
+ EXPECT_EQ(gfx::Rect(2, 2), damage);
frame_provider_->GetFrameDataAndRefResources(observer2.get(), &damage);
- EXPECT_EQ(gfx::RectF(2.f, 2.f).ToString(), damage.ToString());
+ EXPECT_EQ(gfx::Rect(2, 2), damage);
// And both get no damage on the 2nd request.
frame_provider_->GetFrameDataAndRefResources(observer1.get(), &damage);
- EXPECT_EQ(gfx::RectF().ToString(), damage.ToString());
+ EXPECT_EQ(gfx::Rect(), damage);
frame_provider_->GetFrameDataAndRefResources(observer2.get(), &damage);
- EXPECT_EQ(gfx::RectF().ToString(), damage.ToString());
+ EXPECT_EQ(gfx::Rect(), damage);
}
TEST_F(DelegatedFrameProviderTest, LostNothing) {
diff --git a/chromium/cc/layers/delegated_renderer_layer.cc b/chromium/cc/layers/delegated_renderer_layer.cc
index b48d1eae91e..4c0e3cca9da 100644
--- a/chromium/cc/layers/delegated_renderer_layer.cc
+++ b/chromium/cc/layers/delegated_renderer_layer.cc
@@ -72,7 +72,7 @@ void DelegatedRendererLayer::PushPropertiesTo(LayerImpl* impl) {
if (frame_data_)
delegated_impl->SetFrameData(frame_data_, frame_damage_);
frame_data_ = nullptr;
- frame_damage_ = gfx::RectF();
+ frame_damage_ = gfx::Rect();
}
void DelegatedRendererLayer::ProviderHasNewFrame() {
diff --git a/chromium/cc/layers/delegated_renderer_layer.h b/chromium/cc/layers/delegated_renderer_layer.h
index 124b389a0f7..8845258895c 100644
--- a/chromium/cc/layers/delegated_renderer_layer.h
+++ b/chromium/cc/layers/delegated_renderer_layer.h
@@ -44,7 +44,7 @@ class CC_EXPORT DelegatedRendererLayer : public Layer {
bool should_collect_new_frame_;
DelegatedFrameData* frame_data_;
- gfx::RectF frame_damage_;
+ gfx::Rect frame_damage_;
base::WeakPtrFactory<DelegatedRendererLayer> weak_ptrs_;
diff --git a/chromium/cc/layers/delegated_renderer_layer_impl.cc b/chromium/cc/layers/delegated_renderer_layer_impl.cc
index 9235af5a826..9b3a513206c 100644
--- a/chromium/cc/layers/delegated_renderer_layer_impl.cc
+++ b/chromium/cc/layers/delegated_renderer_layer_impl.cc
@@ -87,7 +87,7 @@ void DelegatedRendererLayerImpl::CreateChildIdIfNeeded(
void DelegatedRendererLayerImpl::SetFrameData(
const DelegatedFrameData* frame_data,
- const gfx::RectF& damage_in_frame) {
+ const gfx::Rect& damage_in_frame) {
DCHECK(child_id_) << "CreateChildIdIfNeeded must be called first.";
DCHECK(frame_data);
DCHECK(!frame_data->render_pass_list.empty());
@@ -153,11 +153,10 @@ void DelegatedRendererLayerImpl::SetFrameData(
// the frame, so intersect the damage to the layer's bounds.
RenderPass* new_root_pass = render_pass_list.back();
gfx::Size frame_size = new_root_pass->output_rect.size();
- gfx::RectF damage_in_layer = damage_in_frame;
- damage_in_layer.Scale(inverse_device_scale_factor_);
+ gfx::Rect damage_in_layer =
+ gfx::ScaleToEnclosingRect(damage_in_frame, inverse_device_scale_factor_);
SetUpdateRect(gfx::IntersectRects(
- gfx::UnionRects(update_rect(), gfx::ToEnclosingRect(damage_in_layer)),
- gfx::Rect(bounds())));
+ gfx::UnionRects(update_rect(), damage_in_layer), gfx::Rect(bounds())));
SetRenderPasses(&render_pass_list);
have_render_passes_to_push_ = true;
diff --git a/chromium/cc/layers/delegated_renderer_layer_impl.h b/chromium/cc/layers/delegated_renderer_layer_impl.h
index 2543894c5d4..e59c3ac8760 100644
--- a/chromium/cc/layers/delegated_renderer_layer_impl.h
+++ b/chromium/cc/layers/delegated_renderer_layer_impl.h
@@ -45,7 +45,7 @@ class CC_EXPORT DelegatedRendererLayerImpl : public LayerImpl {
void CreateChildIdIfNeeded(const ReturnCallback& return_callback);
void SetFrameData(const DelegatedFrameData* frame_data,
- const gfx::RectF& damage_in_frame);
+ const gfx::Rect& damage_in_frame);
float inverse_device_scale_factor() const {
return inverse_device_scale_factor_;
diff --git a/chromium/cc/layers/delegated_renderer_layer_impl_unittest.cc b/chromium/cc/layers/delegated_renderer_layer_impl_unittest.cc
index a2e8d704725..5deef6c11bc 100644
--- a/chromium/cc/layers/delegated_renderer_layer_impl_unittest.cc
+++ b/chromium/cc/layers/delegated_renderer_layer_impl_unittest.cc
@@ -15,7 +15,6 @@
#include "cc/test/fake_output_surface.h"
#include "cc/test/geometry_test_utils.h"
#include "cc/test/layer_test_common.h"
-#include "cc/test/render_pass_test_common.h"
#include "cc/test/render_pass_test_utils.h"
#include "cc/test/test_shared_bitmap_manager.h"
#include "cc/test/test_task_graph_runner.h"
@@ -33,13 +32,14 @@ class DelegatedRendererLayerImplTest : public testing::Test {
public:
DelegatedRendererLayerImplTest()
: proxy_(),
- always_impl_thread_and_main_thread_blocked_(&proxy_) {
+ always_impl_thread_and_main_thread_blocked_(&proxy_),
+ output_surface_(FakeOutputSurface::Create3d()) {
LayerTreeSettings settings;
settings.minimum_occlusion_tracking_size = gfx::Size();
host_impl_.reset(new FakeLayerTreeHostImpl(
settings, &proxy_, &shared_bitmap_manager_, &task_graph_runner_));
- host_impl_->InitializeRenderer(FakeOutputSurface::Create3d());
+ host_impl_->InitializeRenderer(output_surface_.get());
host_impl_->SetViewportSize(gfx::Size(10, 10));
}
@@ -49,6 +49,7 @@ class DelegatedRendererLayerImplTest : public testing::Test {
always_impl_thread_and_main_thread_blocked_;
TestSharedBitmapManager shared_bitmap_manager_;
TestTaskGraphRunner task_graph_runner_;
+ scoped_ptr<OutputSurface> output_surface_;
scoped_ptr<LayerTreeHostImpl> host_impl_;
};
@@ -88,21 +89,18 @@ class DelegatedRendererLayerImplTestSimple
delegated_renderer_layer->SetTransform(transform);
RenderPassList delegated_render_passes;
- TestRenderPass* pass1 = AddRenderPass(&delegated_render_passes,
- RenderPassId(9, 6),
- gfx::Rect(6, 6, 6, 6),
- gfx::Transform(1, 0, 0, 1, 5, 6));
+ RenderPass* pass1 =
+ AddRenderPass(&delegated_render_passes, RenderPassId(9, 6),
+ gfx::Rect(6, 6, 6, 6), gfx::Transform(1, 0, 0, 1, 5, 6));
AddQuad(pass1, gfx::Rect(0, 0, 6, 6), 33u);
- TestRenderPass* pass2 = AddRenderPass(&delegated_render_passes,
- RenderPassId(9, 7),
- gfx::Rect(7, 7, 7, 7),
- gfx::Transform(1, 0, 0, 1, 7, 8));
+ RenderPass* pass2 =
+ AddRenderPass(&delegated_render_passes, RenderPassId(9, 7),
+ gfx::Rect(7, 7, 7, 7), gfx::Transform(1, 0, 0, 1, 7, 8));
AddQuad(pass2, gfx::Rect(0, 0, 7, 7), 22u);
AddRenderPassQuad(pass2, pass1);
- TestRenderPass* pass3 = AddRenderPass(&delegated_render_passes,
- RenderPassId(9, 8),
- gfx::Rect(0, 0, 8, 8),
- gfx::Transform(1, 0, 0, 1, 9, 10));
+ RenderPass* pass3 =
+ AddRenderPass(&delegated_render_passes, RenderPassId(9, 8),
+ gfx::Rect(0, 0, 8, 8), gfx::Transform(1, 0, 0, 1, 9, 10));
AddRenderPassQuad(pass3, pass2);
delegated_renderer_layer->SetFrameDataForRenderPasses(
1.f, delegated_render_passes);
@@ -152,16 +150,16 @@ TEST_F(DelegatedRendererLayerImplTest,
delegated_renderer_layer->SetTransform(transform);
RenderPassList delegated_render_passes;
- TestRenderPass* pass1 =
+ RenderPass* pass1 =
AddRenderPass(&delegated_render_passes, RenderPassId(9, 6),
gfx::Rect(6, 6, 6, 6), gfx::Transform(1, 0, 0, 1, 5, 6));
AddQuad(pass1, gfx::Rect(0, 0, 6, 6), 33u);
- TestRenderPass* pass2 =
+ RenderPass* pass2 =
AddRenderPass(&delegated_render_passes, RenderPassId(9, 7),
gfx::Rect(7, 7, 7, 7), gfx::Transform(1, 0, 0, 1, 7, 8));
AddQuad(pass2, gfx::Rect(0, 0, 7, 7), 22u);
AddRenderPassQuad(pass2, pass1);
- TestRenderPass* pass3 =
+ RenderPass* pass3 =
AddRenderPass(&delegated_render_passes, RenderPassId(9, 8),
gfx::Rect(0, 0, 8, 8), gfx::Transform(1, 0, 0, 1, 9, 10));
AddRenderPassQuad(pass3, pass2);
@@ -231,16 +229,16 @@ TEST_F(DelegatedRendererLayerImplTest,
delegated_renderer_layer->SetTransform(transform);
RenderPassList delegated_render_passes;
- TestRenderPass* pass1 =
+ RenderPass* pass1 =
AddRenderPass(&delegated_render_passes, RenderPassId(9, 6),
gfx::Rect(6, 6, 6, 6), gfx::Transform(1, 0, 0, 1, 5, 6));
AddQuad(pass1, gfx::Rect(0, 0, 6, 6), 33u);
- TestRenderPass* pass2 =
+ RenderPass* pass2 =
AddRenderPass(&delegated_render_passes, RenderPassId(9, 7),
gfx::Rect(7, 7, 7, 7), gfx::Transform(1, 0, 0, 1, 7, 8));
AddQuad(pass2, gfx::Rect(0, 0, 7, 7), 22u);
AddRenderPassQuad(pass2, pass1);
- TestRenderPass* pass3 =
+ RenderPass* pass3 =
AddRenderPass(&delegated_render_passes, RenderPassId(9, 8),
gfx::Rect(0, 0, 8, 8), gfx::Transform(1, 0, 0, 1, 9, 10));
AddRenderPassQuad(pass3, pass2);
@@ -615,7 +613,7 @@ class DelegatedRendererLayerImplTestTransform
delegated_device_scale_factor_(2.f) {}
void SetUpTest() {
- host_impl_->SetDeviceScaleFactor(2.f);
+ host_impl_->active_tree()->SetDeviceScaleFactor(2.f);
scoped_ptr<LayerImpl> root_layer = LayerImpl::Create(
host_impl_->active_tree(), 1);
@@ -645,10 +643,9 @@ class DelegatedRendererLayerImplTestTransform
bool child_pass_clipped = false;
{
- TestRenderPass* pass = AddRenderPass(&delegated_render_passes,
- RenderPassId(10, 7),
- child_pass_rect,
- gfx::Transform());
+ RenderPass* pass =
+ AddRenderPass(&delegated_render_passes, RenderPassId(10, 7),
+ child_pass_rect, gfx::Transform());
SharedQuadState* shared_quad_state =
pass->CreateAndAppendSharedQuadState();
shared_quad_state->SetAll(child_pass_transform, child_pass_bounds,
@@ -680,10 +677,9 @@ class DelegatedRendererLayerImplTestTransform
gfx::Rect root_pass_clip_rect(10, 10, 35, 35);
bool root_pass_clipped = root_delegated_render_pass_is_clipped_;
- TestRenderPass* pass = AddRenderPass(&delegated_render_passes,
- RenderPassId(9, 6),
- root_pass_rect,
- gfx::Transform());
+ RenderPass* pass =
+ AddRenderPass(&delegated_render_passes, RenderPassId(9, 6),
+ root_pass_rect, gfx::Transform());
SharedQuadState* shared_quad_state = pass->CreateAndAppendSharedQuadState();
shared_quad_state->SetAll(root_pass_transform, root_pass_bounds,
root_pass_rect, root_pass_clip_rect,
@@ -1067,10 +1063,9 @@ class DelegatedRendererLayerImplTestClip
bool child_pass_clipped = false;
{
- TestRenderPass* pass = AddRenderPass(&delegated_render_passes,
- RenderPassId(10, 7),
- child_pass_rect,
- gfx::Transform());
+ RenderPass* pass =
+ AddRenderPass(&delegated_render_passes, RenderPassId(10, 7),
+ child_pass_rect, gfx::Transform());
SharedQuadState* shared_quad_state =
pass->CreateAndAppendSharedQuadState();
shared_quad_state->SetAll(child_pass_transform, child_pass_bounds,
@@ -1100,10 +1095,9 @@ class DelegatedRendererLayerImplTestClip
gfx::Rect root_pass_clip_rect(5, 5, 40, 40);
bool root_pass_clipped = root_delegated_render_pass_is_clipped_;
- TestRenderPass* pass = AddRenderPass(&delegated_render_passes,
- RenderPassId(9, 6),
- root_pass_rect,
- gfx::Transform());
+ RenderPass* pass =
+ AddRenderPass(&delegated_render_passes, RenderPassId(9, 6),
+ root_pass_rect, gfx::Transform());
SharedQuadState* shared_quad_state = pass->CreateAndAppendSharedQuadState();
shared_quad_state->SetAll(root_pass_transform, root_pass_bounds,
root_pass_rect, root_pass_clip_rect,
@@ -1250,6 +1244,7 @@ TEST_F(DelegatedRendererLayerImplTestClip,
SetUpTest();
LayerTreeHostImpl::FrameData frame;
+ host_impl_->active_tree()->BuildPropertyTreesForTesting();
EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
ASSERT_EQ(2u, frame.render_passes.size());
@@ -1280,6 +1275,7 @@ TEST_F(DelegatedRendererLayerImplTestClip,
SetUpTest();
LayerTreeHostImpl::FrameData frame;
+ host_impl_->active_tree()->BuildPropertyTreesForTesting();
EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
ASSERT_EQ(2u, frame.render_passes.size());
@@ -1370,6 +1366,7 @@ TEST_F(DelegatedRendererLayerImplTestClip,
delegated_renderer_layer_->SetHasRenderSurface(true);
LayerTreeHostImpl::FrameData frame;
+ host_impl_->active_tree()->BuildPropertyTreesForTesting();
EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
ASSERT_EQ(3u, frame.render_passes.size());
@@ -1398,6 +1395,7 @@ TEST_F(DelegatedRendererLayerImplTestClip, QuadsClipped_LayerClipped_Surface) {
delegated_renderer_layer_->SetHasRenderSurface(true);
LayerTreeHostImpl::FrameData frame;
+ host_impl_->active_tree()->BuildPropertyTreesForTesting();
EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
ASSERT_EQ(3u, frame.render_passes.size());
@@ -1443,17 +1441,14 @@ TEST_F(DelegatedRendererLayerImplTest, Occlusion) {
// translation of (211,300).
RenderPassId pass2_id =
delegated_renderer_layer_impl->FirstContributingRenderPassId();
- TestRenderPass* pass2 = AddRenderPass(&delegated_render_passes,
- pass2_id,
- gfx::Rect(quad_screen_rect.size()),
- transform);
+ RenderPass* pass2 =
+ AddRenderPass(&delegated_render_passes, pass2_id,
+ gfx::Rect(quad_screen_rect.size()), transform);
AddQuad(pass2, gfx::Rect(quad_screen_rect.size()), SK_ColorRED);
// |pass1| covers the whole layer.
RenderPassId pass1_id = RenderPassId(impl.root_layer()->id(), 0);
- TestRenderPass* pass1 = AddRenderPass(&delegated_render_passes,
- pass1_id,
- gfx::Rect(layer_size),
- gfx::Transform());
+ RenderPass* pass1 = AddRenderPass(&delegated_render_passes, pass1_id,
+ gfx::Rect(layer_size), gfx::Transform());
AddRenderPassQuad(pass1,
pass2,
0,
@@ -1610,15 +1605,14 @@ TEST_F(DelegatedRendererLayerImplTest, DeviceScaleFactorOcclusion) {
// translation of (211,300).
RenderPassId pass2_id =
delegated_renderer_layer_impl->FirstContributingRenderPassId();
- TestRenderPass* pass2 =
+ RenderPass* pass2 =
AddRenderPass(&delegated_render_passes, pass2_id,
gfx::Rect(quad_screen_rect.size()), transform);
AddQuad(pass2, gfx::Rect(quad_screen_rect.size()), SK_ColorRED);
// |pass1| covers the whole layer.
RenderPassId pass1_id = RenderPassId(impl.root_layer()->id(), 0);
- TestRenderPass* pass1 =
- AddRenderPass(&delegated_render_passes, pass1_id, gfx::Rect(layer_size),
- gfx::Transform());
+ RenderPass* pass1 = AddRenderPass(&delegated_render_passes, pass1_id,
+ gfx::Rect(layer_size), gfx::Transform());
AddRenderPassQuad(pass1, pass2, 0, FilterOperations(), transform,
SkXfermode::kSrcOver_Mode);
delegated_renderer_layer_impl->SetFrameDataForRenderPasses(
diff --git a/chromium/cc/layers/draw_properties.cc b/chromium/cc/layers/draw_properties.cc
new file mode 100644
index 00000000000..7fd380a4b7b
--- /dev/null
+++ b/chromium/cc/layers/draw_properties.cc
@@ -0,0 +1,23 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/layers/draw_properties.h"
+
+namespace cc {
+
+DrawProperties::DrawProperties()
+ : opacity(0.f),
+ screen_space_transform_is_animating(false),
+ can_use_lcd_text(false),
+ is_clipped(false),
+ render_target(nullptr),
+ num_unclipped_descendants(0),
+ has_child_with_a_scroll_parent(false),
+ last_drawn_render_surface_layer_list_id(0),
+ maximum_animation_contents_scale(0.f),
+ starting_animation_contents_scale(0.f) {}
+
+DrawProperties::~DrawProperties() {}
+
+} // namespace cc
diff --git a/chromium/cc/layers/draw_properties.h b/chromium/cc/layers/draw_properties.h
index 5a07af04e32..bcab91036be 100644
--- a/chromium/cc/layers/draw_properties.h
+++ b/chromium/cc/layers/draw_properties.h
@@ -12,32 +12,13 @@
#include "ui/gfx/transform.h"
namespace cc {
+class LayerImpl;
// Container for properties that layers need to compute before they can be
// drawn.
-template <typename LayerType>
struct CC_EXPORT DrawProperties {
- DrawProperties()
- : opacity(0.f),
- blend_mode(SkXfermode::kSrcOver_Mode),
- opacity_is_animating(false),
- screen_space_opacity_is_animating(false),
- target_space_transform_is_animating(false),
- screen_space_transform_is_animating(false),
- can_use_lcd_text(false),
- is_clipped(false),
- render_target(nullptr),
- num_unclipped_descendants(0),
- layer_or_descendant_has_copy_request(false),
- layer_or_descendant_has_input_handler(false),
- has_child_with_a_scroll_parent(false),
- index_of_first_descendants_addition(0),
- num_descendants_added(0),
- index_of_first_render_surface_layer_list_addition(0),
- num_render_surfaces_added(0),
- last_drawn_render_surface_layer_list_id(0),
- maximum_animation_contents_scale(0.f),
- starting_animation_contents_scale(0.f) {}
+ DrawProperties();
+ ~DrawProperties();
// Transforms objects from content space to target surface space, where
// this layer would be drawn.
@@ -49,22 +30,15 @@ struct CC_EXPORT DrawProperties {
// Known occlusion above the layer mapped to the content space of the layer.
Occlusion occlusion_in_content_space;
- // DrawProperties::opacity may be different than LayerType::opacity,
+ // DrawProperties::opacity may be different than LayerImpl::opacity,
// particularly in the case when a RenderSurface re-parents the layer's
// opacity, or when opacity is compounded by the hierarchy.
float opacity;
- // DrawProperties::blend_mode may be different than LayerType::blend_mode,
- // when a RenderSurface re-parents the layer's blend_mode.
- SkXfermode::Mode blend_mode;
-
// xxx_is_animating flags are used to indicate whether the DrawProperties
// are actually meaningful on the main thread. When the properties are
// animating, the main thread may not have the same values that are used
// to draw.
- bool opacity_is_animating;
- bool screen_space_opacity_is_animating;
- bool target_space_transform_is_animating;
bool screen_space_transform_is_animating;
// True if the layer can use LCD text.
@@ -76,7 +50,7 @@ struct CC_EXPORT DrawProperties {
// The layer whose coordinate space this layer draws into. This can be
// either the same layer (draw_properties_.render_target == this) or an
// ancestor of this layer.
- LayerType* render_target;
+ LayerImpl* render_target;
// This rect is a bounding box around what part of the layer is visible, in
// the layer's coordinate space.
@@ -94,27 +68,12 @@ struct CC_EXPORT DrawProperties {
// does not include our clip children because they are clipped by us.
size_t num_unclipped_descendants;
- // If true, the layer or some layer in its sub-tree has a CopyOutputRequest
- // present on it.
- bool layer_or_descendant_has_copy_request;
-
- // If true, the layer or one of its descendants has a wheel or touch handler.
- bool layer_or_descendant_has_input_handler;
-
// This is true if the layer has any direct child that has a scroll parent.
// This layer will not be the scroll parent in this case. This information
// lets us avoid work in CalculateDrawPropertiesInternal -- if none of our
// children have scroll parents, we will not need to recur out of order.
bool has_child_with_a_scroll_parent;
- // If this layer is visited out of order, its contribution to the descendant
- // and render surface layer lists will be put aside in a temporary list.
- // These values will allow for an efficient reordering of these additions.
- size_t index_of_first_descendants_addition;
- size_t num_descendants_added;
- size_t index_of_first_render_surface_layer_list_addition;
- size_t num_render_surfaces_added;
-
// Each time we generate a new render surface layer list, an ID is used to
// identify it. |last_drawn_render_surface_layer_list_id| is set to the ID
// that marked the render surface layer list generation which last updated
diff --git a/chromium/cc/layers/heads_up_display_layer_impl.cc b/chromium/cc/layers/heads_up_display_layer_impl.cc
index dffa6d18d65..1f765091381 100644
--- a/chromium/cc/layers/heads_up_display_layer_impl.cc
+++ b/chromium/cc/layers/heads_up_display_layer_impl.cc
@@ -13,7 +13,6 @@
#include "base/trace_event/trace_event_argument.h"
#include "cc/debug/debug_colors.h"
#include "cc/debug/frame_rate_counter.h"
-#include "cc/debug/paint_time_counter.h"
#include "cc/output/begin_frame_args.h"
#include "cc/output/renderer.h"
#include "cc/quads/texture_draw_quad.h"
@@ -22,6 +21,7 @@
#include "cc/trees/layer_tree_impl.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/skia/include/core/SkPaint.h"
+#include "third_party/skia/include/core/SkPath.h"
#include "third_party/skia/include/core/SkTypeface.h"
#include "third_party/skia/include/effects/SkColorMatrixFilter.h"
#include "ui/gfx/geometry/point.h"
@@ -132,7 +132,7 @@ bool HeadsUpDisplayLayerImpl::WillDraw(DrawMode draw_mode,
internal_contents_scale_ = GetIdealContentsScale();
internal_content_bounds_ =
- gfx::ToCeiledSize(gfx::ScaleSize(bounds(), internal_contents_scale_));
+ gfx::ScaleToCeiledSize(bounds(), internal_contents_scale_);
ReleaseUnmatchedSizeResources(resource_provider);
AcquireResource(resource_provider);
@@ -244,20 +244,6 @@ void HeadsUpDisplayLayerImpl::UpdateHudContents() {
fps_counter->GetMinAndMaxFPS(&fps_graph_.min, &fps_graph_.max);
}
- if (debug_state.continuous_painting) {
- PaintTimeCounter* paint_time_counter =
- layer_tree_impl()->paint_time_counter();
- base::TimeDelta latest, min, max;
-
- if (paint_time_counter->End())
- latest = **paint_time_counter->End();
- paint_time_counter->GetMinAndMaxPaintTime(&min, &max);
-
- paint_time_graph_.value = latest.InMillisecondsF();
- paint_time_graph_.min = min.InMillisecondsF();
- paint_time_graph_.max = max.InMillisecondsF();
- }
-
if (debug_state.ShowMemoryStats()) {
MemoryHistory* memory_history = layer_tree_impl()->memory_history();
if (memory_history->End())
@@ -281,21 +267,13 @@ void HeadsUpDisplayLayerImpl::DrawHudContents(SkCanvas* canvas) {
}
}
- SkRect area = SkRect::MakeEmpty();
- if (debug_state.continuous_painting) {
- area = DrawPaintTimeDisplay(
- canvas, layer_tree_impl()->paint_time_counter(), 0, 0);
- } else if (debug_state.show_fps_counter) {
- // Don't show the FPS display when continuous painting is enabled, because
- // it would show misleading numbers.
- area =
- DrawFPSDisplay(canvas, layer_tree_impl()->frame_rate_counter(), 0, 0);
- }
+ if (!debug_state.show_fps_counter)
+ return;
- if (debug_state.show_fps_counter || debug_state.continuous_painting) {
- area = DrawGpuRasterizationStatus(canvas, 0, area.bottom(),
- SkMaxScalar(area.width(), 150));
- }
+ SkRect area =
+ DrawFPSDisplay(canvas, layer_tree_impl()->frame_rate_counter(), 0, 0);
+ area = DrawGpuRasterizationStatus(canvas, 0, area.bottom(),
+ SkMaxScalar(area.width(), 150));
if (debug_state.ShowMemoryStats())
DrawMemoryDisplay(canvas, 0, area.bottom(), SkMaxScalar(area.width(), 150));
@@ -620,92 +598,6 @@ SkRect HeadsUpDisplayLayerImpl::DrawGpuRasterizationStatus(SkCanvas* canvas,
return area;
}
-SkRect HeadsUpDisplayLayerImpl::DrawPaintTimeDisplay(
- SkCanvas* canvas,
- const PaintTimeCounter* paint_time_counter,
- int right,
- int top) const {
- const int kPadding = 4;
- const int kFontHeight = 14;
-
- const int kGraphWidth =
- base::saturated_cast<int>(paint_time_counter->HistorySize());
- const int kGraphHeight = 40;
-
- SkPaint paint = CreatePaint();
-
- const std::string title = "Compositor frame time (ms)";
- int title_text_width = MeasureText(&paint, title, kFontHeight);
- int contents_width = std::max(title_text_width, kGraphWidth);
-
- const int width = contents_width + 2 * kPadding;
- const int height =
- kFontHeight + kGraphHeight + 4 * kPadding + 2 + kFontHeight + kPadding;
- const int left = bounds().width() - width - right;
-
- const SkRect area = SkRect::MakeXYWH(left, top, width, height);
-
- DrawGraphBackground(canvas, &paint, area);
-
- SkRect text_bounds = SkRect::MakeXYWH(left + kPadding, top + kPadding,
- contents_width, kFontHeight);
- SkRect text_bounds2 =
- SkRect::MakeXYWH(left + kPadding, text_bounds.bottom() + kPadding,
- contents_width, kFontHeight);
- SkRect graph_bounds = SkRect::MakeXYWH(left + (width - kGraphWidth) / 2,
- text_bounds2.bottom() + 2 * kPadding,
- kGraphWidth, kGraphHeight);
-
- const std::string value_text =
- base::StringPrintf("%.1f", paint_time_graph_.value);
- const std::string min_max_text = base::StringPrintf(
- "%.1f-%.1f", paint_time_graph_.min, paint_time_graph_.max);
-
- paint.setColor(DebugColors::PaintTimeDisplayTextAndGraphColor());
- DrawText(canvas, &paint, title, SkPaint::kLeft_Align, kFontHeight,
- text_bounds.left(), text_bounds.bottom());
- DrawText(canvas,
- &paint,
- value_text,
- SkPaint::kLeft_Align,
- kFontHeight,
- text_bounds2.left(),
- text_bounds2.bottom());
- DrawText(canvas,
- &paint,
- min_max_text,
- SkPaint::kRight_Align,
- kFontHeight,
- text_bounds2.right(),
- text_bounds2.bottom());
-
- paint.setColor(DebugColors::PaintTimeDisplayTextAndGraphColor());
- for (PaintTimeCounter::RingBufferType::Iterator it =
- paint_time_counter->End();
- it;
- --it) {
- double pt = it->InMillisecondsF();
-
- if (pt == 0.0)
- continue;
-
- double p = pt / paint_time_graph_.current_upper_bound;
- if (p > 1.0)
- p = 1.0;
-
- canvas->drawRect(
- SkRect::MakeXYWH(graph_bounds.left() + it.index(),
- graph_bounds.bottom() - p * graph_bounds.height(),
- 1,
- p * graph_bounds.height()),
- paint);
- }
-
- DrawGraphLines(canvas, &paint, graph_bounds, paint_time_graph_);
-
- return area;
-}
-
void HeadsUpDisplayLayerImpl::DrawDebugRect(
SkCanvas* canvas,
SkPaint* paint,
diff --git a/chromium/cc/layers/heads_up_display_layer_impl.h b/chromium/cc/layers/heads_up_display_layer_impl.h
index 299d91eb19d..0663b825417 100644
--- a/chromium/cc/layers/heads_up_display_layer_impl.h
+++ b/chromium/cc/layers/heads_up_display_layer_impl.h
@@ -111,10 +111,6 @@ class CC_EXPORT HeadsUpDisplayLayerImpl : public LayerImpl {
int right,
int top,
int width) const;
- SkRect DrawPaintTimeDisplay(SkCanvas* canvas,
- const PaintTimeCounter* paint_time_counter,
- int top,
- int right) const;
void DrawDebugRect(SkCanvas* canvas,
SkPaint* paint,
const DebugRect& rect,
diff --git a/chromium/cc/layers/heads_up_display_layer_impl_unittest.cc b/chromium/cc/layers/heads_up_display_layer_impl_unittest.cc
index ad2215595aa..ef377838571 100644
--- a/chromium/cc/layers/heads_up_display_layer_impl_unittest.cc
+++ b/chromium/cc/layers/heads_up_display_layer_impl_unittest.cc
@@ -34,10 +34,11 @@ TEST(HeadsUpDisplayLayerImplTest, ResourcelessSoftwareDrawAfterResourceLoss) {
FakeImplProxy proxy;
TestSharedBitmapManager shared_bitmap_manager;
TestTaskGraphRunner task_graph_runner;
+ scoped_ptr<OutputSurface> output_surface = FakeOutputSurface::Create3d();
FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager,
&task_graph_runner);
host_impl.CreatePendingTree();
- host_impl.InitializeRenderer(FakeOutputSurface::Create3d());
+ host_impl.InitializeRenderer(output_surface.get());
scoped_ptr<HeadsUpDisplayLayerImpl> layer =
HeadsUpDisplayLayerImpl::Create(host_impl.pending_tree(), 1);
layer->SetBounds(gfx::Size(100, 100));
diff --git a/chromium/cc/layers/io_surface_layer_impl.cc b/chromium/cc/layers/io_surface_layer_impl.cc
index 234d3f3a767..902a73d65b0 100644
--- a/chromium/cc/layers/io_surface_layer_impl.cc
+++ b/chromium/cc/layers/io_surface_layer_impl.cc
@@ -85,7 +85,8 @@ void IOSurfaceLayerImpl::AppendQuads(
visible_quad_rect,
io_surface_size_,
io_surface_resource_id_,
- IOSurfaceDrawQuad::FLIPPED);
+ IOSurfaceDrawQuad::FLIPPED,
+ false);
ValidateQuadResources(quad);
}
diff --git a/chromium/cc/layers/layer.cc b/chromium/cc/layers/layer.cc
index b9867d6217c..4b9162ff5ce 100644
--- a/chromium/cc/layers/layer.cc
+++ b/chromium/cc/layers/layer.cc
@@ -24,6 +24,7 @@
#include "cc/layers/scrollbar_layer_interface.h"
#include "cc/output/copy_output_request.h"
#include "cc/output/copy_output_result.h"
+#include "cc/trees/draw_property_utils.h"
#include "cc/trees/layer_tree_host.h"
#include "cc/trees/layer_tree_impl.h"
#include "third_party/skia/include/core/SkImageFilter.h"
@@ -51,12 +52,10 @@ Layer::Layer(const LayerSettings& settings)
scroll_clip_layer_id_(INVALID_ID),
num_descendants_that_draw_content_(0),
transform_tree_index_(-1),
- opacity_tree_index_(-1),
+ effect_tree_index_(-1),
clip_tree_index_(-1),
property_tree_sequence_number_(-1),
num_layer_or_descendants_with_copy_request_(0),
- num_layer_or_descendants_with_input_handler_(0),
- num_children_with_scroll_parent_(0),
should_flatten_transform_from_property_tree_(false),
should_scroll_on_main_thread_(false),
have_wheel_event_handlers_(false),
@@ -73,7 +72,6 @@ Layer::Layer(const LayerSettings& settings)
double_sided_(true),
should_flatten_transform_(true),
use_parent_backface_visibility_(false),
- draw_checkerboard_for_missing_tiles_(false),
force_render_surface_(false),
transform_is_invertible_(true),
has_render_surface_(false),
@@ -81,6 +79,7 @@ Layer::Layer(const LayerSettings& settings)
background_color_(0),
opacity_(1.f),
blend_mode_(SkXfermode::kSrcOver_Mode),
+ draw_blend_mode_(SkXfermode::kSrcOver_Mode),
scroll_parent_(nullptr),
layer_or_descendant_is_drawn_tracker_(0),
sorted_for_recursion_tracker_(0),
@@ -88,6 +87,7 @@ Layer::Layer(const LayerSettings& settings)
clip_parent_(nullptr),
replica_layer_(nullptr),
client_(nullptr),
+ num_unclipped_descendants_(0),
frame_timing_requests_dirty_(false) {
if (!settings.use_compositor_animation_timelines) {
layer_animation_controller_ = LayerAnimationController::Create(layer_id_);
@@ -259,7 +259,15 @@ void Layer::SetParent(Layer* layer) {
layer->AddDependentNeedsPushProperties();
}
+ if (parent_) {
+ parent_->UpdateNumCopyRequestsForSubtree(
+ -num_layer_or_descendants_with_copy_request_);
+ }
parent_ = layer;
+ if (parent_) {
+ parent_->UpdateNumCopyRequestsForSubtree(
+ num_layer_or_descendants_with_copy_request_);
+ }
SetLayerTreeHost(parent_ ? parent_->layer_tree_host() : nullptr);
if (!layer_tree_host_)
@@ -356,7 +364,7 @@ void Layer::SetBounds(const gfx::Size& size) {
if (ClipNode* clip_node = layer_tree_host_->property_trees()->clip_tree.Node(
clip_tree_index())) {
if (clip_node->owner_id == id()) {
- clip_node->data.clip.set_size(size);
+ clip_node->data.clip.set_size(gfx::SizeF(size));
layer_tree_host_->property_trees()->clip_tree.set_needs_update(true);
}
}
@@ -413,18 +421,17 @@ void Layer::RequestCopyOfOutput(
return;
copy_requests_.push_back(request.Pass());
if (had_no_copy_requests) {
- bool copy_request_added = true;
- UpdateNumCopyRequestsForSubtree(copy_request_added);
+ UpdateNumCopyRequestsForSubtree(1);
}
SetNeedsCommit();
}
-void Layer::UpdateNumCopyRequestsForSubtree(bool add) {
- int change = add ? 1 : -1;
+void Layer::UpdateNumCopyRequestsForSubtree(int delta) {
+ if (!delta)
+ return;
for (Layer* layer = this; layer; layer = layer->parent()) {
- layer->num_layer_or_descendants_with_copy_request_ += change;
- layer->draw_properties().layer_or_descendant_has_copy_request =
- (layer->num_layer_or_descendants_with_copy_request_ != 0);
+ layer->num_layer_or_descendants_with_copy_request_ += delta;
+ layer->SetNeedsPushProperties();
DCHECK_GE(layer->num_layer_or_descendants_with_copy_request_, 0);
}
}
@@ -510,11 +517,20 @@ void Layer::SetFilters(const FilterOperations& filters) {
bool Layer::FilterIsAnimating() const {
DCHECK(layer_tree_host_);
return layer_animation_controller_
- ? layer_animation_controller_->IsAnimatingProperty(
- Animation::FILTER)
+ ? layer_animation_controller_->IsCurrentlyAnimatingProperty(
+ Animation::FILTER,
+ LayerAnimationController::ObserverType::ACTIVE)
: layer_tree_host_->IsAnimatingFilterProperty(this);
}
+bool Layer::HasPotentiallyRunningFilterAnimation() const {
+ if (layer_animation_controller_) {
+ return layer_animation_controller_->IsPotentiallyAnimatingProperty(
+ Animation::FILTER, LayerAnimationController::ObserverType::ACTIVE);
+ }
+ return layer_tree_host_->HasPotentiallyRunningFilterAnimation(this);
+}
+
void Layer::SetBackgroundFilters(const FilterOperations& filters) {
DCHECK(IsPropertyChangeAllowed());
if (background_filters_ == filters)
@@ -534,22 +550,18 @@ void Layer::SetOpacity(float opacity) {
bool Layer::OpacityIsAnimating() const {
DCHECK(layer_tree_host_);
return layer_animation_controller_
- ? layer_animation_controller_->IsAnimatingProperty(
- Animation::OPACITY)
+ ? layer_animation_controller_->IsCurrentlyAnimatingProperty(
+ Animation::OPACITY,
+ LayerAnimationController::ObserverType::ACTIVE)
: layer_tree_host_->IsAnimatingOpacityProperty(this);
}
bool Layer::HasPotentiallyRunningOpacityAnimation() const {
if (layer_animation_controller_) {
- if (Animation* animation =
- layer_animation_controller()->GetAnimation(Animation::OPACITY)) {
- return !animation->is_finished();
- }
- return false;
- } else {
- DCHECK(layer_tree_host_);
- return layer_tree_host_->HasPotentiallyRunningOpacityAnimation(this);
+ return layer_animation_controller_->IsPotentiallyAnimatingProperty(
+ Animation::OPACITY, LayerAnimationController::ObserverType::ACTIVE);
}
+ return layer_tree_host_->HasPotentiallyRunningOpacityAnimation(this);
}
bool Layer::OpacityCanAnimateOnImplThread() const {
@@ -742,22 +754,50 @@ bool Layer::AnimationsPreserveAxisAlignment() const {
bool Layer::TransformIsAnimating() const {
DCHECK(layer_tree_host_);
return layer_animation_controller_
- ? layer_animation_controller_->IsAnimatingProperty(
- Animation::TRANSFORM)
+ ? layer_animation_controller_->IsCurrentlyAnimatingProperty(
+ Animation::TRANSFORM,
+ LayerAnimationController::ObserverType::ACTIVE)
: layer_tree_host_->IsAnimatingTransformProperty(this);
}
bool Layer::HasPotentiallyRunningTransformAnimation() const {
if (layer_animation_controller_) {
- if (Animation* animation =
- layer_animation_controller()->GetAnimation(Animation::TRANSFORM)) {
- return !animation->is_finished();
- }
- return false;
- } else {
- DCHECK(layer_tree_host_);
- return layer_tree_host_->HasPotentiallyRunningTransformAnimation(this);
+ return layer_animation_controller_->IsPotentiallyAnimatingProperty(
+ Animation::TRANSFORM, LayerAnimationController::ObserverType::ACTIVE);
+ }
+ return layer_tree_host_->HasPotentiallyRunningTransformAnimation(this);
+}
+
+bool Layer::HasOnlyTranslationTransforms() const {
+ if (layer_animation_controller_) {
+ return layer_animation_controller_->HasOnlyTranslationTransforms(
+ LayerAnimationController::ObserverType::ACTIVE);
}
+ return layer_tree_host_->HasOnlyTranslationTransforms(this);
+}
+
+bool Layer::MaximumTargetScale(float* max_scale) const {
+ if (layer_animation_controller_) {
+ return layer_animation_controller_->MaximumTargetScale(
+ LayerAnimationController::ObserverType::ACTIVE, max_scale);
+ }
+ return layer_tree_host_->MaximumTargetScale(this, max_scale);
+}
+
+bool Layer::AnimationStartScale(float* start_scale) const {
+ if (layer_animation_controller_) {
+ return layer_animation_controller_->AnimationStartScale(
+ LayerAnimationController::ObserverType::ACTIVE, start_scale);
+ }
+ return layer_tree_host_->AnimationStartScale(this, start_scale);
+}
+
+bool Layer::HasAnyAnimationTargetingProperty(
+ Animation::TargetProperty property) const {
+ if (layer_animation_controller_)
+ return !!layer_animation_controller_->GetAnimation(property);
+
+ return layer_tree_host_->HasAnyAnimationTargetingProperty(this, property);
}
bool Layer::ScrollOffsetAnimationWasInterrupted() const {
@@ -788,10 +828,6 @@ void Layer::AddScrollChild(Layer* child) {
if (!scroll_children_)
scroll_children_.reset(new std::set<Layer*>);
scroll_children_->insert(child);
- if (layer_tree_host_ && !layer_tree_host_->needs_meta_info_recomputation()) {
- num_children_with_scroll_parent_++;
- draw_properties().has_child_with_a_scroll_parent = true;
- }
SetNeedsCommit();
}
@@ -799,12 +835,6 @@ void Layer::RemoveScrollChild(Layer* child) {
scroll_children_->erase(child);
if (scroll_children_->empty())
scroll_children_ = nullptr;
- if (layer_tree_host_ && !layer_tree_host_->needs_meta_info_recomputation()) {
- num_children_with_scroll_parent_--;
- DCHECK_GE(num_children_with_scroll_parent_, 0);
- draw_properties().has_child_with_a_scroll_parent =
- (num_children_with_scroll_parent_ != 0);
- }
SetNeedsCommit();
}
@@ -939,24 +969,11 @@ void Layer::SetHaveWheelEventHandlers(bool have_wheel_event_handlers) {
DCHECK(IsPropertyChangeAllowed());
if (have_wheel_event_handlers_ == have_wheel_event_handlers)
return;
- if (touch_event_handler_region_.IsEmpty() && layer_tree_host_ &&
- !layer_tree_host_->needs_meta_info_recomputation())
- UpdateNumInputHandlersForSubtree(have_wheel_event_handlers);
have_wheel_event_handlers_ = have_wheel_event_handlers;
SetNeedsCommit();
}
-void Layer::UpdateNumInputHandlersForSubtree(bool add) {
- int change = add ? 1 : -1;
- for (Layer* layer = this; layer; layer = layer->parent()) {
- layer->num_layer_or_descendants_with_input_handler_ += change;
- layer->draw_properties().layer_or_descendant_has_input_handler =
- (layer->num_layer_or_descendants_with_input_handler_ != 0);
- DCHECK_GE(layer->num_layer_or_descendants_with_input_handler_, 0);
- }
-}
-
void Layer::SetHaveScrollEventHandlers(bool have_scroll_event_handlers) {
DCHECK(IsPropertyChangeAllowed());
if (have_scroll_event_handlers_ == have_scroll_event_handlers)
@@ -977,9 +994,6 @@ void Layer::SetTouchEventHandlerRegion(const Region& region) {
DCHECK(IsPropertyChangeAllowed());
if (touch_event_handler_region_ == region)
return;
- if (!have_wheel_event_handlers_ && layer_tree_host_ &&
- !layer_tree_host_->needs_meta_info_recomputation())
- UpdateNumInputHandlersForSubtree(!region.IsEmpty());
touch_event_handler_region_ = region;
SetNeedsCommit();
@@ -993,14 +1007,6 @@ void Layer::SetScrollBlocksOn(ScrollBlocksOn scroll_blocks_on) {
SetNeedsCommit();
}
-void Layer::SetDrawCheckerboardForMissingTiles(bool checkerboard) {
- DCHECK(IsPropertyChangeAllowed());
- if (draw_checkerboard_for_missing_tiles_ == checkerboard)
- return;
- draw_checkerboard_for_missing_tiles_ = checkerboard;
- SetNeedsCommit();
-}
-
void Layer::SetForceRenderSurface(bool force) {
DCHECK(IsPropertyChangeAllowed());
if (force_render_surface_ == force)
@@ -1059,28 +1065,28 @@ int Layer::clip_tree_index() const {
return clip_tree_index_;
}
-void Layer::SetOpacityTreeIndex(int index) {
+void Layer::SetEffectTreeIndex(int index) {
DCHECK(IsPropertyChangeAllowed());
- if (opacity_tree_index_ == index)
+ if (effect_tree_index_ == index)
return;
- opacity_tree_index_ = index;
+ effect_tree_index_ = index;
SetNeedsPushProperties();
}
-int Layer::opacity_tree_index() const {
+int Layer::effect_tree_index() const {
if (!layer_tree_host_ ||
layer_tree_host_->property_trees()->sequence_number !=
property_tree_sequence_number_) {
return -1;
}
- return opacity_tree_index_;
+ return effect_tree_index_;
}
void Layer::InvalidatePropertyTreesIndices() {
int invalid_property_tree_index = -1;
SetTransformTreeIndex(invalid_property_tree_index);
SetClipTreeIndex(invalid_property_tree_index);
- SetOpacityTreeIndex(invalid_property_tree_index);
+ SetEffectTreeIndex(invalid_property_tree_index);
}
void Layer::SetShouldFlattenTransform(bool should_flatten) {
@@ -1182,12 +1188,10 @@ void Layer::PushPropertiesTo(LayerImpl* layer) {
layer->SetDebugInfo(TakeDebugInfo());
layer->SetTransformTreeIndex(transform_tree_index());
- layer->SetOpacityTreeIndex(opacity_tree_index());
+ layer->SetEffectTreeIndex(effect_tree_index());
layer->SetClipTreeIndex(clip_tree_index());
layer->set_offset_to_transform_parent(offset_to_transform_parent_);
layer->SetDoubleSided(double_sided_);
- layer->SetDrawCheckerboardForMissingTiles(
- draw_checkerboard_for_missing_tiles_);
layer->SetDrawsContent(DrawsContent());
layer->SetHideLayerAndSubtree(hide_layer_and_subtree_);
layer->SetHasRenderSurface(has_render_surface_);
@@ -1215,6 +1219,9 @@ void Layer::PushPropertiesTo(LayerImpl* layer) {
layer->SetShouldFlattenTransform(should_flatten_transform_);
layer->set_should_flatten_transform_from_property_tree(
should_flatten_transform_from_property_tree_);
+ layer->set_num_layer_or_descendant_with_copy_request(
+ num_layer_or_descendants_with_copy_request_);
+ layer->set_draw_blend_mode(draw_blend_mode_);
layer->SetUseParentBackfaceVisibility(use_parent_backface_visibility_);
if (!layer->TransformIsAnimatingOnImplOnly() && !TransformIsAnimating())
layer->SetTransformAndInvertibility(transform_, transform_is_invertible_);
@@ -1302,7 +1309,8 @@ void Layer::PushPropertiesTo(LayerImpl* layer) {
if (!copy_requests_.empty() && layer_tree_host_)
layer_tree_host_->property_trees()->needs_rebuild = true;
if (had_copy_requests)
- UpdateNumCopyRequestsForSubtree(false);
+ UpdateNumCopyRequestsForSubtree(-1);
+
copy_requests_.clear();
layer->PassCopyRequests(&main_thread_copy_requests);
@@ -1393,10 +1401,6 @@ bool Layer::Update() {
return false;
}
-bool Layer::NeedMoreUpdates() {
- return false;
-}
-
bool Layer::IsSuitableForGpuRasterization() const {
return true;
}
@@ -1416,20 +1420,7 @@ void Layer::SetHasRenderSurface(bool has_render_surface) {
// We do not need SetNeedsCommit here, since this is only ever called
// during a commit, from CalculateDrawProperties.
SetNeedsPushProperties();
-}
-
-void Layer::CreateRenderSurface() {
- DCHECK(!render_surface_);
- render_surface_ = make_scoped_ptr(new RenderSurface(this));
-}
-
-void Layer::ClearRenderSurface() {
- render_surface_ = nullptr;
-}
-
-void Layer::ClearRenderSurfaceLayerList() {
- if (render_surface_)
- render_surface_->ClearLayerLists();
+ layer_tree_host_->property_trees()->needs_rebuild = true;
}
gfx::ScrollOffset Layer::ScrollOffsetForAnimation() const {
@@ -1447,12 +1438,11 @@ void Layer::OnFilterAnimated(const FilterOperations& filters) {
void Layer::OnOpacityAnimated(float opacity) {
opacity_ = opacity;
if (layer_tree_host_) {
- if (OpacityNode* node =
- layer_tree_host_->property_trees()->opacity_tree.Node(
- opacity_tree_index())) {
+ if (EffectNode* node = layer_tree_host_->property_trees()->effect_tree.Node(
+ effect_tree_index())) {
if (node->owner_id == id()) {
node->data.opacity = opacity;
- layer_tree_host_->property_trees()->opacity_tree.set_needs_update(true);
+ layer_tree_host_->property_trees()->effect_tree.set_needs_update(true);
}
}
}
@@ -1489,6 +1479,40 @@ void Layer::OnAnimationWaitingForDeletion() {
SetNeedsPushProperties();
}
+void Layer::OnTransformIsPotentiallyAnimatingChanged(bool is_animating) {
+ if (!layer_tree_host_)
+ return;
+ TransformTree& transform_tree =
+ layer_tree_host_->property_trees()->transform_tree;
+ TransformNode* node = transform_tree.Node(transform_tree_index());
+ if (!node)
+ return;
+
+ if (node->owner_id == id()) {
+ node->data.is_animated = is_animating;
+ if (is_animating) {
+ float maximum_target_scale = 0.f;
+ node->data.local_maximum_animation_target_scale =
+ MaximumTargetScale(&maximum_target_scale) ? maximum_target_scale
+ : 0.f;
+
+ float animation_start_scale = 0.f;
+ node->data.local_starting_animation_scale =
+ AnimationStartScale(&animation_start_scale) ? animation_start_scale
+ : 0.f;
+
+ node->data.has_only_translation_animations =
+ HasOnlyTranslationTransforms();
+
+ } else {
+ node->data.local_maximum_animation_target_scale = 0.f;
+ node->data.local_starting_animation_scale = 0.f;
+ node->data.has_only_translation_animations = true;
+ }
+ transform_tree.set_needs_update(true);
+ }
+}
+
bool Layer::IsActive() const {
return true;
}
@@ -1665,4 +1689,16 @@ bool Layer::sorted_for_recursion() {
layer_tree_host()->meta_information_sequence_number();
}
+gfx::Transform Layer::draw_transform() const {
+ DCHECK_NE(transform_tree_index_, -1);
+ return DrawTransformFromPropertyTrees(
+ this, layer_tree_host_->property_trees()->transform_tree);
+}
+
+gfx::Transform Layer::screen_space_transform() const {
+ DCHECK_NE(transform_tree_index_, -1);
+ return ScreenSpaceTransformFromPropertyTrees(
+ this, layer_tree_host_->property_trees()->transform_tree);
+}
+
} // namespace cc
diff --git a/chromium/cc/layers/layer.h b/chromium/cc/layers/layer.h
index 3ff2810c9d6..800deff5ce2 100644
--- a/chromium/cc/layers/layer.h
+++ b/chromium/cc/layers/layer.h
@@ -20,11 +20,9 @@
#include "cc/base/scoped_ptr_vector.h"
#include "cc/debug/frame_timing_request.h"
#include "cc/debug/micro_benchmark.h"
-#include "cc/layers/draw_properties.h"
#include "cc/layers/layer_lists.h"
#include "cc/layers/layer_position_constraint.h"
#include "cc/layers/paint_properties.h"
-#include "cc/layers/render_surface.h"
#include "cc/layers/scroll_blocks_on.h"
#include "cc/output/filter_operations.h"
#include "cc/trees/property_tree.h"
@@ -75,9 +73,7 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>,
public LayerAnimationValueObserver,
public LayerAnimationValueProvider {
public:
- typedef RenderSurfaceLayerList RenderSurfaceListType;
typedef LayerList LayerListType;
- typedef RenderSurface RenderSurfaceType;
enum LayerIdLabels {
INVALID_ID = -1,
@@ -141,6 +137,14 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>,
void SetBlendMode(SkXfermode::Mode blend_mode);
SkXfermode::Mode blend_mode() const { return blend_mode_; }
+ void set_draw_blend_mode(SkXfermode::Mode blend_mode) {
+ if (draw_blend_mode_ == blend_mode)
+ return;
+ draw_blend_mode_ = blend_mode;
+ SetNeedsPushProperties();
+ }
+ SkXfermode::Mode draw_blend_mode() const { return draw_blend_mode_; }
+
bool uses_default_blend_mode() const {
return blend_mode_ == SkXfermode::kSrcOver_Mode;
}
@@ -157,6 +161,7 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>,
void SetFilters(const FilterOperations& filters);
const FilterOperations& filters() const { return filters_; }
bool FilterIsAnimating() const;
+ bool HasPotentiallyRunningFilterAnimation() const;
// Background filters are filters applied to what is behind this layer, when
// they are viewed through non-opaque regions in this layer. They are used
@@ -190,12 +195,19 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>,
const gfx::Transform& transform() const { return transform_; }
bool TransformIsAnimating() const;
bool HasPotentiallyRunningTransformAnimation() const;
+ bool HasOnlyTranslationTransforms() const;
bool AnimationsPreserveAxisAlignment() const;
bool transform_is_invertible() const { return transform_is_invertible_; }
+ bool MaximumTargetScale(float* max_scale) const;
+ bool AnimationStartScale(float* start_scale) const;
+
void SetTransformOrigin(const gfx::Point3F&);
gfx::Point3F transform_origin() const { return transform_origin_; }
+ bool HasAnyAnimationTargetingProperty(
+ Animation::TargetProperty property) const;
+
bool ScrollOffsetAnimationWasInterrupted() const;
void SetScrollParent(Layer* parent);
@@ -226,55 +238,17 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>,
return clip_children_.get();
}
- DrawProperties<Layer>& draw_properties() { return draw_properties_; }
- const DrawProperties<Layer>& draw_properties() const {
- return draw_properties_;
- }
+ // TODO(enne): Fix style here (and everywhere) once LayerImpl does the same.
+ gfx::Transform draw_transform() const;
+ gfx::Transform screen_space_transform() const;
- // The following are shortcut accessors to get various information from
- // draw_properties_
- const gfx::Transform& draw_transform() const {
- return draw_properties_.target_space_transform;
- }
- const gfx::Transform& screen_space_transform() const {
- return draw_properties_.screen_space_transform;
- }
- float draw_opacity() const { return draw_properties_.opacity; }
- bool draw_opacity_is_animating() const {
- return draw_properties_.opacity_is_animating;
- }
- bool draw_transform_is_animating() const {
- return draw_properties_.target_space_transform_is_animating;
- }
- bool screen_space_transform_is_animating() const {
- return draw_properties_.screen_space_transform_is_animating;
- }
- bool screen_space_opacity_is_animating() const {
- return draw_properties_.screen_space_opacity_is_animating;
- }
- bool is_clipped() const { return draw_properties_.is_clipped; }
- gfx::Rect clip_rect() const { return draw_properties_.clip_rect; }
- gfx::Rect drawable_content_rect() const {
- return draw_properties_.drawable_content_rect;
- }
- gfx::Rect visible_layer_rect() const {
- return draw_properties_.visible_layer_rect;
- }
- Layer* render_target() {
- DCHECK(!draw_properties_.render_target ||
- draw_properties_.render_target->render_surface());
- return draw_properties_.render_target;
- }
- const Layer* render_target() const {
- DCHECK(!draw_properties_.render_target ||
- draw_properties_.render_target->render_surface());
- return draw_properties_.render_target;
+ void set_num_unclipped_descendants(size_t descendants) {
+ num_unclipped_descendants_ = descendants;
}
size_t num_unclipped_descendants() const {
- return draw_properties_.num_unclipped_descendants;
+ return num_unclipped_descendants_;
}
- RenderSurface* render_surface() const { return render_surface_.get(); }
void SetScrollOffset(const gfx::ScrollOffset& scroll_offset);
void SetScrollCompensationAdjustment(
const gfx::Vector2dF& scroll_compensation_adjustment);
@@ -322,11 +296,6 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>,
did_scroll_callback_ = callback;
}
- void SetDrawCheckerboardForMissingTiles(bool checkerboard);
- bool draw_checkerboard_for_missing_tiles() const {
- return draw_checkerboard_for_missing_tiles_;
- }
-
void SetForceRenderSurface(bool force_render_surface);
bool force_render_surface() const { return force_render_surface_; }
@@ -379,10 +348,7 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>,
virtual void SavePaintProperties();
// Returns true iff anything was updated that needs to be committed.
virtual bool Update();
- virtual bool NeedMoreUpdates();
virtual void SetIsMask(bool is_mask) {}
- virtual void ReduceMemoryUsage() {}
- virtual void OnOutputSurfaceCreated() {}
virtual bool IsSuitableForGpuRasterization() const;
virtual scoped_refptr<base::trace_event::ConvertableToTraceFormat>
@@ -392,11 +358,6 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>,
virtual void PushPropertiesTo(LayerImpl* layer);
- void CreateRenderSurface();
- void ClearRenderSurface();
-
- void ClearRenderSurfaceLayerList();
-
LayerTreeHost* layer_tree_host() { return layer_tree_host_; }
const LayerTreeHost* layer_tree_host() const { return layer_tree_host_; }
@@ -463,8 +424,8 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>,
void SetClipTreeIndex(int index);
int clip_tree_index() const;
- void SetOpacityTreeIndex(int index);
- int opacity_tree_index() const;
+ void SetEffectTreeIndex(int index);
+ int effect_tree_index() const;
void set_offset_to_transform_parent(gfx::Vector2dF offset) {
if (offset_to_transform_parent_ == offset)
@@ -476,20 +437,24 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>,
return offset_to_transform_parent_;
}
- // TODO(vollick): Once we transition to transform and clip trees, rename these
- // functions and related values. The "from property trees" functions below
- // use the transform and clip trees. Eventually, we will use these functions
- // to compute the official values, but these functions are retained for
- // testing purposes until we've migrated.
-
+ // TODO(enne): Once LayerImpl only uses property trees, remove these
+ // functions.
const gfx::Rect& visible_rect_from_property_trees() const {
- return visible_rect_from_property_trees_;
+ return visible_layer_rect();
}
void set_visible_rect_from_property_trees(const gfx::Rect& rect) {
- // No push properties here, as this acts like a draw property.
- visible_rect_from_property_trees_ = rect;
+ set_visible_layer_rect(rect);
}
-
+ const gfx::Rect& clip_rect_in_target_space_from_property_trees() const {
+ return clip_rect();
+ }
+ void set_clip_rect_in_target_space_from_property_trees(
+ const gfx::Rect& rect) {
+ set_clip_rect(rect);
+ }
+ // TODO(enne): This needs a different name. It is a calculated value
+ // from the property tree builder and not a synonym for "should
+ // flatten transform".
void set_should_flatten_transform_from_property_tree(bool should_flatten) {
if (should_flatten_transform_from_property_tree_ == should_flatten)
return;
@@ -500,13 +465,14 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>,
return should_flatten_transform_from_property_tree_;
}
- // TODO(vollick): These values are temporary and will be removed as soon as
- // render surface determinations are moved out of CDP. They only exist because
- // certain logic depends on whether or not a layer would render to a separate
- // surface, but CDP destroys surfaces and targets it doesn't need, so without
- // this boolean, this is impossible to determine after the fact without
- // wastefully recomputing it. This is public for the time being so that it can
- // be accessed from CDP.
+ const gfx::Rect& visible_layer_rect() const { return visible_layer_rect_; }
+ void set_visible_layer_rect(const gfx::Rect& rect) {
+ visible_layer_rect_ = rect;
+ }
+
+ const gfx::Rect& clip_rect() const { return clip_rect_; }
+ void set_clip_rect(const gfx::Rect& rect) { clip_rect_ = rect; }
+
bool has_render_surface() const {
return has_render_surface_;
}
@@ -520,29 +486,14 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>,
}
void DidBeginTracing();
- void set_num_layer_or_descandant_with_copy_request(
+ // TODO(weiliangc): this should move to the effect tree.
+ void set_num_layer_or_descendant_with_copy_request(
int num_layer_or_descendants_with_copy_request) {
num_layer_or_descendants_with_copy_request_ =
num_layer_or_descendants_with_copy_request;
}
-
- void set_num_layer_or_descandant_with_input_handler(
- int num_layer_or_descendants_with_input_handler) {
- num_layer_or_descendants_with_input_handler_ =
- num_layer_or_descendants_with_input_handler;
- }
-
- int num_layer_or_descendants_with_input_handler() {
- return num_layer_or_descendants_with_input_handler_;
- }
-
- void set_num_children_with_scroll_parent(
- int num_children_with_scroll_parent) {
- num_children_with_scroll_parent_ = num_children_with_scroll_parent;
- }
-
- int num_children_with_scroll_parent() {
- return num_children_with_scroll_parent_;
+ int num_layer_or_descendants_with_copy_request() {
+ return num_layer_or_descendants_with_copy_request_;
}
void set_visited(bool visited);
@@ -652,6 +603,7 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>,
void OnTransformAnimated(const gfx::Transform& transform) override;
void OnScrollOffsetAnimated(const gfx::ScrollOffset& scroll_offset) override;
void OnAnimationWaitingForDeletion() override;
+ void OnTransformIsPotentiallyAnimatingChanged(bool is_animating) override;
bool IsActive() const override;
// If this layer has a scroll parent, it removes |this| from its list of
@@ -666,8 +618,7 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>,
// indices becomes invalid.
void InvalidatePropertyTreesIndices();
- void UpdateNumCopyRequestsForSubtree(bool add);
- void UpdateNumInputHandlersForSubtree(bool add);
+ void UpdateNumCopyRequestsForSubtree(int delta);
LayerList children_;
Layer* parent_;
@@ -690,12 +641,10 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>,
int scroll_clip_layer_id_;
int num_descendants_that_draw_content_;
int transform_tree_index_;
- int opacity_tree_index_;
+ int effect_tree_index_;
int clip_tree_index_;
int property_tree_sequence_number_;
int num_layer_or_descendants_with_copy_request_;
- int num_layer_or_descendants_with_input_handler_;
- int num_children_with_scroll_parent_;
gfx::Vector2dF offset_to_transform_parent_;
bool should_flatten_transform_from_property_tree_ : 1;
bool should_scroll_on_main_thread_ : 1;
@@ -713,7 +662,6 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>,
bool double_sided_ : 1;
bool should_flatten_transform_ : 1;
bool use_parent_backface_visibility_ : 1;
- bool draw_checkerboard_for_missing_tiles_ : 1;
bool force_render_surface_ : 1;
bool transform_is_invertible_ : 1;
bool has_render_surface_ : 1;
@@ -724,6 +672,9 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>,
SkColor background_color_;
float opacity_;
SkXfermode::Mode blend_mode_;
+ // draw_blend_mode may be different than blend_mode_,
+ // when a RenderSurface re-parents the layer's blend_mode.
+ SkXfermode::Mode draw_blend_mode_;
FilterOperations filters_;
FilterOperations background_filters_;
LayerPositionConstraint position_constraint_;
@@ -753,14 +704,12 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>,
base::Closure did_scroll_callback_;
- DrawProperties<Layer> draw_properties_;
-
PaintProperties paint_properties_;
- // TODO(awoloszyn): This is redundant with has_render_surface_,
- // and should get removed once it is no longer needed on main thread.
- scoped_ptr<RenderSurface> render_surface_;
- gfx::Rect visible_rect_from_property_trees_;
+ // These all act like draw properties, so don't need push properties.
+ gfx::Rect visible_layer_rect_;
+ gfx::Rect clip_rect_;
+ size_t num_unclipped_descendants_;
std::vector<FrameTimingRequest> frame_timing_requests_;
bool frame_timing_requests_dirty_;
diff --git a/chromium/cc/layers/layer_impl.cc b/chromium/cc/layers/layer_impl.cc
index 588c8ac4d90..afacef86551 100644
--- a/chromium/cc/layers/layer_impl.cc
+++ b/chromium/cc/layers/layer_impl.cc
@@ -17,6 +17,7 @@
#include "cc/debug/layer_tree_debug_state.h"
#include "cc/debug/micro_benchmark_impl.h"
#include "cc/debug/traced_value.h"
+#include "cc/input/scroll_state.h"
#include "cc/layers/layer_utils.h"
#include "cc/layers/painted_scrollbar_layer_impl.h"
#include "cc/output/copy_output_request.h"
@@ -65,7 +66,6 @@ LayerImpl::LayerImpl(LayerTreeImpl* tree_impl,
contents_opaque_(false),
is_root_for_isolated_group_(false),
use_parent_backface_visibility_(false),
- draw_checkerboard_for_missing_tiles_(false),
draws_content_(false),
hide_layer_and_subtree_(false),
transform_is_invertible_(true),
@@ -74,18 +74,21 @@ LayerImpl::LayerImpl(LayerTreeImpl* tree_impl,
background_color_(0),
opacity_(1.0),
blend_mode_(SkXfermode::kSrcOver_Mode),
+ draw_blend_mode_(SkXfermode::kSrcOver_Mode),
num_descendants_that_draw_content_(0),
transform_tree_index_(-1),
- opacity_tree_index_(-1),
+ effect_tree_index_(-1),
clip_tree_index_(-1),
draw_depth_(0.f),
needs_push_properties_(false),
num_dependents_need_push_properties_(0),
sorting_context_id_(0),
current_draw_mode_(DRAW_MODE_NONE),
+ num_layer_or_descendants_with_copy_request_(0),
frame_timing_requests_dirty_(false),
visited_(false),
layer_or_descendant_is_drawn_(false),
+ layer_or_descendant_has_input_handler_(false),
sorted_for_recursion_(false) {
DCHECK_GT(layer_id_, 0);
DCHECK(layer_tree_impl_);
@@ -196,6 +199,30 @@ void LayerImpl::SetScrollChildren(std::set<LayerImpl*>* children) {
SetNeedsPushProperties();
}
+void LayerImpl::DistributeScroll(ScrollState* scroll_state) {
+ DCHECK(scroll_state);
+ if (scroll_state->FullyConsumed())
+ return;
+
+ scroll_state->DistributeToScrollChainDescendant();
+
+ // If the scroll doesn't propagate, and we're currently scrolling
+ // a layer other than this one, prevent the scroll from
+ // propagating to this layer.
+ if (!scroll_state->should_propagate() &&
+ scroll_state->delta_consumed_for_scroll_sequence() &&
+ scroll_state->current_native_scrolling_layer() != this) {
+ return;
+ }
+
+ ApplyScroll(scroll_state);
+}
+
+void LayerImpl::ApplyScroll(ScrollState* scroll_state) {
+ DCHECK(scroll_state);
+ layer_tree_impl()->ApplyScroll(this, scroll_state);
+}
+
void LayerImpl::SetNumDescendantsThatDrawContent(int num_descendants) {
if (num_descendants_that_draw_content_ == num_descendants)
return;
@@ -228,8 +255,8 @@ void LayerImpl::SetClipTreeIndex(int index) {
SetNeedsPushProperties();
}
-void LayerImpl::SetOpacityTreeIndex(int index) {
- opacity_tree_index_ = index;
+void LayerImpl::SetEffectTreeIndex(int index) {
+ effect_tree_index_ = index;
SetNeedsPushProperties();
}
@@ -291,7 +318,7 @@ void LayerImpl::PopulateSharedQuadState(SharedQuadState* state) const {
state->SetAll(draw_properties_.target_space_transform, bounds(),
draw_properties_.visible_layer_rect, draw_properties_.clip_rect,
draw_properties_.is_clipped, draw_properties_.opacity,
- draw_properties_.blend_mode, sorting_context_id_);
+ draw_blend_mode_, sorting_context_id_);
}
void LayerImpl::PopulateScaledSharedQuadState(SharedQuadState* state,
@@ -299,14 +326,14 @@ void LayerImpl::PopulateScaledSharedQuadState(SharedQuadState* state,
gfx::Transform scaled_draw_transform =
draw_properties_.target_space_transform;
scaled_draw_transform.Scale(SK_MScalar1 / scale, SK_MScalar1 / scale);
- gfx::Size scaled_bounds = gfx::ToCeiledSize(gfx::ScaleSize(bounds(), scale));
+ gfx::Size scaled_bounds = gfx::ScaleToCeiledSize(bounds(), scale);
gfx::Rect scaled_visible_layer_rect =
gfx::ScaleToEnclosingRect(visible_layer_rect(), scale);
scaled_visible_layer_rect.Intersect(gfx::Rect(scaled_bounds));
state->SetAll(scaled_draw_transform, scaled_bounds, scaled_visible_layer_rect,
draw_properties().clip_rect, draw_properties().is_clipped,
- draw_properties().opacity, draw_properties().blend_mode,
+ draw_properties().opacity, draw_blend_mode_,
sorting_context_id_);
}
@@ -521,8 +548,6 @@ void LayerImpl::PushPropertiesTo(LayerImpl* layer) {
layer->SetBackgroundColor(background_color_);
layer->SetBounds(bounds_);
layer->SetDoubleSided(double_sided_);
- layer->SetDrawCheckerboardForMissingTiles(
- draw_checkerboard_for_missing_tiles_);
layer->SetDrawsContent(DrawsContent());
layer->SetHideLayerAndSubtree(hide_layer_and_subtree_);
layer->SetHasRenderSurface(!!render_surface());
@@ -546,6 +571,7 @@ void LayerImpl::PushPropertiesTo(LayerImpl* layer) {
layer->SetShouldFlattenTransform(should_flatten_transform_);
layer->set_should_flatten_transform_from_property_tree(
should_flatten_transform_from_property_tree_);
+ layer->set_draw_blend_mode(draw_blend_mode_);
layer->SetUseParentBackfaceVisibility(use_parent_backface_visibility_);
layer->SetTransformAndInvertibility(transform_, transform_is_invertible_);
@@ -563,7 +589,7 @@ void LayerImpl::PushPropertiesTo(LayerImpl* layer) {
layer->SetTransformTreeIndex(transform_tree_index_);
layer->SetClipTreeIndex(clip_tree_index_);
- layer->SetOpacityTreeIndex(opacity_tree_index_);
+ layer->SetEffectTreeIndex(effect_tree_index_);
layer->set_offset_to_transform_parent(offset_to_transform_parent_);
LayerImpl* scroll_parent = nullptr;
@@ -618,6 +644,9 @@ void LayerImpl::PushPropertiesTo(LayerImpl* layer) {
layer->SetStackingOrderChanged(stacking_order_changed_);
layer->SetDebugInfo(debug_info_);
+ layer->set_num_layer_or_descendant_with_copy_request(
+ num_layer_or_descendants_with_copy_request_);
+ set_num_layer_or_descendant_with_copy_request(0);
if (frame_timing_requests_dirty_) {
layer->SetFrameTimingRequests(frame_timing_requests_);
@@ -752,8 +781,8 @@ const char* LayerImpl::LayerTypeAsString() const {
void LayerImpl::ResetAllChangeTrackingForSubtree() {
layer_property_changed_ = false;
- update_rect_ = gfx::Rect();
- damage_rect_ = gfx::RectF();
+ update_rect_.SetRect(0, 0, 0, 0);
+ damage_rect_.SetRect(0, 0, 0, 0);
if (render_surface_)
render_surface_->ResetPropertyChangedFlag();
@@ -778,6 +807,14 @@ void LayerImpl::UpdatePropertyTreeTransform() {
TransformTree& transform_tree =
layer_tree_impl()->property_trees()->transform_tree;
TransformNode* node = transform_tree.Node(transform_tree_index_);
+ // A LayerImpl's own current state is insufficient for determining whether
+ // it owns a TransformNode, since this depends on the state of the
+ // corresponding Layer at the time of the last commit. For example, a
+ // transform animation might have been in progress at the time the last
+ // commit started, but might have finished since then on the compositor
+ // thread.
+ if (node->owner_id != id())
+ return;
if (node->data.local != transform_) {
node->data.local = transform_;
node->data.needs_local_transform_update = true;
@@ -792,13 +829,61 @@ void LayerImpl::UpdatePropertyTreeTransform() {
}
}
+void LayerImpl::UpdatePropertyTreeTransformIsAnimated(bool is_animated) {
+ if (transform_tree_index_ != -1) {
+ TransformTree& transform_tree =
+ layer_tree_impl()->property_trees()->transform_tree;
+ TransformNode* node = transform_tree.Node(transform_tree_index_);
+ // A LayerImpl's own current state is insufficient for determining whether
+ // it owns a TransformNode, since this depends on the state of the
+ // corresponding Layer at the time of the last commit. For example, if
+ // |is_animated| is false, this might mean a transform animation just ticked
+ // past its finish point (so the LayerImpl still owns a TransformNode) or it
+ // might mean that a transform animation was removed during commit or
+ // activation (and, in that case, the LayerImpl will no longer own a
+ // TransformNode, unless it has non-animation-related reasons for owning a
+ // node).
+ if (node->owner_id != id())
+ return;
+ if (node->data.is_animated != is_animated) {
+ node->data.is_animated = is_animated;
+ if (is_animated) {
+ float maximum_target_scale = 0.f;
+ node->data.local_maximum_animation_target_scale =
+ MaximumTargetScale(&maximum_target_scale) ? maximum_target_scale
+ : 0.f;
+
+ float animation_start_scale = 0.f;
+ node->data.local_starting_animation_scale =
+ AnimationStartScale(&animation_start_scale) ? animation_start_scale
+ : 0.f;
+
+ node->data.has_only_translation_animations =
+ HasOnlyTranslationTransforms();
+ } else {
+ node->data.local_maximum_animation_target_scale = 0.f;
+ node->data.local_starting_animation_scale = 0.f;
+ node->data.has_only_translation_animations = true;
+ }
+
+ transform_tree.set_needs_update(true);
+ }
+ }
+}
+
void LayerImpl::UpdatePropertyTreeOpacity() {
- if (opacity_tree_index_ != -1) {
- OpacityTree& opacity_tree =
- layer_tree_impl()->property_trees()->opacity_tree;
- OpacityNode* node = opacity_tree.Node(opacity_tree_index_);
+ if (effect_tree_index_ != -1) {
+ EffectTree& effect_tree = layer_tree_impl()->property_trees()->effect_tree;
+ EffectNode* node = effect_tree.Node(effect_tree_index_);
+ // A LayerImpl's own current state is insufficient for determining whether
+ // it owns an OpacityNode, since this depends on the state of the
+ // corresponding Layer at the time of the last commit. For example, an
+ // opacity animation might have been in progress at the time the last commit
+ // started, but might have finished since then on the compositor thread.
+ if (node->owner_id != id())
+ return;
node->data.opacity = opacity_;
- opacity_tree.set_needs_update(true);
+ effect_tree.set_needs_update(true);
}
}
@@ -806,11 +891,14 @@ void LayerImpl::UpdatePropertyTreeForScrollingAndAnimationIfNeeded() {
if (scrollable())
UpdatePropertyTreeScrollOffset();
- if (OpacityIsAnimating())
+ if (HasAnyAnimationTargetingProperty(Animation::OPACITY))
UpdatePropertyTreeOpacity();
- if (TransformIsAnimating())
+ if (HasAnyAnimationTargetingProperty(Animation::TRANSFORM)) {
UpdatePropertyTreeTransform();
+ UpdatePropertyTreeTransformIsAnimated(
+ HasPotentiallyRunningTransformAnimation());
+ }
}
gfx::ScrollOffset LayerImpl::ScrollOffsetForAnimation() const {
@@ -845,6 +933,10 @@ void LayerImpl::OnScrollOffsetAnimated(const gfx::ScrollOffset& scroll_offset) {
void LayerImpl::OnAnimationWaitingForDeletion() {}
+void LayerImpl::OnTransformIsPotentiallyAnimatingChanged(bool is_animating) {
+ UpdatePropertyTreeTransformIsAnimated(is_animating);
+}
+
bool LayerImpl::IsActive() const {
return layer_tree_impl_->IsActiveTree();
}
@@ -895,8 +987,8 @@ void LayerImpl::SetBoundsDelta(const gfx::Vector2dF& bounds_delta) {
layer_tree_impl()->property_trees()->clip_tree.Node(clip_tree_index());
if (clip_node) {
DCHECK(id() == clip_node->owner_id);
- clip_node->data.clip =
- gfx::RectF(gfx::PointF() + offset_to_transform_parent(), bounds());
+ clip_node->data.clip = gfx::RectF(
+ gfx::PointF() + offset_to_transform_parent(), gfx::SizeF(bounds()));
layer_tree_impl()->property_trees()->clip_tree.set_needs_update(true);
}
@@ -1013,12 +1105,25 @@ void LayerImpl::SetFilters(const FilterOperations& filters) {
}
bool LayerImpl::FilterIsAnimating() const {
+ LayerAnimationController::ObserverType observer_type =
+ IsActive() ? LayerAnimationController::ObserverType::ACTIVE
+ : LayerAnimationController::ObserverType::PENDING;
return layer_animation_controller_
- ? layer_animation_controller_->IsAnimatingProperty(
- Animation::FILTER)
+ ? layer_animation_controller_->IsCurrentlyAnimatingProperty(
+ Animation::FILTER, observer_type)
: layer_tree_impl_->IsAnimatingFilterProperty(this);
}
+bool LayerImpl::HasPotentiallyRunningFilterAnimation() const {
+ LayerAnimationController::ObserverType observer_type =
+ IsActive() ? LayerAnimationController::ObserverType::ACTIVE
+ : LayerAnimationController::ObserverType::PENDING;
+ return layer_animation_controller_
+ ? layer_animation_controller_->IsPotentiallyAnimatingProperty(
+ Animation::FILTER, observer_type)
+ : layer_tree_impl_->HasPotentiallyRunningFilterAnimation(this);
+}
+
bool LayerImpl::FilterIsAnimatingOnImplOnly() const {
if (!layer_animation_controller_)
return layer_tree_impl_->FilterIsAnimatingOnImplOnly(this);
@@ -1062,22 +1167,23 @@ void LayerImpl::SetOpacity(float opacity) {
}
bool LayerImpl::OpacityIsAnimating() const {
+ LayerAnimationController::ObserverType observer_type =
+ IsActive() ? LayerAnimationController::ObserverType::ACTIVE
+ : LayerAnimationController::ObserverType::PENDING;
return layer_animation_controller_
- ? layer_animation_controller_->IsAnimatingProperty(
- Animation::OPACITY)
+ ? layer_animation_controller_->IsCurrentlyAnimatingProperty(
+ Animation::OPACITY, observer_type)
: layer_tree_impl_->IsAnimatingOpacityProperty(this);
}
bool LayerImpl::HasPotentiallyRunningOpacityAnimation() const {
- if (layer_animation_controller_) {
- if (Animation* animation =
- layer_animation_controller()->GetAnimation(Animation::OPACITY)) {
- return !animation->is_finished();
- }
- return false;
- } else {
- return layer_tree_impl_->HasPotentiallyRunningOpacityAnimation(this);
- }
+ LayerAnimationController::ObserverType observer_type =
+ IsActive() ? LayerAnimationController::ObserverType::ACTIVE
+ : LayerAnimationController::ObserverType::PENDING;
+ return layer_animation_controller_
+ ? layer_animation_controller_->IsPotentiallyAnimatingProperty(
+ Animation::OPACITY, observer_type)
+ : layer_tree_impl_->HasPotentiallyRunningOpacityAnimation(this);
}
bool LayerImpl::OpacityIsAnimatingOnImplOnly() const {
@@ -1162,22 +1268,23 @@ void LayerImpl::SetTransformAndInvertibility(const gfx::Transform& transform,
}
bool LayerImpl::TransformIsAnimating() const {
+ LayerAnimationController::ObserverType observer_type =
+ IsActive() ? LayerAnimationController::ObserverType::ACTIVE
+ : LayerAnimationController::ObserverType::PENDING;
return layer_animation_controller_
- ? layer_animation_controller_->IsAnimatingProperty(
- Animation::TRANSFORM)
+ ? layer_animation_controller_->IsCurrentlyAnimatingProperty(
+ Animation::TRANSFORM, observer_type)
: layer_tree_impl_->IsAnimatingTransformProperty(this);
}
bool LayerImpl::HasPotentiallyRunningTransformAnimation() const {
- if (layer_animation_controller_) {
- if (Animation* animation =
- layer_animation_controller()->GetAnimation(Animation::TRANSFORM)) {
- return !animation->is_finished();
- }
- return false;
- } else {
- return layer_tree_impl_->HasPotentiallyRunningTransformAnimation(this);
- }
+ LayerAnimationController::ObserverType observer_type =
+ IsActive() ? LayerAnimationController::ObserverType::ACTIVE
+ : LayerAnimationController::ObserverType::PENDING;
+ return layer_animation_controller_
+ ? layer_animation_controller_->IsPotentiallyAnimatingProperty(
+ Animation::TRANSFORM, observer_type)
+ : layer_tree_impl_->HasPotentiallyRunningTransformAnimation(this);
}
bool LayerImpl::TransformIsAnimatingOnImplOnly() const {
@@ -1193,21 +1300,41 @@ bool LayerImpl::HasOnlyTranslationTransforms() const {
if (!layer_animation_controller_)
return layer_tree_impl_->HasOnlyTranslationTransforms(this);
- return layer_animation_controller_->HasOnlyTranslationTransforms();
+ LayerAnimationController::ObserverType observer_type =
+ IsActive() ? LayerAnimationController::ObserverType::ACTIVE
+ : LayerAnimationController::ObserverType::PENDING;
+ return layer_animation_controller_->HasOnlyTranslationTransforms(
+ observer_type);
}
bool LayerImpl::MaximumTargetScale(float* max_scale) const {
if (!layer_animation_controller_)
return layer_tree_impl_->MaximumTargetScale(this, max_scale);
- return layer_animation_controller_->MaximumTargetScale(max_scale);
+ LayerAnimationController::ObserverType observer_type =
+ IsActive() ? LayerAnimationController::ObserverType::ACTIVE
+ : LayerAnimationController::ObserverType::PENDING;
+ return layer_animation_controller_->MaximumTargetScale(observer_type,
+ max_scale);
}
bool LayerImpl::AnimationStartScale(float* start_scale) const {
if (!layer_animation_controller_)
return layer_tree_impl_->AnimationStartScale(this, start_scale);
- return layer_animation_controller_->AnimationStartScale(start_scale);
+ LayerAnimationController::ObserverType observer_type =
+ IsActive() ? LayerAnimationController::ObserverType::ACTIVE
+ : LayerAnimationController::ObserverType::PENDING;
+ return layer_animation_controller_->AnimationStartScale(observer_type,
+ start_scale);
+}
+
+bool LayerImpl::HasAnyAnimationTargetingProperty(
+ Animation::TargetProperty property) const {
+ if (!layer_animation_controller_)
+ return layer_tree_impl_->HasAnyAnimationTargetingProperty(this, property);
+
+ return !!layer_animation_controller_->GetAnimation(property);
}
bool LayerImpl::HasFilterAnimationThatInflatesBounds() const {
@@ -1253,25 +1380,14 @@ void LayerImpl::SetUpdateRect(const gfx::Rect& update_rect) {
SetNeedsPushProperties();
}
-void LayerImpl::AddDamageRect(const gfx::RectF& damage_rect) {
- damage_rect_ = gfx::UnionRects(damage_rect_, damage_rect);
-}
-
-bool LayerImpl::IsExternalScrollActive() const {
- return layer_tree_impl_->IsExternalScrollActive();
+void LayerImpl::AddDamageRect(const gfx::Rect& damage_rect) {
+ damage_rect_.Union(damage_rect);
}
void LayerImpl::SetCurrentScrollOffset(const gfx::ScrollOffset& scroll_offset) {
DCHECK(IsActive());
if (scroll_offset_->SetCurrent(scroll_offset))
- DidUpdateScrollOffset(false);
-}
-
-void LayerImpl::SetCurrentScrollOffsetFromDelegate(
- const gfx::ScrollOffset& scroll_offset) {
- DCHECK(IsActive());
- if (scroll_offset_->SetCurrent(scroll_offset))
- DidUpdateScrollOffset(true);
+ DidUpdateScrollOffset();
}
void LayerImpl::PushScrollOffsetFromMainThread(
@@ -1289,12 +1405,13 @@ gfx::ScrollOffset LayerImpl::PullDeltaForMainThread() {
// TODO(miletus): Remove all this temporary flooring machinery when
// Blink fully supports fractional scrolls.
gfx::ScrollOffset current_offset = CurrentScrollOffset();
- gfx::Vector2dF current_delta = ScrollDelta();
- gfx::Vector2dF floored_delta(floor(current_delta.x()),
- floor(current_delta.y()));
- gfx::Vector2dF diff_delta = floored_delta - current_delta;
- gfx::ScrollOffset tmp_offset = ScrollOffsetWithDelta(current_offset,
- diff_delta);
+ gfx::ScrollOffset current_delta = IsActive()
+ ? scroll_offset_->Delta()
+ : scroll_offset_->PendingDelta().get();
+ gfx::ScrollOffset floored_delta(floor(current_delta.x()),
+ floor(current_delta.y()));
+ gfx::ScrollOffset diff_delta = floored_delta - current_delta;
+ gfx::ScrollOffset tmp_offset = current_offset + diff_delta;
scroll_offset_->SetCurrent(tmp_offset);
gfx::ScrollOffset delta = scroll_offset_->PullDeltaForMainThread();
scroll_offset_->SetCurrent(current_offset);
@@ -1340,7 +1457,7 @@ void LayerImpl::PushScrollOffset(const gfx::ScrollOffset* scroll_offset) {
}
if (changed)
- DidUpdateScrollOffset(false);
+ DidUpdateScrollOffset();
}
void LayerImpl::UpdatePropertyTreeScrollOffset() {
@@ -1359,11 +1476,9 @@ void LayerImpl::UpdatePropertyTreeScrollOffset() {
}
}
-void LayerImpl::DidUpdateScrollOffset(bool is_from_root_delegate) {
+void LayerImpl::DidUpdateScrollOffset() {
DCHECK(scroll_offset_);
- if (!is_from_root_delegate)
- layer_tree_impl()->DidUpdateScrollOffset(id());
NoteLayerPropertyChangedForSubtree();
ScrollbarParametersDidChange(false);
@@ -1373,7 +1488,7 @@ void LayerImpl::DidUpdateScrollOffset(bool is_from_root_delegate) {
if (layer_tree_impl()->IsActiveTree()) {
LayerImpl* pending_twin = layer_tree_impl()->FindPendingTreeLayerById(id());
if (pending_twin)
- pending_twin->DidUpdateScrollOffset(is_from_root_delegate);
+ pending_twin->DidUpdateScrollOffset();
}
}
@@ -1402,7 +1517,7 @@ gfx::ScrollOffset LayerImpl::MaxScrollOffset() const {
if (!scroll_clip_layer_ || bounds().IsEmpty())
return gfx::ScrollOffset();
- LayerImpl const* page_scale_layer = layer_tree_impl()->page_scale_layer();
+ LayerImpl const* page_scale_layer = layer_tree_impl()->PageScaleLayer();
DCHECK(this != page_scale_layer);
DCHECK(this != layer_tree_impl()->InnerViewportScrollLayer() ||
IsContainerForFixedPositionLayers());
@@ -1416,8 +1531,9 @@ gfx::ScrollOffset LayerImpl::MaxScrollOffset() const {
}
gfx::SizeF scaled_scroll_bounds =
- gfx::ToFlooredSize(gfx::ScaleSize(BoundsForScrolling(), scale_factor));
- scaled_scroll_bounds = gfx::ToFlooredSize(scaled_scroll_bounds);
+ gfx::ScaleSize(BoundsForScrolling(), scale_factor);
+ scaled_scroll_bounds.SetSize(std::floor(scaled_scroll_bounds.width()),
+ std::floor(scaled_scroll_bounds.height()));
gfx::ScrollOffset max_offset(
scaled_scroll_bounds.width() - scroll_clip_layer_->bounds().width(),
@@ -1448,7 +1564,7 @@ void LayerImpl::SetScrollbarPosition(ScrollbarLayerImplBase* scrollbar_layer,
LayerImpl* scrollbar_clip_layer,
bool on_resize) const {
DCHECK(scrollbar_layer);
- LayerImpl* page_scale_layer = layer_tree_impl()->page_scale_layer();
+ LayerImpl* page_scale_layer = layer_tree_impl()->PageScaleLayer();
DCHECK(this != page_scale_layer);
DCHECK(scrollbar_clip_layer);
@@ -1640,8 +1756,9 @@ void LayerImpl::AsValueInto(base::trace_event::TracedValue* state) const {
MathUtil::AddToTracedValue("transform_origin", transform_origin_, state);
bool clipped;
- gfx::QuadF layer_quad = MathUtil::MapQuad(
- screen_space_transform(), gfx::QuadF(gfx::Rect(bounds())), &clipped);
+ gfx::QuadF layer_quad =
+ MathUtil::MapQuad(screen_space_transform(),
+ gfx::QuadF(gfx::RectF(gfx::Rect(bounds()))), &clipped);
MathUtil::AddToTracedValue("layer_quad", layer_quad, state);
if (!touch_event_handler_region_.IsEmpty()) {
state->BeginArray("touch_event_handler_region");
@@ -1789,7 +1906,7 @@ gfx::Rect LayerImpl::GetScaledEnclosingRectInTargetSpace(float scale) const {
gfx::Transform scaled_draw_transform =
draw_properties_.target_space_transform;
scaled_draw_transform.Scale(SK_MScalar1 / scale, SK_MScalar1 / scale);
- gfx::Size scaled_bounds = gfx::ToCeiledSize(gfx::ScaleSize(bounds(), scale));
+ gfx::Size scaled_bounds = gfx::ScaleToCeiledSize(bounds(), scale);
return MathUtil::MapEnclosingClippedRect(scaled_draw_transform,
gfx::Rect(scaled_bounds));
}
diff --git a/chromium/cc/layers/layer_impl.h b/chromium/cc/layers/layer_impl.h
index 57a0be1204a..4e94980939e 100644
--- a/chromium/cc/layers/layer_impl.h
+++ b/chromium/cc/layers/layer_impl.h
@@ -57,7 +57,7 @@ class LayerTreeHostImpl;
class LayerTreeImpl;
class MicroBenchmarkImpl;
class Occlusion;
-class OpacityTree;
+class EffectTree;
class PrioritizedTile;
class RenderPass;
class RenderPassId;
@@ -67,6 +67,7 @@ class ScrollbarLayerImplBase;
class SimpleEnclosedRegion;
class Tile;
class TransformTree;
+class ScrollState;
struct AppendQuadsData;
@@ -112,6 +113,7 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver,
void OnTransformAnimated(const gfx::Transform& transform) override;
void OnScrollOffsetAnimated(const gfx::ScrollOffset& scroll_offset) override;
void OnAnimationWaitingForDeletion() override;
+ void OnTransformIsPotentiallyAnimatingChanged(bool is_animating) override;
bool IsActive() const override;
// AnimationDelegate implementation.
@@ -149,6 +151,9 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver,
return scroll_children_.get();
}
+ void DistributeScroll(ScrollState* scroll_state);
+ void ApplyScroll(ScrollState* scroll_state);
+
void set_property_tree_sequence_number(int sequence_number) {}
void SetTransformTreeIndex(int index);
@@ -157,8 +162,8 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver,
void SetClipTreeIndex(int index);
int clip_tree_index() const { return clip_tree_index_; }
- void SetOpacityTreeIndex(int index);
- int opacity_tree_index() const { return opacity_tree_index_; }
+ void SetEffectTreeIndex(int index);
+ int effect_tree_index() const { return effect_tree_index_; }
void set_offset_to_transform_parent(const gfx::Vector2dF& offset) {
offset_to_transform_parent_ = offset;
@@ -175,6 +180,14 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver,
visible_rect_from_property_trees_ = rect;
}
+ const gfx::Rect& clip_rect_in_target_space_from_property_trees() const {
+ return clip_rect_in_target_space_from_property_trees_;
+ }
+ void set_clip_rect_in_target_space_from_property_trees(
+ const gfx::Rect& rect) {
+ clip_rect_in_target_space_from_property_trees_ = rect;
+ }
+
void set_should_flatten_transform_from_property_tree(bool should_flatten) {
should_flatten_transform_from_property_tree_ = should_flatten;
SetNeedsPushProperties();
@@ -183,7 +196,10 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver,
return should_flatten_transform_from_property_tree_;
}
+ bool is_clipped() const { return draw_properties_.is_clipped; }
+
void UpdatePropertyTreeTransform();
+ void UpdatePropertyTreeTransformIsAnimated(bool is_animated);
void UpdatePropertyTreeOpacity();
void UpdatePropertyTreeScrollOffset();
@@ -284,6 +300,7 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver,
void SetFilters(const FilterOperations& filters);
const FilterOperations& filters() const { return filters_; }
bool FilterIsAnimating() const;
+ bool HasPotentiallyRunningFilterAnimation() const;
bool FilterIsAnimatingOnImplOnly() const;
void SetBackgroundFilters(const FilterOperations& filters);
@@ -305,6 +322,13 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver,
void SetBlendMode(SkXfermode::Mode);
SkXfermode::Mode blend_mode() const { return blend_mode_; }
+ void set_draw_blend_mode(SkXfermode::Mode blend_mode) {
+ if (draw_blend_mode_ == blend_mode)
+ return;
+ draw_blend_mode_ = blend_mode;
+ SetNeedsPushProperties();
+ }
+ SkXfermode::Mode draw_blend_mode() const { return draw_blend_mode_; }
bool uses_default_blend_mode() const {
return blend_mode_ == SkXfermode::kSrcOver_Mode;
}
@@ -361,12 +385,8 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver,
RenderSurfaceImpl* render_surface() const { return render_surface_.get(); }
- DrawProperties<LayerImpl>& draw_properties() {
- return draw_properties_;
- }
- const DrawProperties<LayerImpl>& draw_properties() const {
- return draw_properties_;
- }
+ DrawProperties& draw_properties() { return draw_properties_; }
+ const DrawProperties& draw_properties() const { return draw_properties_; }
// The following are shortcut accessors to get various information from
// draw_properties_
@@ -377,23 +397,10 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver,
return draw_properties_.screen_space_transform;
}
float draw_opacity() const { return draw_properties_.opacity; }
- SkXfermode::Mode draw_blend_mode() const {
- return draw_properties_.blend_mode;
- }
- bool draw_opacity_is_animating() const {
- return draw_properties_.opacity_is_animating;
- }
- bool draw_transform_is_animating() const {
- return draw_properties_.target_space_transform_is_animating;
- }
bool screen_space_transform_is_animating() const {
return draw_properties_.screen_space_transform_is_animating;
}
- bool screen_space_opacity_is_animating() const {
- return draw_properties_.screen_space_opacity_is_animating;
- }
bool can_use_lcd_text() const { return draw_properties_.can_use_lcd_text; }
- bool is_clipped() const { return draw_properties_.is_clipped; }
gfx::Rect clip_rect() const { return draw_properties_.clip_rect; }
gfx::Rect drawable_content_rect() const {
return draw_properties_.drawable_content_rect;
@@ -428,11 +435,7 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver,
void SetBoundsDelta(const gfx::Vector2dF& bounds_delta);
gfx::Vector2dF bounds_delta() const { return bounds_delta_; }
- bool IsExternalScrollActive() const;
-
void SetCurrentScrollOffset(const gfx::ScrollOffset& scroll_offset);
- void SetCurrentScrollOffsetFromDelegate(
- const gfx::ScrollOffset& scroll_offset);
void PushScrollOffsetFromMainThread(const gfx::ScrollOffset& scroll_offset);
// This method is similar to PushScrollOffsetFromMainThread but will cause the
// scroll offset given to clobber any scroll changes on the active tree in the
@@ -518,12 +521,6 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver,
scroll_blocks_on_ = scroll_blocks_on;
}
ScrollBlocksOn scroll_blocks_on() const { return scroll_blocks_on_; }
- void SetDrawCheckerboardForMissingTiles(bool checkerboard) {
- draw_checkerboard_for_missing_tiles_ = checkerboard;
- }
- bool draw_checkerboard_for_missing_tiles() const {
- return draw_checkerboard_for_missing_tiles_;
- }
InputHandler::ScrollStatus TryScroll(
const gfx::PointF& screen_space_point,
@@ -546,6 +543,11 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver,
bool MaximumTargetScale(float* max_scale) const;
bool AnimationStartScale(float* start_scale) const;
+ // This includes all animations, even those that are finished but haven't yet
+ // been deleted.
+ bool HasAnyAnimationTargetingProperty(
+ Animation::TargetProperty property) const;
+
bool HasFilterAnimationThatInflatesBounds() const;
bool HasTransformAnimationThatInflatesBounds() const;
bool HasAnimationThatInflatesBounds() const;
@@ -557,11 +559,10 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver,
// Note this rect is in layer space (not content space).
void SetUpdateRect(const gfx::Rect& update_rect);
- gfx::Rect update_rect() const { return update_rect_; }
-
- void AddDamageRect(const gfx::RectF& damage_rect);
+ const gfx::Rect& update_rect() const { return update_rect_; }
- const gfx::RectF& damage_rect() const { return damage_rect_; }
+ void AddDamageRect(const gfx::Rect& damage_rect);
+ const gfx::Rect& damage_rect() const { return damage_rect_; }
virtual base::DictionaryValue* LayerTreeAsJson() const;
@@ -666,12 +667,30 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver,
bool layer_or_descendant_is_drawn() { return layer_or_descendant_is_drawn_; }
+ void set_layer_or_descendant_has_input_handler(
+ bool layer_or_descendant_has_input_handler) {
+ layer_or_descendant_has_input_handler_ =
+ layer_or_descendant_has_input_handler;
+ }
+
+ bool layer_or_descendant_has_input_handler() {
+ return layer_or_descendant_has_input_handler_;
+ }
+
void set_sorted_for_recursion(bool sorted_for_recursion) {
sorted_for_recursion_ = sorted_for_recursion;
}
-
bool sorted_for_recursion() { return sorted_for_recursion_; }
+ void set_num_layer_or_descendant_with_copy_request(
+ int num_layer_or_descendants_with_copy_request) {
+ num_layer_or_descendants_with_copy_request_ =
+ num_layer_or_descendants_with_copy_request;
+ }
+ int num_layer_or_descendants_with_copy_request() {
+ return num_layer_or_descendants_with_copy_request_;
+ }
+
void UpdatePropertyTreeForScrollingAndAnimationIfNeeded();
float GetIdealContentsScale() const;
@@ -708,10 +727,7 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver,
void ValidateQuadResourcesInternal(DrawQuad* quad) const;
void PushScrollOffset(const gfx::ScrollOffset* scroll_offset);
- // If the new scroll offset is assigned from the root scroll offset delegate,
- // LayerImpl won't inform the root scroll offset delegate about the scroll
- // change to avoid feedback.
- void DidUpdateScrollOffset(bool is_from_root_delegate);
+ void DidUpdateScrollOffset();
void NoteLayerPropertyChangedForDescendantsInternal();
virtual const char* LayerTypeAsString() const;
@@ -751,7 +767,6 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver,
gfx::Vector2dF offset_to_transform_parent_;
- bool scrollable_ : 1;
bool should_scroll_on_main_thread_ : 1;
bool have_wheel_event_handlers_ : 1;
bool have_scroll_event_handlers_ : 1;
@@ -774,7 +789,6 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver,
bool contents_opaque_ : 1;
bool is_root_for_isolated_group_ : 1;
bool use_parent_backface_visibility_ : 1;
- bool draw_checkerboard_for_missing_tiles_ : 1;
bool draws_content_ : 1;
bool hide_layer_and_subtree_ : 1;
@@ -792,6 +806,9 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver,
float opacity_;
SkXfermode::Mode blend_mode_;
+ // draw_blend_mode may be different than blend_mode_,
+ // when a RenderSurface re-parents the layer's blend_mode.
+ SkXfermode::Mode draw_blend_mode_;
gfx::PointF position_;
gfx::Transform transform_;
@@ -802,8 +819,9 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver,
int num_descendants_that_draw_content_;
gfx::Rect visible_rect_from_property_trees_;
+ gfx::Rect clip_rect_in_target_space_from_property_trees_;
int transform_tree_index_;
- int opacity_tree_index_;
+ int effect_tree_index_;
int clip_tree_index_;
// The global depth value of the center of the layer. This value is used
@@ -835,11 +853,12 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver,
private:
// Rect indicating what was repainted/updated during update.
// Note that plugin layers bypass this and leave it empty.
- // Uses layer (not content) space.
+ // This is in the layer's space.
gfx::Rect update_rect_;
- // This rect is in layer space.
- gfx::RectF damage_rect_;
+ // Denotes an area that is damaged and needs redraw. This is in the layer's
+ // space.
+ gfx::Rect damage_rect_;
// Manages animations for this layer.
scoped_refptr<LayerAnimationController> layer_animation_controller_;
@@ -853,15 +872,18 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver,
// Group of properties that need to be computed based on the layer tree
// hierarchy before layers can be drawn.
- DrawProperties<LayerImpl> draw_properties_;
+ DrawProperties draw_properties_;
scoped_refptr<base::trace_event::ConvertableToTraceFormat> debug_info_;
scoped_ptr<RenderSurfaceImpl> render_surface_;
std::vector<FrameTimingRequest> frame_timing_requests_;
+ int num_layer_or_descendants_with_copy_request_;
bool frame_timing_requests_dirty_;
bool visited_;
bool layer_or_descendant_is_drawn_;
+ // If true, the layer or one of its descendants has a wheel or touch handler.
+ bool layer_or_descendant_has_input_handler_;
bool sorted_for_recursion_;
DISALLOW_COPY_AND_ASSIGN(LayerImpl);
diff --git a/chromium/cc/layers/layer_impl_unittest.cc b/chromium/cc/layers/layer_impl_unittest.cc
index 964b9994085..7404e4e2663 100644
--- a/chromium/cc/layers/layer_impl_unittest.cc
+++ b/chromium/cc/layers/layer_impl_unittest.cc
@@ -89,9 +89,10 @@ TEST(LayerImplTest, VerifyLayerChangesAreTrackedProperly) {
FakeImplProxy proxy;
TestSharedBitmapManager shared_bitmap_manager;
TestTaskGraphRunner task_graph_runner;
+ scoped_ptr<OutputSurface> output_surface = FakeOutputSurface::Create3d();
FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager,
&task_graph_runner);
- EXPECT_TRUE(host_impl.InitializeRenderer(FakeOutputSurface::Create3d()));
+ EXPECT_TRUE(host_impl.InitializeRenderer(output_surface.get()));
scoped_ptr<LayerImpl> root_clip =
LayerImpl::Create(host_impl.active_tree(), 1);
scoped_ptr<LayerImpl> root_ptr =
@@ -247,9 +248,10 @@ TEST(LayerImplTest, VerifyNeedsUpdateDrawProperties) {
FakeImplProxy proxy;
TestSharedBitmapManager shared_bitmap_manager;
TestTaskGraphRunner task_graph_runner;
+ scoped_ptr<OutputSurface> output_surface = FakeOutputSurface::Create3d();
FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager,
&task_graph_runner);
- EXPECT_TRUE(host_impl.InitializeRenderer(FakeOutputSurface::Create3d()));
+ EXPECT_TRUE(host_impl.InitializeRenderer(output_surface.get()));
host_impl.active_tree()->SetRootLayer(
LayerImpl::Create(host_impl.active_tree(), 1));
LayerImpl* root = host_impl.active_tree()->root_layer();
@@ -310,6 +312,7 @@ TEST(LayerImplTest, VerifyNeedsUpdateDrawProperties) {
// Unrelated functions, always set to new values, always set needs update.
VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(
layer->SetMaskLayer(LayerImpl::Create(host_impl.active_tree(), 4)));
+ host_impl.active_tree()->BuildPropertyTreesForTesting();
VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(layer->SetMasksToBounds(true));
VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(layer->SetContentsOpaque(true));
VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(
@@ -360,9 +363,10 @@ TEST(LayerImplTest, SafeOpaqueBackgroundColor) {
FakeImplProxy proxy;
TestSharedBitmapManager shared_bitmap_manager;
TestTaskGraphRunner task_graph_runner;
+ scoped_ptr<OutputSurface> output_surface = FakeOutputSurface::Create3d();
FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager,
&task_graph_runner);
- EXPECT_TRUE(host_impl.InitializeRenderer(FakeOutputSurface::Create3d()));
+ EXPECT_TRUE(host_impl.InitializeRenderer(output_surface.get()));
scoped_ptr<LayerImpl> layer = LayerImpl::Create(host_impl.active_tree(), 1);
for (int contents_opaque = 0; contents_opaque < 2; ++contents_opaque) {
diff --git a/chromium/cc/layers/layer_lists.cc b/chromium/cc/layers/layer_lists.cc
deleted file mode 100644
index 7a4df7295a3..00000000000
--- a/chromium/cc/layers/layer_lists.cc
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cc/layers/layer_lists.h"
-
-#include "cc/layers/layer.h"
-
-namespace cc {
-
-RenderSurfaceLayerList::RenderSurfaceLayerList() {}
-
-RenderSurfaceLayerList::~RenderSurfaceLayerList() {
- for (size_t i = 0; i < size(); ++i)
- at(size() - 1 - i)->ClearRenderSurface();
-}
-
-Layer* RenderSurfaceLayerList::at(size_t i) const {
- return list_.at(i).get();
-}
-
-void RenderSurfaceLayerList::pop_back() {
- list_.pop_back();
-}
-
-void RenderSurfaceLayerList::push_back(const scoped_refptr<Layer>& layer) {
- list_.push_back(layer);
-}
-
-Layer* RenderSurfaceLayerList::back() {
- return list_.back().get();
-}
-
-size_t RenderSurfaceLayerList::size() const {
- return list_.size();
-}
-
-scoped_refptr<Layer>& RenderSurfaceLayerList::operator[](size_t i) {
- return list_[i];
-}
-const scoped_refptr<Layer>& RenderSurfaceLayerList::operator[](size_t i) const {
- return list_[i];
-}
-
-LayerList::iterator RenderSurfaceLayerList::begin() {
- return list_.begin();
-}
-
-LayerList::iterator RenderSurfaceLayerList::end() {
- return list_.end();
-}
-
-LayerList::const_iterator RenderSurfaceLayerList::begin() const {
- return list_.begin();
-}
-
-LayerList::const_iterator RenderSurfaceLayerList::end() const {
- return list_.end();
-}
-
-void RenderSurfaceLayerList::clear() {
- for (size_t i = 0; i < list_.size(); ++i)
- DCHECK(!list_[i]->render_surface());
- list_.clear();
-}
-
-} // namespace cc
diff --git a/chromium/cc/layers/layer_lists.h b/chromium/cc/layers/layer_lists.h
index 9a4084b340f..870785dad93 100644
--- a/chromium/cc/layers/layer_lists.h
+++ b/chromium/cc/layers/layer_lists.h
@@ -16,37 +16,9 @@ class Layer;
class LayerImpl;
typedef std::vector<scoped_refptr<Layer>> LayerList;
-
typedef ScopedPtrVector<LayerImpl> OwnedLayerImplList;
typedef std::vector<LayerImpl*> LayerImplList;
-class CC_EXPORT RenderSurfaceLayerList {
- public:
- RenderSurfaceLayerList();
- ~RenderSurfaceLayerList();
-
- Layer* at(size_t i) const;
- void pop_back();
- void push_back(const scoped_refptr<Layer>& layer);
- Layer* back();
- size_t size() const;
- bool empty() const { return size() == 0u; }
- scoped_refptr<Layer>& operator[](size_t i);
- const scoped_refptr<Layer>& operator[](size_t i) const;
- LayerList::iterator begin();
- LayerList::iterator end();
- LayerList::const_iterator begin() const;
- LayerList::const_iterator end() const;
- void clear();
- LayerList& AsLayerList() { return list_; }
- const LayerList& AsLayerList() const { return list_; }
-
- private:
- LayerList list_;
-
- DISALLOW_COPY_AND_ASSIGN(RenderSurfaceLayerList);
-};
-
} // namespace cc
#endif // CC_LAYERS_LAYER_LISTS_H_
diff --git a/chromium/cc/layers/layer_position_constraint_unittest.cc b/chromium/cc/layers/layer_position_constraint_unittest.cc
index fdb7f5b6ea4..377d3f417ff 100644
--- a/chromium/cc/layers/layer_position_constraint_unittest.cc
+++ b/chromium/cc/layers/layer_position_constraint_unittest.cc
@@ -136,9 +136,8 @@ class LayerPositionConstraintTest : public testing::Test {
}
void CommitAndUpdateImplPointers() {
- RenderSurfaceLayerList render_surface_layer_list;
- LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
- root_.get(), root_->bounds(), &render_surface_layer_list);
+ LayerTreeHostCommon::CalcDrawPropsMainInputs inputs(root_.get(),
+ root_->bounds());
inputs.inner_viewport_scroll_layer =
layer_tree_host_->inner_viewport_scroll_layer();
inputs.outer_viewport_scroll_layer =
diff --git a/chromium/cc/layers/layer_unittest.cc b/chromium/cc/layers/layer_unittest.cc
index ba8e92d75b9..10b1d147eaf 100644
--- a/chromium/cc/layers/layer_unittest.cc
+++ b/chromium/cc/layers/layer_unittest.cc
@@ -630,10 +630,6 @@ TEST_F(LayerTest, CheckPropertyChangeCausesCorrectBehavior) {
EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetDoubleSided(false));
EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetTouchEventHandlerRegion(
gfx::Rect(10, 10)));
- EXPECT_SET_NEEDS_COMMIT(
- 1,
- test_layer->SetDrawCheckerboardForMissingTiles(
- !test_layer->draw_checkerboard_for_missing_tiles()));
EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetForceRenderSurface(true));
EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetHideLayerAndSubtree(true));
diff --git a/chromium/cc/layers/nine_patch_layer_impl_unittest.cc b/chromium/cc/layers/nine_patch_layer_impl_unittest.cc
index 3535c985106..3405bc545cf 100644
--- a/chromium/cc/layers/nine_patch_layer_impl_unittest.cc
+++ b/chromium/cc/layers/nine_patch_layer_impl_unittest.cc
@@ -46,9 +46,10 @@ void NinePatchLayerLayoutTest(const gfx::Size& bitmap_size,
FakeImplProxy proxy;
TestSharedBitmapManager shared_bitmap_manager;
TestTaskGraphRunner task_graph_runner;
+ scoped_ptr<OutputSurface> output_surface = FakeOutputSurface::Create3d();
FakeUIResourceLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager,
&task_graph_runner);
- host_impl.InitializeRenderer(FakeOutputSurface::Create3d());
+ host_impl.InitializeRenderer(output_surface.get());
scoped_ptr<NinePatchLayerImpl> layer =
NinePatchLayerImpl::Create(host_impl.active_tree(), 1);
@@ -84,7 +85,7 @@ void NinePatchLayerLayoutTest(const gfx::Size& bitmap_size,
// Check if the left-over quad is the same size as the mapped aperture quad in
// layer space.
if (!fill_center) {
- EXPECT_EQ(expected_remaining, gfx::ToEnclosedRect(remaining.bounds()));
+ EXPECT_EQ(expected_remaining, remaining.bounds());
} else {
EXPECT_TRUE(remaining.bounds().IsEmpty());
}
diff --git a/chromium/cc/layers/painted_scrollbar_layer.cc b/chromium/cc/layers/painted_scrollbar_layer.cc
index f537ffc7e07..67f83c650cf 100644
--- a/chromium/cc/layers/painted_scrollbar_layer.cc
+++ b/chromium/cc/layers/painted_scrollbar_layer.cc
@@ -94,7 +94,7 @@ float PaintedScrollbarLayer::ClampScaleToMaxTextureSize(float scale) {
// If the scaled bounds() is bigger than the max texture size of the
// device, we need to clamp it by rescaling, since this is used
// below to set the texture size.
- gfx::Size scaled_bounds = gfx::ToCeiledSize(gfx::ScaleSize(bounds(), scale));
+ gfx::Size scaled_bounds = gfx::ScaleToCeiledSize(bounds(), scale);
if (scaled_bounds.width() > MaxTextureSize() ||
scaled_bounds.height() > MaxTextureSize()) {
if (scaled_bounds.width() > scaled_bounds.height())
@@ -218,9 +218,9 @@ void PaintedScrollbarLayer::UpdateInternalContentScale() {
bool changed = false;
changed |= UpdateProperty(ClampScaleToMaxTextureSize(scale),
&internal_contents_scale_);
- changed |= UpdateProperty(
- gfx::ToCeiledSize(gfx::ScaleSize(bounds(), internal_contents_scale_)),
- &internal_content_bounds_);
+ changed |=
+ UpdateProperty(gfx::ScaleToCeiledSize(bounds(), internal_contents_scale_),
+ &internal_content_bounds_);
if (changed) {
// If the content scale or bounds change, repaint.
SetNeedsDisplay();
@@ -243,7 +243,7 @@ bool PaintedScrollbarLayer::Update() {
bool updated = false;
- if (track_rect_.IsEmpty() || scaled_track_rect.IsEmpty()) {
+ if (scaled_track_rect.IsEmpty()) {
if (track_resource_) {
track_resource_ = nullptr;
thumb_resource_ = nullptr;
diff --git a/chromium/cc/layers/picture_image_layer.cc b/chromium/cc/layers/picture_image_layer.cc
index 6d903bd40bc..ee129330b3e 100644
--- a/chromium/cc/layers/picture_image_layer.cc
+++ b/chromium/cc/layers/picture_image_layer.cc
@@ -5,8 +5,10 @@
#include "cc/layers/picture_image_layer.h"
#include "cc/layers/picture_image_layer_impl.h"
+#include "cc/playback/display_item_list_settings.h"
#include "cc/playback/drawing_display_item.h"
#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkImage.h"
#include "third_party/skia/include/core/SkPictureRecorder.h"
#include "ui/gfx/skia_util.h"
@@ -31,18 +33,18 @@ scoped_ptr<LayerImpl> PictureImageLayer::CreateLayerImpl(
}
bool PictureImageLayer::HasDrawableContent() const {
- return !bitmap_.isNull() && PictureLayer::HasDrawableContent();
+ return image_ && PictureLayer::HasDrawableContent();
}
-void PictureImageLayer::SetBitmap(const SkBitmap& bitmap) {
- // SetBitmap() currently gets called whenever there is any
+void PictureImageLayer::SetImage(skia::RefPtr<const SkImage> image) {
+ // SetImage() currently gets called whenever there is any
// style change that affects the layer even if that change doesn't
// affect the actual contents of the image (e.g. a CSS animation).
// With this check in place we avoid unecessary texture uploads.
- if (bitmap.pixelRef() && bitmap.pixelRef() == bitmap_.pixelRef())
+ if (image_.get() == image.get())
return;
- bitmap_ = bitmap;
+ image_ = image.Pass();
UpdateDrawsContent(HasDrawableContent());
SetNeedsDisplay();
}
@@ -51,19 +53,20 @@ void PictureImageLayer::PaintContents(
SkCanvas* canvas,
const gfx::Rect& clip,
ContentLayerClient::PaintingControlSetting painting_control) {
- if (!bitmap_.width() || !bitmap_.height())
- return;
+ DCHECK(image_);
+ DCHECK_GT(image_->width(), 0);
+ DCHECK_GT(image_->height(), 0);
SkScalar content_to_layer_scale_x =
- SkFloatToScalar(static_cast<float>(bounds().width()) / bitmap_.width());
+ SkFloatToScalar(static_cast<float>(bounds().width()) / image_->width());
SkScalar content_to_layer_scale_y =
- SkFloatToScalar(static_cast<float>(bounds().height()) / bitmap_.height());
+ SkFloatToScalar(static_cast<float>(bounds().height()) / image_->height());
canvas->scale(content_to_layer_scale_x, content_to_layer_scale_y);
// Because Android WebView resourceless software draw mode rasters directly
// to the root canvas, this draw must use the kSrcOver_Mode so that
// transparent images blend correctly.
- canvas->drawBitmap(bitmap_, 0, 0);
+ canvas->drawImage(image_.get(), 0, 0);
}
scoped_refptr<DisplayItemList> PictureImageLayer::PaintContentsToDisplayList(
@@ -71,9 +74,10 @@ scoped_refptr<DisplayItemList> PictureImageLayer::PaintContentsToDisplayList(
ContentLayerClient::PaintingControlSetting painting_control) {
// Picture image layers can be used with GatherPixelRefs, so cached SkPictures
// are currently required.
- const bool use_cached_picture = true;
+ DisplayItemListSettings settings;
+ settings.use_cached_picture = true;
scoped_refptr<DisplayItemList> display_list =
- DisplayItemList::Create(clip, use_cached_picture);
+ DisplayItemList::Create(clip, settings);
SkPictureRecorder recorder;
SkCanvas* canvas = recorder.beginRecording(gfx::RectToSkRect(clip));
@@ -92,4 +96,8 @@ bool PictureImageLayer::FillsBoundsCompletely() const {
return false;
}
+size_t PictureImageLayer::GetApproximateUnsharedMemoryUsage() const {
+ return 0;
+}
+
} // namespace cc
diff --git a/chromium/cc/layers/picture_image_layer.h b/chromium/cc/layers/picture_image_layer.h
index df597f3bf02..df3068683c3 100644
--- a/chromium/cc/layers/picture_image_layer.h
+++ b/chromium/cc/layers/picture_image_layer.h
@@ -8,16 +8,18 @@
#include "cc/base/cc_export.h"
#include "cc/layers/content_layer_client.h"
#include "cc/layers/picture_layer.h"
-#include "third_party/skia/include/core/SkBitmap.h"
+#include "skia/ext/refptr.h"
#include "ui/gfx/geometry/size.h"
+class SkImage;
+
namespace cc {
class CC_EXPORT PictureImageLayer : public PictureLayer, ContentLayerClient {
public:
static scoped_refptr<PictureImageLayer> Create(const LayerSettings& settings);
- void SetBitmap(const SkBitmap& image);
+ void SetImage(skia::RefPtr<const SkImage> image);
// Layer implementation.
scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override;
@@ -31,6 +33,7 @@ class CC_EXPORT PictureImageLayer : public PictureLayer, ContentLayerClient {
const gfx::Rect& clip,
ContentLayerClient::PaintingControlSetting painting_control) override;
bool FillsBoundsCompletely() const override;
+ size_t GetApproximateUnsharedMemoryUsage() const override;
protected:
bool HasDrawableContent() const override;
@@ -39,7 +42,7 @@ class CC_EXPORT PictureImageLayer : public PictureLayer, ContentLayerClient {
explicit PictureImageLayer(const LayerSettings& settings);
~PictureImageLayer() override;
- SkBitmap bitmap_;
+ skia::RefPtr<const SkImage> image_;
DISALLOW_COPY_AND_ASSIGN(PictureImageLayer);
};
diff --git a/chromium/cc/layers/picture_image_layer_impl_unittest.cc b/chromium/cc/layers/picture_image_layer_impl_unittest.cc
index 2a9dda710db..8d36095e0f3 100644
--- a/chromium/cc/layers/picture_image_layer_impl_unittest.cc
+++ b/chromium/cc/layers/picture_image_layer_impl_unittest.cc
@@ -7,10 +7,10 @@
#include "base/thread_task_runner_handle.h"
#include "cc/layers/append_quads_data.h"
#include "cc/quads/draw_quad.h"
+#include "cc/test/fake_display_list_raster_source.h"
#include "cc/test/fake_impl_proxy.h"
#include "cc/test/fake_layer_tree_host_impl.h"
#include "cc/test/fake_output_surface.h"
-#include "cc/test/fake_picture_pile_impl.h"
#include "cc/test/test_shared_bitmap_manager.h"
#include "cc/test/test_task_graph_runner.h"
#include "cc/tiles/tile_priority.h"
@@ -43,12 +43,13 @@ class PictureImageLayerImplTest : public testing::Test {
public:
PictureImageLayerImplTest()
: proxy_(base::ThreadTaskRunnerHandle::Get()),
+ output_surface_(FakeOutputSurface::Create3d()),
host_impl_(PictureLayerImplImageTestSettings(),
&proxy_,
&shared_bitmap_manager_,
&task_graph_runner_) {
host_impl_.CreatePendingTree();
- host_impl_.InitializeRenderer(FakeOutputSurface::Create3d());
+ host_impl_.InitializeRenderer(output_surface_.get());
}
scoped_ptr<TestablePictureImageLayerImpl> CreateLayer(int id,
@@ -64,7 +65,7 @@ class PictureImageLayerImplTest : public testing::Test {
}
TestablePictureImageLayerImpl* layer =
new TestablePictureImageLayerImpl(tree, id);
- layer->raster_source_ = FakePicturePileImpl::CreateInfiniteFilledPile();
+ layer->raster_source_ = FakeDisplayListRasterSource::CreateInfiniteFilled();
layer->SetBounds(layer->raster_source_->GetSize());
return make_scoped_ptr(layer);
}
@@ -93,6 +94,7 @@ class PictureImageLayerImplTest : public testing::Test {
FakeImplProxy proxy_;
TestSharedBitmapManager shared_bitmap_manager_;
TestTaskGraphRunner task_graph_runner_;
+ scoped_ptr<OutputSurface> output_surface_;
FakeLayerTreeHostImpl host_impl_;
};
diff --git a/chromium/cc/layers/picture_image_layer_unittest.cc b/chromium/cc/layers/picture_image_layer_unittest.cc
index fafdbf12541..f9379c6e3f9 100644
--- a/chromium/cc/layers/picture_image_layer_unittest.cc
+++ b/chromium/cc/layers/picture_image_layer_unittest.cc
@@ -8,9 +8,10 @@
#include "cc/test/skia_common.h"
#include "cc/trees/layer_tree_settings.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkColor.h"
+#include "third_party/skia/include/core/SkImage.h"
+#include "third_party/skia/include/core/SkSurface.h"
namespace cc {
namespace {
@@ -20,19 +21,21 @@ TEST(PictureImageLayerTest, PaintContentsToDisplayList) {
PictureImageLayer::Create(LayerSettings());
gfx::Rect layer_rect(200, 200);
- SkBitmap image_bitmap;
unsigned char image_pixels[4 * 200 * 200] = {0};
SkImageInfo info =
SkImageInfo::MakeN32Premul(layer_rect.width(), layer_rect.height());
- image_bitmap.installPixels(info, image_pixels, info.minRowBytes());
- SkCanvas image_canvas(image_bitmap);
- image_canvas.clear(SK_ColorRED);
+ skia::RefPtr<SkSurface> image_surface = skia::AdoptRef(
+ SkSurface::NewRasterDirect(info, image_pixels, info.minRowBytes()));
+ SkCanvas* image_canvas = image_surface->getCanvas();
+ image_canvas->clear(SK_ColorRED);
SkPaint blue_paint;
blue_paint.setColor(SK_ColorBLUE);
- image_canvas.drawRectCoords(0.f, 0.f, 100.f, 100.f, blue_paint);
- image_canvas.drawRectCoords(100.f, 100.f, 200.f, 200.f, blue_paint);
+ image_canvas->drawRectCoords(0.f, 0.f, 100.f, 100.f, blue_paint);
+ image_canvas->drawRectCoords(100.f, 100.f, 200.f, 200.f, blue_paint);
- layer->SetBitmap(image_bitmap);
+ skia::RefPtr<const SkImage> image =
+ skia::AdoptRef(image_surface->newImageSnapshot());
+ layer->SetImage(image.Pass());
layer->SetBounds(gfx::Size(layer_rect.width(), layer_rect.height()));
scoped_refptr<DisplayItemList> display_list =
diff --git a/chromium/cc/layers/picture_layer.cc b/chromium/cc/layers/picture_layer.cc
index 53d5d97d456..6c215a3eba8 100644
--- a/chromium/cc/layers/picture_layer.cc
+++ b/chromium/cc/layers/picture_layer.cc
@@ -8,7 +8,6 @@
#include "cc/layers/content_layer_client.h"
#include "cc/layers/picture_layer_impl.h"
#include "cc/playback/display_list_recording_source.h"
-#include "cc/playback/picture_pile.h"
#include "cc/trees/layer_tree_host.h"
#include "cc/trees/layer_tree_impl.h"
#include "third_party/skia/include/core/SkPictureRecorder.h"
@@ -89,19 +88,15 @@ void PictureLayer::SetLayerTreeHost(LayerTreeHost* host) {
if (!host)
return;
- const LayerTreeSettings& settings = layer_tree_host()->settings();
- if (!recording_source_) {
- if (settings.use_display_lists) {
- recording_source_.reset(
- new DisplayListRecordingSource(settings.default_tile_grid_size));
- } else {
- recording_source_.reset(new PicturePile(settings.minimum_contents_scale,
- settings.default_tile_grid_size));
- }
- }
+ if (!recording_source_)
+ recording_source_.reset(new DisplayListRecordingSource);
recording_source_->SetSlowdownRasterScaleFactor(
host->debug_state().slow_down_raster_scale_factor);
- recording_source_->SetGatherPixelRefs(settings.gather_pixel_refs);
+ // If we need to enable image decode tasks, then we have to generate the
+ // discardable images metadata.
+ const LayerTreeSettings& settings = layer_tree_host()->settings();
+ recording_source_->SetGenerateDiscardableImagesMetadata(
+ settings.image_decode_tasks_enabled);
}
void PictureLayer::SetNeedsDisplayRect(const gfx::Rect& layer_rect) {
@@ -181,33 +176,16 @@ skia::RefPtr<SkPicture> PictureLayer::GetPicture() const {
return skia::RefPtr<SkPicture>();
gfx::Size layer_size = bounds();
- const LayerTreeSettings& settings = layer_tree_host()->settings();
-
- if (settings.use_display_lists) {
- scoped_ptr<RecordingSource> recording_source;
- recording_source.reset(
- new DisplayListRecordingSource(settings.default_tile_grid_size));
- Region recording_invalidation;
- recording_source->UpdateAndExpandInvalidation(
- client_, &recording_invalidation, layer_size, gfx::Rect(layer_size),
- update_source_frame_number_, RecordingSource::RECORD_NORMALLY);
-
- scoped_refptr<RasterSource> raster_source =
- recording_source->CreateRasterSource(false);
-
- return raster_source->GetFlattenedPicture();
- }
+ scoped_ptr<RecordingSource> recording_source(new DisplayListRecordingSource);
+ Region recording_invalidation;
+ recording_source->UpdateAndExpandInvalidation(
+ client_, &recording_invalidation, layer_size, gfx::Rect(layer_size),
+ update_source_frame_number_, RecordingSource::RECORD_NORMALLY);
- int width = layer_size.width();
- int height = layer_size.height();
+ scoped_refptr<RasterSource> raster_source =
+ recording_source->CreateRasterSource(false);
- SkPictureRecorder recorder;
- SkCanvas* canvas = recorder.beginRecording(width, height, nullptr, 0);
- client_->PaintContents(canvas, gfx::Rect(width, height),
- ContentLayerClient::PAINTING_BEHAVIOR_NORMAL);
- skia::RefPtr<SkPicture> picture =
- skia::AdoptRef(recorder.endRecordingAsPicture());
- return picture;
+ return raster_source->GetFlattenedPicture();
}
bool PictureLayer::IsSuitableForGpuRasterization() const {
diff --git a/chromium/cc/layers/picture_layer_impl.cc b/chromium/cc/layers/picture_layer_impl.cc
index 90fdeb1efb4..a550968e69f 100644
--- a/chromium/cc/layers/picture_layer_impl.cc
+++ b/chromium/cc/layers/picture_layer_impl.cc
@@ -18,7 +18,6 @@
#include "cc/layers/append_quads_data.h"
#include "cc/layers/solid_color_layer_impl.h"
#include "cc/output/begin_frame_args.h"
-#include "cc/quads/checkerboard_draw_quad.h"
#include "cc/quads/debug_border_draw_quad.h"
#include "cc/quads/picture_draw_quad.h"
#include "cc/quads/solid_color_draw_quad.h"
@@ -183,14 +182,22 @@ void PictureLayerImpl::AppendQuads(RenderPass* render_pass,
gfx::Rect opaque_rect = contents_opaque() ? geometry_rect : gfx::Rect();
gfx::Rect visible_geometry_rect =
scaled_occlusion.GetUnoccludedContentRect(geometry_rect);
- // TODO(enne): HasRecordings is a workaround for crash in crbug.com/526402.
- // Need proper fix for when recording does not cover visible rect.
- if (visible_geometry_rect.IsEmpty() || !raster_source_->HasRecordings())
+
+ // The raster source may not be valid over the entire visible rect,
+ // and rastering outside of that may cause incorrect pixels.
+ gfx::Rect scaled_recorded_viewport = gfx::ScaleToEnclosingRect(
+ raster_source_->RecordedViewport(), max_contents_scale);
+ geometry_rect.Intersect(scaled_recorded_viewport);
+ opaque_rect.Intersect(scaled_recorded_viewport);
+ visible_geometry_rect.Intersect(scaled_recorded_viewport);
+
+ if (visible_geometry_rect.IsEmpty())
return;
+ DCHECK(raster_source_->HasRecordings());
gfx::Rect quad_content_rect = shared_quad_state->visible_quad_layer_rect;
gfx::Size texture_size = quad_content_rect.size();
- gfx::RectF texture_rect = gfx::RectF(texture_size);
+ gfx::RectF texture_rect = gfx::RectF(gfx::SizeF(texture_size));
PictureDrawQuad* quad =
render_pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
@@ -324,8 +331,11 @@ void PictureLayerImpl::AppendQuads(RenderPass* render_pass,
if (!has_draw_quad) {
// Checkerboard.
- // TODO(danakj): Make this a different color when debugging.
SkColor color = SafeOpaqueBackgroundColor();
+ if (ShowDebugBorders()) {
+ // Fill the whole tile with the missing tile color.
+ color = DebugColors::OOMTileBorderColor();
+ }
SolidColorDrawQuad* quad =
render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
quad->SetNew(shared_quad_state, geometry_rect, visible_geometry_rect,
@@ -336,8 +346,6 @@ void PictureLayerImpl::AppendQuads(RenderPass* render_pass,
append_quads_data->num_missing_tiles++;
++missing_tile_count;
}
- append_quads_data->approximated_visible_content_area +=
- visible_geometry_rect.width() * visible_geometry_rect.height();
append_quads_data->checkerboarded_visible_content_area +=
visible_geometry_rect.width() * visible_geometry_rect.height();
continue;
@@ -405,6 +413,9 @@ bool PictureLayerImpl::UpdateTiles(bool resourceless_software_draw) {
AddTilingsForRasterScale();
}
+ if (layer_tree_impl()->IsActiveTree())
+ AddLowResolutionTilingIfNeeded();
+
DCHECK(raster_page_scale_);
DCHECK(raster_device_scale_);
DCHECK(raster_source_scale_);
@@ -414,7 +425,7 @@ bool PictureLayerImpl::UpdateTiles(bool resourceless_software_draw) {
was_screen_space_transform_animating_ =
draw_properties().screen_space_transform_is_animating;
- if (draw_transform_is_animating())
+ if (screen_space_transform_is_animating())
raster_source_->SetShouldAttemptToUseDistanceFieldText();
double current_frame_time_in_seconds =
@@ -466,9 +477,8 @@ void PictureLayerImpl::UpdateViewportRectForTilePriorityInContentSpace() {
gfx::Transform view_to_layer(gfx::Transform::kSkipInitialization);
if (screen_space_transform().GetInverse(&view_to_layer)) {
// Transform from view space to content space.
- visible_rect_in_content_space =
- gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
- view_to_layer, viewport_rect_for_tile_priority));
+ visible_rect_in_content_space = MathUtil::ProjectEnclosingClippedRect(
+ view_to_layer, viewport_rect_for_tile_priority);
// We have to allow for a viewport that is outside of the layer bounds in
// order to compute tile priorities correctly for offscreen content that
@@ -579,8 +589,8 @@ bool PictureLayerImpl::RasterSourceUsesLCDText() const {
void PictureLayerImpl::NotifyTileStateChanged(const Tile* tile) {
if (layer_tree_impl()->IsActiveTree()) {
- gfx::RectF layer_damage_rect =
- gfx::ScaleRect(tile->content_rect(), 1.f / tile->contents_scale());
+ gfx::Rect layer_damage_rect = gfx::ScaleToEnclosingRect(
+ tile->content_rect(), 1.f / tile->contents_scale());
AddDamageRect(layer_damage_rect);
}
if (tile->draw_info().NeedsRaster()) {
@@ -624,8 +634,7 @@ Region PictureLayerImpl::GetInvalidationRegion() {
return IntersectRegions(invalidation_, update_rect());
}
-ScopedTilePtr PictureLayerImpl::CreateTile(float contents_scale,
- const gfx::Rect& content_rect) {
+ScopedTilePtr PictureLayerImpl::CreateTile(const Tile::CreateInfo& info) {
int flags = 0;
// We don't handle solid color masks, so we shouldn't bother analyzing those.
@@ -633,9 +642,11 @@ ScopedTilePtr PictureLayerImpl::CreateTile(float contents_scale,
if (!is_mask_)
flags = Tile::USE_PICTURE_ANALYSIS;
+ if (contents_opaque())
+ flags |= Tile::IS_OPAQUE;
+
return layer_tree_impl()->tile_manager()->CreateTile(
- content_rect.size(), content_rect, contents_scale, id(),
- layer_tree_impl()->source_frame_number(), flags);
+ info, id(), layer_tree_impl()->source_frame_number(), flags);
}
const Region* PictureLayerImpl::GetPendingInvalidation() {
@@ -695,7 +706,8 @@ gfx::Size PictureLayerImpl::CalculateTileSize(
divisor = 2;
if (content_bounds.width() <= viewport_width / 4)
divisor = 1;
- default_tile_height = MathUtil::RoundUp(viewport_height, divisor) / divisor;
+ default_tile_height =
+ MathUtil::UncheckedRoundUp(viewport_height, divisor) / divisor;
// Grow default sizes to account for overlapping border texels.
default_tile_width += 2 * PictureLayerTiling::kBorderTexels;
@@ -731,12 +743,12 @@ gfx::Size PictureLayerImpl::CalculateTileSize(
// Clamp the tile width/height to the content width/height to save space.
if (content_bounds.width() < default_tile_width) {
tile_width = std::min(tile_width, content_bounds.width());
- tile_width = MathUtil::RoundUp(tile_width, kTileRoundUp);
+ tile_width = MathUtil::UncheckedRoundUp(tile_width, kTileRoundUp);
tile_width = std::min(tile_width, default_tile_width);
}
if (content_bounds.height() < default_tile_height) {
tile_height = std::min(tile_height, content_bounds.height());
- tile_height = MathUtil::RoundUp(tile_height, kTileRoundUp);
+ tile_height = MathUtil::UncheckedRoundUp(tile_height, kTileRoundUp);
tile_height = std::min(tile_height, default_tile_height);
}
@@ -809,31 +821,18 @@ void PictureLayerImpl::AddTilingsForRasterScale() {
PictureLayerTiling* high_res =
tilings_->FindTilingWithScale(raster_contents_scale_);
- // We always need a high res tiling, so create one if it doesn't exist.
- if (!high_res)
+ if (!high_res) {
+ // We always need a high res tiling, so create one if it doesn't exist.
high_res = AddTiling(raster_contents_scale_);
- high_res->set_resolution(HIGH_RESOLUTION);
-
- // If the low res scale is the same as the high res scale, that tiling
- // will be treated as high res.
- if (layer_tree_impl()->create_low_res_tiling() &&
- raster_contents_scale_ != low_res_raster_contents_scale_) {
- PictureLayerTiling* low_res =
- tilings_->FindTilingWithScale(low_res_raster_contents_scale_);
-
- // Only create new low res tilings when the transform is static. This
- // prevents wastefully creating a paired low res tiling for every new high
- // res tiling during a pinch or a CSS animation.
- bool is_pinching = layer_tree_impl()->PinchGestureActive();
- bool is_animating = draw_properties().screen_space_transform_is_animating;
- if (!low_res && !is_pinching && !is_animating)
- low_res = AddTiling(low_res_raster_contents_scale_);
-
- if (low_res) {
- DCHECK_NE(low_res, high_res);
- low_res->set_resolution(LOW_RESOLUTION);
- }
+ } else if (high_res->may_contain_low_resolution_tiles()) {
+ // If the tiling we find here was LOW_RESOLUTION previously, it may not be
+ // fully rastered, so destroy the old tiles.
+ high_res->Reset();
+ // Reset the flag now that we'll make it high res, it will have fully
+ // rastered content.
+ high_res->reset_may_contain_low_resolution_tiles();
}
+ high_res->set_resolution(HIGH_RESOLUTION);
if (layer_tree_impl()->IsPendingTree()) {
// On the pending tree, drop any tilings that are non-ideal since we don't
@@ -890,6 +889,34 @@ bool PictureLayerImpl::ShouldAdjustRasterScale() const {
return false;
}
+void PictureLayerImpl::AddLowResolutionTilingIfNeeded() {
+ DCHECK(layer_tree_impl()->IsActiveTree());
+
+ if (!layer_tree_impl()->create_low_res_tiling())
+ return;
+
+ // We should have a high resolution tiling at raster_contents_scale, so if the
+ // low res one is the same then we shouldn't try to override this tiling by
+ // marking it as a low res.
+ if (raster_contents_scale_ == low_res_raster_contents_scale_)
+ return;
+
+ PictureLayerTiling* low_res =
+ tilings_->FindTilingWithScale(low_res_raster_contents_scale_);
+ DCHECK_IMPLIES(low_res, low_res->resolution() != HIGH_RESOLUTION);
+
+ // Only create new low res tilings when the transform is static. This
+ // prevents wastefully creating a paired low res tiling for every new high
+ // res tiling during a pinch or a CSS animation.
+ bool is_pinching = layer_tree_impl()->PinchGestureActive();
+ bool is_animating = draw_properties().screen_space_transform_is_animating;
+ if (!is_pinching && !is_animating) {
+ if (!low_res)
+ low_res = AddTiling(low_res_raster_contents_scale_);
+ low_res->set_resolution(LOW_RESOLUTION);
+ }
+}
+
void PictureLayerImpl::RecalculateRasterScales() {
float old_raster_contents_scale = raster_contents_scale_;
float old_raster_page_scale = raster_page_scale_;
@@ -953,8 +980,8 @@ void PictureLayerImpl::RecalculateRasterScales() {
float maximum_scale = draw_properties().maximum_animation_contents_scale;
float starting_scale = draw_properties().starting_animation_contents_scale;
if (maximum_scale) {
- gfx::Size bounds_at_maximum_scale = gfx::ToCeiledSize(
- gfx::ScaleSize(raster_source_->GetSize(), maximum_scale));
+ gfx::Size bounds_at_maximum_scale =
+ gfx::ScaleToCeiledSize(raster_source_->GetSize(), maximum_scale);
int64 maximum_area = static_cast<int64>(bounds_at_maximum_scale.width()) *
static_cast<int64>(bounds_at_maximum_scale.height());
gfx::Size viewport = layer_tree_impl()->device_viewport_size();
@@ -964,8 +991,8 @@ void PictureLayerImpl::RecalculateRasterScales() {
can_raster_at_maximum_scale = true;
}
if (starting_scale && starting_scale > maximum_scale) {
- gfx::Size bounds_at_starting_scale = gfx::ToCeiledSize(
- gfx::ScaleSize(raster_source_->GetSize(), starting_scale));
+ gfx::Size bounds_at_starting_scale =
+ gfx::ScaleToCeiledSize(raster_source_->GetSize(), starting_scale);
int64 start_area = static_cast<int64>(bounds_at_starting_scale.width()) *
static_cast<int64>(bounds_at_starting_scale.height());
gfx::Size viewport = layer_tree_impl()->device_viewport_size();
@@ -994,8 +1021,8 @@ void PictureLayerImpl::RecalculateRasterScales() {
// If this layer would create zero or one tiles at this content scale,
// don't create a low res tiling.
- gfx::Size raster_bounds = gfx::ToCeiledSize(
- gfx::ScaleSize(raster_source_->GetSize(), raster_contents_scale_));
+ gfx::Size raster_bounds =
+ gfx::ScaleToCeiledSize(raster_source_->GetSize(), raster_contents_scale_);
gfx::Size tile_size = CalculateTileSize(raster_bounds);
bool tile_covers_bounds = tile_size.width() >= raster_bounds.width() &&
tile_size.height() >= raster_bounds.height();
@@ -1035,9 +1062,9 @@ void PictureLayerImpl::CleanUpTilingsOnActiveLayer(
}
PictureLayerTilingSet* twin_set = twin ? twin->tilings_.get() : nullptr;
- tilings_->CleanUpTilings(
- min_acceptable_high_res_scale, max_acceptable_high_res_scale,
- used_tilings, layer_tree_impl()->create_low_res_tiling(), twin_set);
+ tilings_->CleanUpTilings(min_acceptable_high_res_scale,
+ max_acceptable_high_res_scale, used_tilings,
+ twin_set);
DCHECK_GT(tilings_->num_tilings(), 0u);
SanityCheckTilingState();
}
@@ -1130,7 +1157,7 @@ scoped_ptr<PictureLayerTilingSet>
PictureLayerImpl::CreatePictureLayerTilingSet() {
const LayerTreeSettings& settings = layer_tree_impl()->settings();
return PictureLayerTilingSet::Create(
- GetTree(), this, settings.max_tiles_for_interest_area,
+ GetTree(), this, settings.tiling_interest_area_padding,
layer_tree_impl()->use_gpu_rasterization()
? settings.gpu_rasterization_skewport_target_time_in_seconds
: settings.skewport_target_time_in_seconds,
diff --git a/chromium/cc/layers/picture_layer_impl.h b/chromium/cc/layers/picture_layer_impl.h
index a23dbba61d7..409afaeb9ca 100644
--- a/chromium/cc/layers/picture_layer_impl.h
+++ b/chromium/cc/layers/picture_layer_impl.h
@@ -12,7 +12,6 @@
#include "cc/base/cc_export.h"
#include "cc/base/scoped_ptr_vector.h"
#include "cc/layers/layer_impl.h"
-#include "cc/playback/picture_pile_impl.h"
#include "cc/tiles/picture_layer_tiling.h"
#include "cc/tiles/picture_layer_tiling_set.h"
#include "cc/tiles/tiling_set_eviction_queue.h"
@@ -55,8 +54,7 @@ class CC_EXPORT PictureLayerImpl
Region GetInvalidationRegion() override;
// PictureLayerTilingClient overrides.
- ScopedTilePtr CreateTile(float contents_scale,
- const gfx::Rect& content_rect) override;
+ ScopedTilePtr CreateTile(const Tile::CreateInfo& info) override;
gfx::Size CalculateTileSize(const gfx::Size& content_bounds) const override;
const Region* GetPendingInvalidation() override;
const PictureLayerTiling* GetPendingOrActiveTwinTiling(
@@ -108,6 +106,7 @@ class CC_EXPORT PictureLayerImpl
PictureLayerTiling* AddTiling(float contents_scale);
void RemoveAllTilings();
void AddTilingsForRasterScale();
+ void AddLowResolutionTilingIfNeeded();
virtual bool ShouldAdjustRasterScale() const;
virtual void RecalculateRasterScales();
void CleanUpTilingsOnActiveLayer(
diff --git a/chromium/cc/layers/picture_layer_impl_perftest.cc b/chromium/cc/layers/picture_layer_impl_perftest.cc
index dcbf2fba85f..6c45b095142 100644
--- a/chromium/cc/layers/picture_layer_impl_perftest.cc
+++ b/chromium/cc/layers/picture_layer_impl_perftest.cc
@@ -6,11 +6,11 @@
#include "base/thread_task_runner_handle.h"
#include "cc/debug/lap_timer.h"
+#include "cc/test/fake_display_list_raster_source.h"
#include "cc/test/fake_impl_proxy.h"
#include "cc/test/fake_layer_tree_host_impl.h"
#include "cc/test/fake_output_surface.h"
#include "cc/test/fake_picture_layer_impl.h"
-#include "cc/test/fake_picture_pile_impl.h"
#include "cc/test/test_shared_bitmap_manager.h"
#include "cc/test/test_task_graph_runner.h"
#include "cc/tiles/tiling_set_raster_queue_all.h"
@@ -30,6 +30,7 @@ void AddTiling(float scale,
std::vector<Tile*>* all_tiles) {
PictureLayerTiling* tiling = layer->AddTiling(scale);
+ tiling->set_resolution(HIGH_RESOLUTION);
tiling->CreateAllTilesForTesting();
std::vector<Tile*> tiling_tiles = tiling->AllTilesForTesting();
std::copy(
@@ -40,6 +41,7 @@ class PictureLayerImplPerfTest : public testing::Test {
public:
PictureLayerImplPerfTest()
: proxy_(base::ThreadTaskRunnerHandle::Get()),
+ output_surface_(FakeOutputSurface::Create3d()),
host_impl_(LayerTreeSettings(),
&proxy_,
&shared_bitmap_manager_,
@@ -49,24 +51,25 @@ class PictureLayerImplPerfTest : public testing::Test {
kTimeCheckInterval) {}
void SetUp() override {
- host_impl_.InitializeRenderer(FakeOutputSurface::Create3d());
+ host_impl_.InitializeRenderer(output_surface_.get());
}
- void SetupActiveTree(const gfx::Size& layer_bounds,
- const gfx::Size& tile_size) {
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- LayerTreeImpl* active_tree = host_impl_.active_tree();
- active_tree->DetachLayerTree();
-
- scoped_ptr<FakePictureLayerImpl> active_layer =
- FakePictureLayerImpl::CreateWithRasterSource(active_tree, 7, pile);
- active_layer->SetDrawsContent(true);
- active_layer->SetHasRenderSurface(true);
- active_tree->SetRootLayer(active_layer.Pass());
-
- active_layer_ = static_cast<FakePictureLayerImpl*>(
- host_impl_.active_tree()->LayerById(7));
+ void SetupPendingTree(const gfx::Size& layer_bounds) {
+ scoped_refptr<FakeDisplayListRasterSource> raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
+ host_impl_.CreatePendingTree();
+ LayerTreeImpl* pending_tree = host_impl_.pending_tree();
+ pending_tree->DetachLayerTree();
+
+ scoped_ptr<FakePictureLayerImpl> pending_layer =
+ FakePictureLayerImpl::CreateWithRasterSource(pending_tree, 7,
+ raster_source);
+ pending_layer->SetDrawsContent(true);
+ pending_layer->SetHasRenderSurface(true);
+ pending_tree->SetRootLayer(pending_layer.Pass());
+
+ pending_layer_ = static_cast<FakePictureLayerImpl*>(
+ host_impl_.pending_tree()->LayerById(7));
}
void RunRasterQueueConstructAndIterateTest(const std::string& test_name,
@@ -74,13 +77,13 @@ class PictureLayerImplPerfTest : public testing::Test {
const gfx::Size& viewport_size) {
host_impl_.SetViewportSize(viewport_size);
bool update_lcd_text = false;
- host_impl_.active_tree()->UpdateDrawProperties(update_lcd_text);
+ host_impl_.pending_tree()->UpdateDrawProperties(update_lcd_text);
timer_.Reset();
do {
int count = num_tiles;
scoped_ptr<TilingSetRasterQueueAll> queue(new TilingSetRasterQueueAll(
- active_layer_->picture_layer_tiling_set(), false));
+ pending_layer_->picture_layer_tiling_set(), false));
while (count--) {
ASSERT_TRUE(!queue->IsEmpty()) << "count: " << count;
ASSERT_TRUE(queue->Top().tile()) << "count: " << count;
@@ -96,15 +99,15 @@ class PictureLayerImplPerfTest : public testing::Test {
void RunRasterQueueConstructTest(const std::string& test_name,
const gfx::Rect& viewport) {
host_impl_.SetViewportSize(viewport.size());
- active_layer_->PushScrollOffsetFromMainThreadAndClobberActiveValue(
+ pending_layer_->PushScrollOffsetFromMainThread(
gfx::ScrollOffset(viewport.x(), viewport.y()));
bool update_lcd_text = false;
- host_impl_.active_tree()->UpdateDrawProperties(update_lcd_text);
+ host_impl_.pending_tree()->UpdateDrawProperties(update_lcd_text);
timer_.Reset();
do {
scoped_ptr<TilingSetRasterQueueAll> queue(new TilingSetRasterQueueAll(
- active_layer_->picture_layer_tiling_set(), false));
+ pending_layer_->picture_layer_tiling_set(), false));
timer_.NextLap();
} while (!timer_.HasTimeLimitExpired());
@@ -117,15 +120,14 @@ class PictureLayerImplPerfTest : public testing::Test {
int num_tiles,
const gfx::Size& viewport_size) {
host_impl_.SetViewportSize(viewport_size);
- active_layer_->MarkAllTilingsUsed();
bool update_lcd_text = false;
- host_impl_.active_tree()->UpdateDrawProperties(update_lcd_text);
+ host_impl_.pending_tree()->UpdateDrawProperties(update_lcd_text);
timer_.Reset();
do {
int count = num_tiles;
scoped_ptr<TilingSetEvictionQueue> queue(new TilingSetEvictionQueue(
- active_layer_->picture_layer_tiling_set()));
+ pending_layer_->picture_layer_tiling_set()));
while (count--) {
ASSERT_TRUE(!queue->IsEmpty()) << "count: " << count;
ASSERT_TRUE(queue->Top().tile()) << "count: " << count;
@@ -142,16 +144,15 @@ class PictureLayerImplPerfTest : public testing::Test {
void RunEvictionQueueConstructTest(const std::string& test_name,
const gfx::Rect& viewport) {
host_impl_.SetViewportSize(viewport.size());
- active_layer_->PushScrollOffsetFromMainThreadAndClobberActiveValue(
+ pending_layer_->PushScrollOffsetFromMainThread(
gfx::ScrollOffset(viewport.x(), viewport.y()));
- active_layer_->MarkAllTilingsUsed();
bool update_lcd_text = false;
- host_impl_.active_tree()->UpdateDrawProperties(update_lcd_text);
+ host_impl_.pending_tree()->UpdateDrawProperties(update_lcd_text);
timer_.Reset();
do {
scoped_ptr<TilingSetEvictionQueue> queue(new TilingSetEvictionQueue(
- active_layer_->picture_layer_tiling_set()));
+ pending_layer_->picture_layer_tiling_set()));
timer_.NextLap();
} while (!timer_.HasTimeLimitExpired());
@@ -163,8 +164,9 @@ class PictureLayerImplPerfTest : public testing::Test {
TestSharedBitmapManager shared_bitmap_manager_;
TestTaskGraphRunner task_graph_runner_;
FakeImplProxy proxy_;
+ scoped_ptr<OutputSurface> output_surface_;
FakeLayerTreeHostImpl host_impl_;
- FakePictureLayerImpl* active_layer_;
+ FakePictureLayerImpl* pending_layer_;
LapTimer timer_;
private:
@@ -172,15 +174,15 @@ class PictureLayerImplPerfTest : public testing::Test {
};
TEST_F(PictureLayerImplPerfTest, TilingSetRasterQueueConstructAndIterate) {
- SetupActiveTree(gfx::Size(10000, 10000), gfx::Size(256, 256));
+ SetupPendingTree(gfx::Size(10000, 10000));
float low_res_factor = host_impl_.settings().low_res_contents_scale_factor;
- active_layer_->AddTiling(low_res_factor);
- active_layer_->AddTiling(0.3f);
- active_layer_->AddTiling(0.7f);
- active_layer_->AddTiling(1.0f);
- active_layer_->AddTiling(2.0f);
+ pending_layer_->AddTiling(low_res_factor);
+ pending_layer_->AddTiling(0.3f);
+ pending_layer_->AddTiling(0.7f);
+ pending_layer_->AddTiling(1.0f);
+ pending_layer_->AddTiling(2.0f);
RunRasterQueueConstructAndIterateTest("32_100x100", 32, gfx::Size(100, 100));
RunRasterQueueConstructAndIterateTest("32_500x500", 32, gfx::Size(500, 500));
@@ -189,15 +191,15 @@ TEST_F(PictureLayerImplPerfTest, TilingSetRasterQueueConstructAndIterate) {
}
TEST_F(PictureLayerImplPerfTest, TilingSetRasterQueueConstruct) {
- SetupActiveTree(gfx::Size(10000, 10000), gfx::Size(256, 256));
+ SetupPendingTree(gfx::Size(10000, 10000));
float low_res_factor = host_impl_.settings().low_res_contents_scale_factor;
- active_layer_->AddTiling(low_res_factor);
- active_layer_->AddTiling(0.3f);
- active_layer_->AddTiling(0.7f);
- active_layer_->AddTiling(1.0f);
- active_layer_->AddTiling(2.0f);
+ pending_layer_->AddTiling(low_res_factor);
+ pending_layer_->AddTiling(0.3f);
+ pending_layer_->AddTiling(0.7f);
+ pending_layer_->AddTiling(1.0f);
+ pending_layer_->AddTiling(2.0f);
RunRasterQueueConstructTest("0_0_100x100", gfx::Rect(0, 0, 100, 100));
RunRasterQueueConstructTest("5000_0_100x100", gfx::Rect(5000, 0, 100, 100));
@@ -205,16 +207,16 @@ TEST_F(PictureLayerImplPerfTest, TilingSetRasterQueueConstruct) {
}
TEST_F(PictureLayerImplPerfTest, TilingSetEvictionQueueConstructAndIterate) {
- SetupActiveTree(gfx::Size(10000, 10000), gfx::Size(256, 256));
+ SetupPendingTree(gfx::Size(10000, 10000));
float low_res_factor = host_impl_.settings().low_res_contents_scale_factor;
std::vector<Tile*> all_tiles;
- AddTiling(low_res_factor, active_layer_, &all_tiles);
- AddTiling(0.3f, active_layer_, &all_tiles);
- AddTiling(0.7f, active_layer_, &all_tiles);
- AddTiling(1.0f, active_layer_, &all_tiles);
- AddTiling(2.0f, active_layer_, &all_tiles);
+ AddTiling(low_res_factor, pending_layer_, &all_tiles);
+ AddTiling(0.3f, pending_layer_, &all_tiles);
+ AddTiling(0.7f, pending_layer_, &all_tiles);
+ AddTiling(1.0f, pending_layer_, &all_tiles);
+ AddTiling(2.0f, pending_layer_, &all_tiles);
ASSERT_TRUE(host_impl_.tile_manager() != nullptr);
host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting(all_tiles);
@@ -230,16 +232,16 @@ TEST_F(PictureLayerImplPerfTest, TilingSetEvictionQueueConstructAndIterate) {
}
TEST_F(PictureLayerImplPerfTest, TilingSetEvictionQueueConstruct) {
- SetupActiveTree(gfx::Size(10000, 10000), gfx::Size(256, 256));
+ SetupPendingTree(gfx::Size(10000, 10000));
float low_res_factor = host_impl_.settings().low_res_contents_scale_factor;
std::vector<Tile*> all_tiles;
- AddTiling(low_res_factor, active_layer_, &all_tiles);
- AddTiling(0.3f, active_layer_, &all_tiles);
- AddTiling(0.7f, active_layer_, &all_tiles);
- AddTiling(1.0f, active_layer_, &all_tiles);
- AddTiling(2.0f, active_layer_, &all_tiles);
+ AddTiling(low_res_factor, pending_layer_, &all_tiles);
+ AddTiling(0.3f, pending_layer_, &all_tiles);
+ AddTiling(0.7f, pending_layer_, &all_tiles);
+ AddTiling(1.0f, pending_layer_, &all_tiles);
+ AddTiling(2.0f, pending_layer_, &all_tiles);
ASSERT_TRUE(host_impl_.tile_manager() != nullptr);
host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting(all_tiles);
diff --git a/chromium/cc/layers/picture_layer_impl_unittest.cc b/chromium/cc/layers/picture_layer_impl_unittest.cc
index 6e89caa802a..78f56fd90f5 100644
--- a/chromium/cc/layers/picture_layer_impl_unittest.cc
+++ b/chromium/cc/layers/picture_layer_impl_unittest.cc
@@ -18,11 +18,12 @@
#include "cc/quads/tile_draw_quad.h"
#include "cc/test/begin_frame_args_test.h"
#include "cc/test/fake_content_layer_client.h"
+#include "cc/test/fake_display_list_raster_source.h"
+#include "cc/test/fake_display_list_recording_source.h"
#include "cc/test/fake_impl_proxy.h"
#include "cc/test/fake_layer_tree_host_impl.h"
#include "cc/test/fake_output_surface.h"
#include "cc/test/fake_picture_layer_impl.h"
-#include "cc/test/fake_picture_pile_impl.h"
#include "cc/test/geometry_test_utils.h"
#include "cc/test/gpu_rasterization_enabled_settings.h"
#include "cc/test/layer_test_common.h"
@@ -51,6 +52,18 @@ namespace {
EXPECT_NE(x, active_layer_->expression); \
} while (false)
+#define EXPECT_BOTH_TRUE(expression) \
+ do { \
+ EXPECT_TRUE(pending_layer_->expression); \
+ EXPECT_TRUE(active_layer_->expression); \
+ } while (false)
+
+#define EXPECT_BOTH_FALSE(expression) \
+ do { \
+ EXPECT_FALSE(pending_layer_->expression); \
+ EXPECT_FALSE(active_layer_->expression); \
+ } while (false)
+
class MockCanvas : public SkCanvas {
public:
explicit MockCanvas(int w, int h) : SkCanvas(w, h) {}
@@ -81,6 +94,7 @@ class PictureLayerImplTest : public testing::Test {
public:
PictureLayerImplTest()
: proxy_(base::ThreadTaskRunnerHandle::Get()),
+ output_surface_(FakeOutputSurface::Create3d()),
host_impl_(LowResTilingsSettings(),
&proxy_,
&shared_bitmap_manager_,
@@ -95,6 +109,7 @@ class PictureLayerImplTest : public testing::Test {
explicit PictureLayerImplTest(const LayerTreeSettings& settings)
: proxy_(base::ThreadTaskRunnerHandle::Get()),
+ output_surface_(FakeOutputSurface::Create3d()),
host_impl_(settings,
&proxy_,
&shared_bitmap_manager_,
@@ -109,30 +124,27 @@ class PictureLayerImplTest : public testing::Test {
void SetUp() override { InitializeRenderer(); }
virtual void InitializeRenderer() {
- host_impl_.InitializeRenderer(FakeOutputSurface::Create3d());
+ host_impl_.InitializeRenderer(output_surface_.get());
}
void SetupDefaultTrees(const gfx::Size& layer_bounds) {
- gfx::Size tile_size(100, 100);
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> active_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
-
- SetupTrees(pending_pile, active_pile);
+ SetupTrees(pending_raster_source, active_raster_source);
}
void SetupDefaultTreesWithInvalidation(const gfx::Size& layer_bounds,
const Region& invalidation) {
- gfx::Size tile_size(100, 100);
-
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> active_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
- SetupTreesWithInvalidation(pending_pile, active_pile, invalidation);
+ SetupTreesWithInvalidation(pending_raster_source, active_raster_source,
+ invalidation);
}
void ActivateTree() {
@@ -151,40 +163,41 @@ class PictureLayerImplTest : public testing::Test {
void SetupDefaultTreesWithFixedTileSize(const gfx::Size& layer_bounds,
const gfx::Size& tile_size,
const Region& invalidation) {
- gfx::Size pile_tile_size(100, 100);
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> active_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(pile_tile_size, layer_bounds);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateFilledPile(pile_tile_size, layer_bounds);
-
- SetupTreesWithFixedTileSize(pending_pile, active_pile, tile_size,
- invalidation);
+ SetupTreesWithFixedTileSize(pending_raster_source, active_raster_source,
+ tile_size, invalidation);
}
- void SetupTrees(
- scoped_refptr<PicturePileImpl> pending_pile,
- scoped_refptr<PicturePileImpl> active_pile) {
- SetupPendingTree(active_pile);
+ void SetupTrees(scoped_refptr<RasterSource> pending_raster_source,
+ scoped_refptr<RasterSource> active_raster_source) {
+ SetupPendingTree(active_raster_source);
ActivateTree();
- SetupPendingTreeInternal(pending_pile, gfx::Size(), Region());
+ SetupPendingTreeInternal(pending_raster_source, gfx::Size(), Region());
}
- void SetupTreesWithInvalidation(scoped_refptr<PicturePileImpl> pending_pile,
- scoped_refptr<PicturePileImpl> active_pile,
- const Region& pending_invalidation) {
- SetupPendingTreeInternal(active_pile, gfx::Size(), Region());
+ void SetupTreesWithInvalidation(
+ scoped_refptr<RasterSource> pending_raster_source,
+ scoped_refptr<RasterSource> active_raster_source,
+ const Region& pending_invalidation) {
+ SetupPendingTreeInternal(active_raster_source, gfx::Size(), Region());
ActivateTree();
- SetupPendingTreeInternal(pending_pile, gfx::Size(), pending_invalidation);
+ SetupPendingTreeInternal(pending_raster_source, gfx::Size(),
+ pending_invalidation);
}
- void SetupTreesWithFixedTileSize(scoped_refptr<PicturePileImpl> pending_pile,
- scoped_refptr<PicturePileImpl> active_pile,
- const gfx::Size& tile_size,
- const Region& pending_invalidation) {
- SetupPendingTreeInternal(active_pile, tile_size, Region());
+ void SetupTreesWithFixedTileSize(
+ scoped_refptr<RasterSource> pending_raster_source,
+ scoped_refptr<RasterSource> active_raster_source,
+ const gfx::Size& tile_size,
+ const Region& pending_invalidation) {
+ SetupPendingTreeInternal(active_raster_source, tile_size, Region());
ActivateTree();
- SetupPendingTreeInternal(pending_pile, tile_size, pending_invalidation);
+ SetupPendingTreeInternal(pending_raster_source, tile_size,
+ pending_invalidation);
}
void SetupPendingTree(scoped_refptr<RasterSource> raster_source) {
@@ -211,6 +224,8 @@ class PictureLayerImplTest : public testing::Test {
host_impl_.pending_tree()->PushPageScaleFromMainThread(1.f, 0.00001f,
100000.f);
LayerTreeImpl* pending_tree = host_impl_.pending_tree();
+ pending_tree->SetDeviceScaleFactor(
+ host_impl_.active_tree()->device_scale_factor());
// Steal from the recycled tree if possible.
scoped_ptr<LayerImpl> pending_root = pending_tree->DetachLayerTree();
@@ -229,7 +244,7 @@ class PictureLayerImplTest : public testing::Test {
pending_layer->set_fixed_tile_size(tile_size);
}
pending_root->SetHasRenderSurface(true);
- // The bounds() just mirror the pile size.
+ // The bounds() just mirror the raster source size.
pending_layer->SetBounds(raster_source->GetSize());
pending_layer->SetRasterSourceOnPending(raster_source, invalidation);
@@ -252,8 +267,8 @@ class PictureLayerImplTest : public testing::Test {
float maximum_animation_contents_scale,
float starting_animation_contents_scale,
bool animating_transform_to_screen) {
- host_impl_.SetDeviceScaleFactor(device_scale_factor);
- host_impl_.SetPageScaleOnActiveTree(page_scale_factor);
+ layer->layer_tree_impl()->SetDeviceScaleFactor(device_scale_factor);
+ host_impl_.active_tree()->SetPageScaleOnActiveTree(page_scale_factor);
gfx::Transform scale_transform;
scale_transform.Scale(ideal_contents_scale, ideal_contents_scale);
@@ -268,9 +283,9 @@ class PictureLayerImplTest : public testing::Test {
bool resourceless_software_draw = false;
layer->UpdateTiles(resourceless_software_draw);
}
- static void VerifyAllPrioritizedTilesExistAndHavePile(
+ static void VerifyAllPrioritizedTilesExistAndHaveRasterSource(
const PictureLayerTiling* tiling,
- PicturePileImpl* pile) {
+ RasterSource* raster_source) {
auto prioritized_tiles =
tiling->UpdateAndGetAllPrioritizedTilesForTesting();
for (PictureLayerTiling::CoverageIterator iter(
@@ -280,7 +295,7 @@ class PictureLayerImplTest : public testing::Test {
iter;
++iter) {
EXPECT_TRUE(*iter);
- EXPECT_EQ(pile, prioritized_tiles[*iter].raster_source());
+ EXPECT_EQ(raster_source, prioritized_tiles[*iter].raster_source());
}
}
@@ -341,12 +356,23 @@ class PictureLayerImplTest : public testing::Test {
EXPECT_GT(tiles.size(), 0u);
}
+ void SetInitialDeviceScaleFactor(float device_scale_factor) {
+ // Device scale factor is a per-tree property. However, tests can't directly
+ // set the pending tree's device scale factor before the pending tree is
+ // created, and setting it after SetupPendingTreeInternal is too late, since
+ // draw properties will already have been updated on the tree. To handle
+ // this, we initially set only the active tree's device scale factor, and we
+ // copy this over to the pending tree inside SetupPendingTreeInternal.
+ host_impl_.active_tree()->SetDeviceScaleFactor(device_scale_factor);
+ }
+
protected:
void TestQuadsForSolidColor(bool test_for_solid);
FakeImplProxy proxy_;
TestSharedBitmapManager shared_bitmap_manager_;
TestTaskGraphRunner task_graph_runner_;
+ scoped_ptr<OutputSurface> output_surface_;
FakeLayerTreeHostImpl host_impl_;
int root_id_;
int id_;
@@ -371,41 +397,49 @@ TEST_F(PictureLayerImplTest, TileGridAlignment) {
gfx::Size layer_size(settings.default_tile_size.width() * 7 / 2,
settings.default_tile_size.height() * 7 / 2);
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(layer_size, layer_size);
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_size);
- scoped_ptr<FakePicturePile> active_recording =
- FakePicturePile::CreateFilledPile(layer_size, layer_size);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateFromPile(active_recording.get(), nullptr);
+ // Create an active recording source, but make sure it's not solid.
+ scoped_ptr<FakeDisplayListRecordingSource> active_recording_source =
+ FakeDisplayListRecordingSource::CreateFilledRecordingSource(layer_size);
+ active_recording_source->add_draw_rect(gfx::Rect(layer_size));
+ active_recording_source->add_draw_rect(
+ gfx::Rect(0, 0, layer_size.width() - 1, layer_size.height() - 1));
+ active_recording_source->Rerecord();
+ scoped_refptr<FakeDisplayListRasterSource> active_raster_source =
+ FakeDisplayListRasterSource::CreateFromRecordingSource(
+ active_recording_source.get(), false);
- SetupTrees(pending_pile, active_pile);
+ SetupTrees(pending_raster_source, active_raster_source);
- // Add 1x1 rects at the centers of each tile, then re-record pile contents
+ // Add 1x1 rects at the centers of each tile, then re-record recording source
+ // contents.
active_layer_->tilings()->tiling_at(0)->CreateAllTilesForTesting();
std::vector<Tile*> tiles =
active_layer_->tilings()->tiling_at(0)->AllTilesForTesting();
EXPECT_EQ(16u, tiles.size());
std::vector<SkRect> rects;
std::vector<Tile*>::const_iterator tile_iter;
+ active_recording_source->reset_draws();
for (tile_iter = tiles.begin(); tile_iter < tiles.end(); tile_iter++) {
gfx::Point tile_center = (*tile_iter)->content_rect().CenterPoint();
gfx::Rect rect(tile_center.x(), tile_center.y(), 1, 1);
- active_recording->add_draw_rect(rect);
+ active_recording_source->add_draw_rect(rect);
rects.push_back(SkRect::MakeXYWH(rect.x(), rect.y(), 1, 1));
}
// Force re-raster with newly injected content
- active_recording->RemoveRecordingAt(0, 0);
- active_recording->AddRecordingAt(0, 0);
+ active_recording_source->Rerecord();
- scoped_refptr<FakePicturePileImpl> updated_active_pile =
- FakePicturePileImpl::CreateFromPile(active_recording.get(), nullptr);
+ scoped_refptr<FakeDisplayListRasterSource> updated_active_raster_source =
+ FakeDisplayListRasterSource::CreateFromRecordingSource(
+ active_recording_source.get(), false);
std::vector<SkRect>::const_iterator rect_iter = rects.begin();
for (tile_iter = tiles.begin(); tile_iter < tiles.end(); tile_iter++) {
MockCanvas mock_canvas(1000, 1000);
- updated_active_pile->PlaybackToSharedCanvas(
+ updated_active_raster_source->PlaybackToSharedCanvas(
&mock_canvas, (*tile_iter)->content_rect(), 1.0f);
// This test verifies that when drawing the contents of a specific tile
@@ -419,15 +453,8 @@ TEST_F(PictureLayerImplTest, TileGridAlignment) {
}
TEST_F(PictureLayerImplTest, CloneNoInvalidation) {
- gfx::Size tile_size(100, 100);
gfx::Size layer_bounds(400, 400);
-
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
-
- SetupTreesWithInvalidation(pending_pile, active_pile, Region());
+ SetupDefaultTrees(layer_bounds);
EXPECT_EQ(pending_layer_->tilings()->num_tilings(),
active_layer_->tilings()->num_tilings());
@@ -440,15 +467,8 @@ TEST_F(PictureLayerImplTest, CloneNoInvalidation) {
TEST_F(PictureLayerImplTest, ExternalViewportRectForPrioritizingTiles) {
host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));
- gfx::Size tile_size(100, 100);
gfx::Size layer_bounds(400, 400);
-
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
-
- SetupTreesWithInvalidation(pending_pile, active_pile, Region());
+ SetupDefaultTrees(layer_bounds);
SetupDrawPropertiesAndUpdateTiles(active_layer_, 1.f, 1.f, 1.f, 1.f, 0.f,
false);
@@ -512,8 +532,8 @@ TEST_F(PictureLayerImplTest, ExternalViewportRectForPrioritizingTiles) {
// bounds, then tile priorities will end up being incorrect in cases of fully
// offscreen layer.
viewport_rect_for_tile_priority_in_view_space =
- gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
- screen_to_view, viewport_rect_for_tile_priority));
+ MathUtil::ProjectEnclosingClippedRect(screen_to_view,
+ viewport_rect_for_tile_priority);
EXPECT_EQ(viewport_rect_for_tile_priority_in_view_space,
active_layer_->viewport_rect_for_tile_priority_in_content_space());
@@ -529,16 +549,8 @@ TEST_F(PictureLayerImplTest, ExternalViewportRectForPrioritizingTiles) {
TEST_F(PictureLayerImplTest, InvalidViewportForPrioritizingTiles) {
host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));
-
- gfx::Size tile_size(100, 100);
gfx::Size layer_bounds(400, 400);
-
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
-
- SetupTreesWithInvalidation(pending_pile, active_pile, Region());
+ SetupDefaultTrees(layer_bounds);
SetupDrawPropertiesAndUpdateTiles(active_layer_, 1.f, 1.f, 1.f, 1.f, 0.f,
false);
@@ -606,15 +618,8 @@ TEST_F(PictureLayerImplTest, InvalidViewportForPrioritizingTiles) {
TEST_F(PictureLayerImplTest, ViewportRectForTilePriorityIsCached) {
host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));
- gfx::Size tile_size(100, 100);
gfx::Size layer_bounds(400, 400);
-
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
-
- SetupTreesWithInvalidation(pending_pile, active_pile, Region());
+ SetupDefaultTrees(layer_bounds);
SetupDrawPropertiesAndUpdateTiles(active_layer_, 1.f, 1.f, 1.f, 1.f, 0.f,
false);
@@ -655,31 +660,32 @@ TEST_F(PictureLayerImplTest, ViewportRectForTilePriorityIsCached) {
}
TEST_F(PictureLayerImplTest, ClonePartialInvalidation) {
- gfx::Size tile_size(100, 100);
gfx::Size layer_bounds(400, 400);
gfx::Rect layer_invalidation(150, 200, 30, 180);
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- scoped_refptr<FakePicturePileImpl> lost_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> active_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> lost_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
- SetupPendingTreeWithFixedTileSize(lost_pile, gfx::Size(50, 50), Region());
+ SetupPendingTreeWithFixedTileSize(lost_raster_source, gfx::Size(50, 50),
+ Region());
ActivateTree();
// Add a unique tiling on the active tree.
PictureLayerTiling* tiling = active_layer_->AddTiling(3.f);
+ tiling->set_resolution(HIGH_RESOLUTION);
tiling->CreateAllTilesForTesting();
// Ensure UpdateTiles won't remove any tilings.
active_layer_->MarkAllTilingsUsed();
// Then setup a new pending tree and activate it.
- SetupTreesWithFixedTileSize(pending_pile, active_pile, gfx::Size(50, 50),
- layer_invalidation);
+ SetupTreesWithFixedTileSize(pending_raster_source, active_raster_source,
+ gfx::Size(50, 50), layer_invalidation);
- EXPECT_EQ(2u, pending_layer_->num_tilings());
+ EXPECT_EQ(1u, pending_layer_->num_tilings());
EXPECT_EQ(3u, active_layer_->num_tilings());
const PictureLayerTilingSet* tilings = pending_layer_->tilings();
@@ -701,7 +707,8 @@ TEST_F(PictureLayerImplTest, ClonePartialInvalidation) {
// invalidated and it has the latest raster source.
if (*iter) {
EXPECT_FALSE(iter.geometry_rect().IsEmpty());
- EXPECT_EQ(pending_pile.get(), prioritized_tiles[*iter].raster_source());
+ EXPECT_EQ(pending_raster_source.get(),
+ prioritized_tiles[*iter].raster_source());
EXPECT_TRUE(iter.geometry_rect().Intersects(content_invalidation));
} else {
// We don't create tiles in non-invalidated regions.
@@ -726,22 +733,22 @@ TEST_F(PictureLayerImplTest, ClonePartialInvalidation) {
++iter) {
EXPECT_TRUE(*iter);
EXPECT_FALSE(iter.geometry_rect().IsEmpty());
- // Pile will be updated upon activation.
- EXPECT_EQ(active_pile.get(), prioritized_tiles[*iter].raster_source());
+ // Raster source will be updated upon activation.
+ EXPECT_EQ(active_raster_source.get(),
+ prioritized_tiles[*iter].raster_source());
}
}
}
TEST_F(PictureLayerImplTest, CloneFullInvalidation) {
- gfx::Size tile_size(90, 80);
gfx::Size layer_bounds(300, 500);
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> active_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
- SetupTreesWithInvalidation(pending_pile, active_pile,
+ SetupTreesWithInvalidation(pending_raster_source, active_raster_source,
gfx::Rect(layer_bounds));
EXPECT_EQ(pending_layer_->tilings()->num_tilings(),
@@ -749,21 +756,15 @@ TEST_F(PictureLayerImplTest, CloneFullInvalidation) {
const PictureLayerTilingSet* tilings = pending_layer_->tilings();
EXPECT_GT(tilings->num_tilings(), 0u);
- for (size_t i = 0; i < tilings->num_tilings(); ++i)
- VerifyAllPrioritizedTilesExistAndHavePile(tilings->tiling_at(i),
- pending_pile.get());
+ for (size_t i = 0; i < tilings->num_tilings(); ++i) {
+ VerifyAllPrioritizedTilesExistAndHaveRasterSource(
+ tilings->tiling_at(i), pending_raster_source.get());
+ }
}
TEST_F(PictureLayerImplTest, UpdateTilesCreatesTilings) {
- gfx::Size tile_size(400, 400);
gfx::Size layer_bounds(1300, 1900);
-
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
-
- SetupTrees(pending_pile, active_pile);
+ SetupDefaultTrees(layer_bounds);
float low_res_factor = host_impl_.settings().low_res_contents_scale_factor;
EXPECT_LT(low_res_factor, 1.f);
@@ -830,16 +831,9 @@ TEST_F(PictureLayerImplTest, UpdateTilesCreatesTilings) {
active_layer_->tilings()->tiling_at(3)->contents_scale());
}
-TEST_F(PictureLayerImplTest, PendingLayerOnlyHasHighAndLowResTiling) {
- gfx::Size tile_size(400, 400);
+TEST_F(PictureLayerImplTest, PendingLayerOnlyHasHighResTiling) {
gfx::Size layer_bounds(1300, 1900);
-
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
-
- SetupTrees(pending_pile, active_pile);
+ SetupDefaultTrees(layer_bounds);
float low_res_factor = host_impl_.settings().low_res_contents_scale_factor;
EXPECT_LT(low_res_factor, 1.f);
@@ -856,11 +850,9 @@ TEST_F(PictureLayerImplTest, PendingLayerOnlyHasHighAndLowResTiling) {
1.f, // maximum animation scale
0.f, // starting animation scale
false);
- ASSERT_EQ(2u, pending_layer_->tilings()->num_tilings());
+ ASSERT_EQ(1u, pending_layer_->tilings()->num_tilings());
EXPECT_FLOAT_EQ(6.f,
pending_layer_->tilings()->tiling_at(0)->contents_scale());
- EXPECT_FLOAT_EQ(6.f * low_res_factor,
- pending_layer_->tilings()->tiling_at(1)->contents_scale());
// If we change the page scale factor, then we should get new tilings.
SetupDrawPropertiesAndUpdateTiles(pending_layer_,
@@ -870,11 +862,9 @@ TEST_F(PictureLayerImplTest, PendingLayerOnlyHasHighAndLowResTiling) {
1.f, // maximum animation scale
0.f, // starting animation scale
false);
- ASSERT_EQ(2u, pending_layer_->tilings()->num_tilings());
+ ASSERT_EQ(1u, pending_layer_->tilings()->num_tilings());
EXPECT_FLOAT_EQ(6.6f,
pending_layer_->tilings()->tiling_at(0)->contents_scale());
- EXPECT_FLOAT_EQ(6.6f * low_res_factor,
- pending_layer_->tilings()->tiling_at(1)->contents_scale());
// If we change the device scale factor, then we should get new tilings.
SetupDrawPropertiesAndUpdateTiles(pending_layer_,
@@ -884,11 +874,9 @@ TEST_F(PictureLayerImplTest, PendingLayerOnlyHasHighAndLowResTiling) {
1.f, // maximum animation scale
0.f, // starting animation scale
false);
- ASSERT_EQ(2u, pending_layer_->tilings()->num_tilings());
+ ASSERT_EQ(1u, pending_layer_->tilings()->num_tilings());
EXPECT_FLOAT_EQ(7.26f,
pending_layer_->tilings()->tiling_at(0)->contents_scale());
- EXPECT_FLOAT_EQ(7.26f * low_res_factor,
- pending_layer_->tilings()->tiling_at(1)->contents_scale());
// If we change the device scale factor, but end up at the same total scale
// factor somehow, then we don't get new tilings.
@@ -899,30 +887,27 @@ TEST_F(PictureLayerImplTest, PendingLayerOnlyHasHighAndLowResTiling) {
1.f, // maximum animation scale
0.f, // starting animation scale
false);
- ASSERT_EQ(2u, pending_layer_->tilings()->num_tilings());
+ ASSERT_EQ(1u, pending_layer_->tilings()->num_tilings());
EXPECT_FLOAT_EQ(7.26f,
pending_layer_->tilings()->tiling_at(0)->contents_scale());
- EXPECT_FLOAT_EQ(7.26f * low_res_factor,
- pending_layer_->tilings()->tiling_at(1)->contents_scale());
}
TEST_F(PictureLayerImplTest, CreateTilingsEvenIfTwinHasNone) {
// This test makes sure that if a layer can have tilings, then a commit makes
// it not able to have tilings (empty size), and then a future commit that
// makes it valid again should be able to create tilings.
- gfx::Size tile_size(400, 400);
gfx::Size layer_bounds(1300, 1900);
- scoped_refptr<FakePicturePileImpl> empty_pile =
- FakePicturePileImpl::CreateEmptyPile(tile_size, layer_bounds);
- scoped_refptr<FakePicturePileImpl> valid_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> empty_raster_source =
+ FakeDisplayListRasterSource::CreateEmpty(layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> valid_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
- SetupPendingTree(valid_pile);
- ASSERT_EQ(2u, pending_layer_->tilings()->num_tilings());
+ SetupPendingTree(valid_raster_source);
+ ASSERT_EQ(1u, pending_layer_->tilings()->num_tilings());
ActivateTree();
- SetupPendingTree(empty_pile);
+ SetupPendingTree(empty_raster_source);
EXPECT_FALSE(pending_layer_->CanHaveTilings());
ASSERT_EQ(2u, active_layer_->tilings()->num_tilings());
ASSERT_EQ(0u, pending_layer_->tilings()->num_tilings());
@@ -931,22 +916,43 @@ TEST_F(PictureLayerImplTest, CreateTilingsEvenIfTwinHasNone) {
EXPECT_FALSE(active_layer_->CanHaveTilings());
ASSERT_EQ(0u, active_layer_->tilings()->num_tilings());
- SetupPendingTree(valid_pile);
- ASSERT_EQ(2u, pending_layer_->tilings()->num_tilings());
+ SetupPendingTree(valid_raster_source);
+ ASSERT_EQ(1u, pending_layer_->tilings()->num_tilings());
ASSERT_EQ(0u, active_layer_->tilings()->num_tilings());
}
+TEST_F(PictureLayerImplTest, LowResTilingStaysOnActiveTree) {
+ gfx::Size layer_bounds(1300, 1900);
+
+ scoped_refptr<FakeDisplayListRasterSource> valid_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> other_valid_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
+
+ SetupPendingTree(valid_raster_source);
+ ASSERT_EQ(1u, pending_layer_->tilings()->num_tilings());
+
+ ActivateTree();
+ SetupPendingTree(other_valid_raster_source);
+ ASSERT_EQ(2u, active_layer_->tilings()->num_tilings());
+ ASSERT_EQ(1u, pending_layer_->tilings()->num_tilings());
+ auto* low_res_tiling =
+ active_layer_->tilings()->FindTilingWithResolution(LOW_RESOLUTION);
+ EXPECT_TRUE(low_res_tiling);
+
+ ActivateTree();
+ ASSERT_EQ(2u, active_layer_->tilings()->num_tilings());
+ auto* other_low_res_tiling =
+ active_layer_->tilings()->FindTilingWithResolution(LOW_RESOLUTION);
+ EXPECT_TRUE(other_low_res_tiling);
+ EXPECT_EQ(low_res_tiling, other_low_res_tiling);
+}
+
TEST_F(PictureLayerImplTest, ZoomOutCrash) {
- gfx::Size tile_size(400, 400);
gfx::Size layer_bounds(1300, 1900);
// Set up the high and low res tilings before pinch zoom.
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
-
- SetupTrees(pending_pile, active_pile);
+ SetupDefaultTrees(layer_bounds);
ResetTilingsAndRasterScales();
EXPECT_EQ(0u, active_layer_->tilings()->num_tilings());
SetContentsScaleOnBothLayers(32.0f, 1.0f, 32.0f, 1.0f, 0.f, false);
@@ -958,25 +964,22 @@ TEST_F(PictureLayerImplTest, ZoomOutCrash) {
}
TEST_F(PictureLayerImplTest, PinchGestureTilings) {
- gfx::Size tile_size(400, 400);
gfx::Size layer_bounds(1300, 1900);
float low_res_factor = host_impl_.settings().low_res_contents_scale_factor;
-
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
-
// Set up the high and low res tilings before pinch zoom.
- SetupTrees(pending_pile, active_pile);
+ SetupDefaultTrees(layer_bounds);
ResetTilingsAndRasterScales();
SetContentsScaleOnBothLayers(2.f, 1.0f, 2.f, 1.0f, 0.f, false);
- EXPECT_BOTH_EQ(num_tilings(), 2u);
- EXPECT_BOTH_EQ(tilings()->tiling_at(0)->contents_scale(), 2.f);
- EXPECT_BOTH_EQ(tilings()->tiling_at(1)->contents_scale(),
- 2.f * low_res_factor);
+ EXPECT_EQ(active_layer_->num_tilings(), 2u);
+ EXPECT_EQ(pending_layer_->num_tilings(), 1u);
+ EXPECT_EQ(active_layer_->tilings()->tiling_at(0)->contents_scale(), 2.f);
+ EXPECT_EQ(active_layer_->tilings()->tiling_at(1)->contents_scale(),
+ 2.f * low_res_factor);
+ // One of the tilings has to be a low resolution one.
+ EXPECT_EQ(LOW_RESOLUTION,
+ active_layer_->tilings()->tiling_at(1)->resolution());
// Ensure UpdateTiles won't remove any tilings.
active_layer_->MarkAllTilingsUsed();
@@ -994,6 +997,9 @@ TEST_F(PictureLayerImplTest, PinchGestureTilings) {
active_layer_->tilings()->tiling_at(1)->contents_scale());
EXPECT_FLOAT_EQ(2.0f * low_res_factor,
active_layer_->tilings()->tiling_at(2)->contents_scale());
+ // Since we're pinching, we shouldn't create a low resolution tiling.
+ EXPECT_FALSE(
+ active_layer_->tilings()->FindTilingWithResolution(LOW_RESOLUTION));
// Ensure UpdateTiles won't remove any tilings.
active_layer_->MarkAllTilingsUsed();
@@ -1003,6 +1009,8 @@ TEST_F(PictureLayerImplTest, PinchGestureTilings) {
SetContentsScaleOnBothLayers(low_res_factor * 2.1f, 1.0f,
low_res_factor * 2.1f, 1.0f, 0.f, false);
EXPECT_EQ(3u, active_layer_->tilings()->num_tilings());
+ EXPECT_FALSE(
+ active_layer_->tilings()->FindTilingWithResolution(LOW_RESOLUTION));
// Zoom in a lot now. Since we increase by increments of
// kMaxScaleRatioDuringPinch, this will create a new tiling at 4.0.
@@ -1010,18 +1018,36 @@ TEST_F(PictureLayerImplTest, PinchGestureTilings) {
EXPECT_EQ(4u, active_layer_->tilings()->num_tilings());
EXPECT_FLOAT_EQ(4.0f,
active_layer_->tilings()->tiling_at(0)->contents_scale());
+ // Although one of the tilings matches the low resolution scale, it still
+ // shouldn't be marked as low resolution since we're pinching.
+ auto* low_res_tiling =
+ active_layer_->tilings()->FindTilingWithScale(4.f * low_res_factor);
+ EXPECT_TRUE(low_res_tiling);
+ EXPECT_NE(LOW_RESOLUTION, low_res_tiling->resolution());
+
+ // Stop a pinch gesture.
+ host_impl_.PinchGestureEnd();
+
+ // Ensure UpdateTiles won't remove any tilings.
+ active_layer_->MarkAllTilingsUsed();
+
+ // After pinch ends, set the scale to what the raster scale was updated to
+ // (checked above).
+ SetContentsScaleOnBothLayers(4.0f, 1.0f, 4.0f, 1.f, 0.f, false);
+ EXPECT_EQ(4u, active_layer_->tilings()->num_tilings());
+ EXPECT_FLOAT_EQ(4.0f,
+ active_layer_->tilings()->tiling_at(0)->contents_scale());
+ // Now that we stopped pinching, the low resolution tiling that existed should
+ // now be marked as low resolution.
+ low_res_tiling =
+ active_layer_->tilings()->FindTilingWithScale(4.f * low_res_factor);
+ EXPECT_TRUE(low_res_tiling);
+ EXPECT_EQ(LOW_RESOLUTION, low_res_tiling->resolution());
}
TEST_F(PictureLayerImplTest, SnappedTilingDuringZoom) {
- gfx::Size tile_size(300, 300);
gfx::Size layer_bounds(2600, 3800);
-
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
-
- SetupTrees(pending_pile, active_pile);
+ SetupDefaultTrees(layer_bounds);
ResetTilingsAndRasterScales();
EXPECT_EQ(0u, active_layer_->tilings()->num_tilings());
@@ -1073,14 +1099,8 @@ TEST_F(PictureLayerImplTest, SnappedTilingDuringZoom) {
}
TEST_F(PictureLayerImplTest, CleanUpTilings) {
- gfx::Size tile_size(400, 400);
gfx::Size layer_bounds(1300, 1900);
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
-
std::vector<PictureLayerTiling*> used_tilings;
float low_res_factor = host_impl_.settings().low_res_contents_scale_factor;
@@ -1089,7 +1109,7 @@ TEST_F(PictureLayerImplTest, CleanUpTilings) {
float scale = 1.f;
float page_scale = 1.f;
- SetupTrees(pending_pile, active_pile);
+ SetupDefaultTrees(layer_bounds);
EXPECT_EQ(2u, active_layer_->tilings()->num_tilings());
EXPECT_EQ(1.f, active_layer_->HighResTiling()->contents_scale());
@@ -1219,8 +1239,9 @@ TEST_F(PictureLayerImplTest, DontAddLowResDuringAnimation) {
maximum_animation_scale,
starting_animation_scale, animating_transform);
EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 1.f);
- EXPECT_BOTH_EQ(LowResTiling()->contents_scale(), low_res_factor);
- EXPECT_BOTH_EQ(num_tilings(), 2u);
+ EXPECT_EQ(active_layer_->LowResTiling()->contents_scale(), low_res_factor);
+ EXPECT_EQ(active_layer_->num_tilings(), 2u);
+ EXPECT_EQ(pending_layer_->num_tilings(), 1u);
// Ensure UpdateTiles won't remove any tilings.
active_layer_->MarkAllTilingsUsed();
@@ -1247,21 +1268,21 @@ TEST_F(PictureLayerImplTest, DontAddLowResDuringAnimation) {
maximum_animation_scale,
starting_animation_scale, animating_transform);
EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 2.f);
- EXPECT_BOTH_EQ(LowResTiling()->contents_scale(), 2.f * low_res_factor);
+ EXPECT_EQ(active_layer_->LowResTiling()->contents_scale(),
+ 2.f * low_res_factor);
EXPECT_EQ(4u, active_layer_->num_tilings());
- EXPECT_EQ(2u, pending_layer_->num_tilings());
+ EXPECT_EQ(1u, pending_layer_->num_tilings());
}
TEST_F(PictureLayerImplTest, DontAddLowResForSmallLayers) {
gfx::Size layer_bounds(host_impl_.settings().default_tile_size);
- gfx::Size tile_size(100, 100);
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> active_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
- SetupTrees(pending_pile, active_pile);
+ SetupTrees(pending_raster_source, active_raster_source);
float low_res_factor = host_impl_.settings().low_res_contents_scale_factor;
float device_scale = 1.f;
@@ -1297,14 +1318,16 @@ TEST_F(PictureLayerImplTest, DontAddLowResForSmallLayers) {
maximum_animation_scale,
starting_animation_scale, animating_transform);
EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), contents_scale);
- EXPECT_BOTH_EQ(LowResTiling()->contents_scale(),
- contents_scale * low_res_factor);
- EXPECT_BOTH_EQ(num_tilings(), 2u);
+ EXPECT_EQ(active_layer_->LowResTiling()->contents_scale(),
+ contents_scale * low_res_factor);
+ EXPECT_FALSE(pending_layer_->LowResTiling());
+ EXPECT_EQ(active_layer_->num_tilings(), 2u);
+ EXPECT_EQ(pending_layer_->num_tilings(), 1u);
// Mask layers dont create low res since they always fit on one tile.
scoped_ptr<FakePictureLayerImpl> mask =
FakePictureLayerImpl::CreateMaskWithRasterSource(
- host_impl_.pending_tree(), 3, pending_pile);
+ host_impl_.pending_tree(), 3, pending_raster_source);
mask->SetBounds(layer_bounds);
mask->SetDrawsContent(true);
@@ -1318,21 +1341,21 @@ TEST_F(PictureLayerImplTest, DontAddLowResForSmallLayers) {
TEST_F(PictureLayerImplTest, HugeMasksGetScaledDown) {
host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));
- gfx::Size tile_size(100, 100);
gfx::Size layer_bounds(1000, 1000);
- scoped_refptr<FakePicturePileImpl> valid_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- SetupPendingTree(valid_pile);
+ scoped_refptr<FakeDisplayListRasterSource> valid_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
+ SetupPendingTree(valid_raster_source);
scoped_ptr<FakePictureLayerImpl> mask_ptr =
FakePictureLayerImpl::CreateMaskWithRasterSource(
- host_impl_.pending_tree(), 3, valid_pile);
+ host_impl_.pending_tree(), 3, valid_raster_source);
mask_ptr->SetBounds(layer_bounds);
mask_ptr->SetDrawsContent(true);
pending_layer_->SetMaskLayer(mask_ptr.Pass());
pending_layer_->SetHasRenderSurface(true);
+ host_impl_.pending_tree()->BuildPropertyTreesForTesting();
host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));
bool update_lcd_text = false;
host_impl_.pending_tree()->UpdateDrawProperties(update_lcd_text);
@@ -1375,12 +1398,12 @@ TEST_F(PictureLayerImplTest, HugeMasksGetScaledDown) {
// Resize larger than the max texture size.
int max_texture_size = host_impl_.GetRendererCapabilities().max_texture_size;
gfx::Size huge_bounds(max_texture_size + 1, 10);
- scoped_refptr<FakePicturePileImpl> huge_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, huge_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> huge_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(huge_bounds);
- SetupPendingTree(huge_pile);
+ SetupPendingTree(huge_raster_source);
pending_mask->SetBounds(huge_bounds);
- pending_mask->SetRasterSourceOnPending(huge_pile, Region());
+ pending_mask->SetRasterSourceOnPending(huge_raster_source, Region());
host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));
host_impl_.pending_tree()->UpdateDrawProperties(update_lcd_text);
@@ -1416,7 +1439,7 @@ TEST_F(PictureLayerImplTest, HugeMasksGetScaledDown) {
EXPECT_EQ(expected_size, mask_texture_size);
// Do another activate, the same holds.
- SetupPendingTree(huge_pile);
+ SetupPendingTree(huge_raster_source);
ActivateTree();
EXPECT_EQ(1u, active_mask->HighResTiling()->AllTilesForTesting().size());
active_layer_->GetContentsResourceId(&mask_resource_id, &mask_texture_size);
@@ -1427,12 +1450,12 @@ TEST_F(PictureLayerImplTest, HugeMasksGetScaledDown) {
// contents scale. Then the layer should no longer have any tiling.
float min_contents_scale = host_impl_.settings().minimum_contents_scale;
gfx::Size extra_huge_bounds(max_texture_size / min_contents_scale + 1, 10);
- scoped_refptr<FakePicturePileImpl> extra_huge_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, extra_huge_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> extra_huge_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(extra_huge_bounds);
- SetupPendingTree(extra_huge_pile);
+ SetupPendingTree(extra_huge_raster_source);
pending_mask->SetBounds(extra_huge_bounds);
- pending_mask->SetRasterSourceOnPending(extra_huge_pile, Region());
+ pending_mask->SetRasterSourceOnPending(extra_huge_raster_source, Region());
EXPECT_FALSE(pending_mask->CanHaveTilings());
@@ -1445,23 +1468,23 @@ TEST_F(PictureLayerImplTest, HugeMasksGetScaledDown) {
TEST_F(PictureLayerImplTest, ScaledMaskLayer) {
host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));
- gfx::Size tile_size(100, 100);
gfx::Size layer_bounds(1000, 1000);
- host_impl_.SetDeviceScaleFactor(1.3f);
+ SetInitialDeviceScaleFactor(1.3f);
- scoped_refptr<FakePicturePileImpl> valid_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- SetupPendingTree(valid_pile);
+ scoped_refptr<FakeDisplayListRasterSource> valid_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
+ SetupPendingTree(valid_raster_source);
scoped_ptr<FakePictureLayerImpl> mask_ptr =
FakePictureLayerImpl::CreateMaskWithRasterSource(
- host_impl_.pending_tree(), 3, valid_pile);
+ host_impl_.pending_tree(), 3, valid_raster_source);
mask_ptr->SetBounds(layer_bounds);
mask_ptr->SetDrawsContent(true);
pending_layer_->SetMaskLayer(mask_ptr.Pass());
pending_layer_->SetHasRenderSurface(true);
+ host_impl_.pending_tree()->BuildPropertyTreesForTesting();
host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));
bool update_lcd_text = false;
host_impl_.pending_tree()->UpdateDrawProperties(update_lcd_text);
@@ -1489,21 +1512,14 @@ TEST_F(PictureLayerImplTest, ScaledMaskLayer) {
active_mask->GetContentsResourceId(&mask_resource_id, &mask_texture_size);
EXPECT_NE(0u, mask_resource_id);
gfx::Size expected_mask_texture_size =
- gfx::ToCeiledSize(gfx::ScaleSize(active_mask->bounds(), 1.3f));
+ gfx::ScaleToCeiledSize(active_mask->bounds(), 1.3f);
EXPECT_EQ(mask_texture_size, expected_mask_texture_size);
}
TEST_F(PictureLayerImplTest, ReleaseResources) {
- gfx::Size tile_size(400, 400);
gfx::Size layer_bounds(1300, 1900);
-
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
-
- SetupTrees(pending_pile, active_pile);
- EXPECT_EQ(2u, pending_layer_->tilings()->num_tilings());
+ SetupDefaultTrees(layer_bounds);
+ EXPECT_EQ(1u, pending_layer_->tilings()->num_tilings());
// All tilings should be removed when losing output surface.
active_layer_->ReleaseResources();
@@ -1523,18 +1539,16 @@ TEST_F(PictureLayerImplTest, ReleaseResources) {
1.f, // maximum animation scale
0.f, // starting animation_scale
false);
- EXPECT_EQ(2u, pending_layer_->tilings()->num_tilings());
+ EXPECT_EQ(1u, pending_layer_->tilings()->num_tilings());
}
TEST_F(PictureLayerImplTest, ClampTilesToMaxTileSize) {
- // The default max tile size is larger than 400x400.
- gfx::Size tile_size(400, 400);
gfx::Size layer_bounds(5000, 5000);
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
- SetupPendingTree(pending_pile);
+ SetupPendingTree(pending_raster_source);
EXPECT_GE(pending_layer_->tilings()->num_tilings(), 1u);
pending_layer_->tilings()->tiling_at(0)->CreateAllTilesForTesting();
@@ -1554,12 +1568,14 @@ TEST_F(PictureLayerImplTest, ClampTilesToMaxTileSize) {
TestWebGraphicsContext3D::Create();
context->set_max_texture_size(140);
host_impl_.DidLoseOutputSurface();
- host_impl_.InitializeRenderer(
- FakeOutputSurface::Create3d(context.Pass()).Pass());
+ scoped_ptr<OutputSurface> new_output_surface =
+ FakeOutputSurface::Create3d(context.Pass());
+ host_impl_.InitializeRenderer(new_output_surface.get());
+ output_surface_ = new_output_surface.Pass();
SetupDrawPropertiesAndUpdateTiles(pending_layer_, 1.f, 1.f, 1.f, 1.f, 0.f,
false);
- ASSERT_EQ(2u, pending_layer_->tilings()->num_tilings());
+ ASSERT_EQ(1u, pending_layer_->tilings()->num_tilings());
pending_layer_->tilings()->tiling_at(0)->CreateAllTilesForTesting();
@@ -1570,16 +1586,8 @@ TEST_F(PictureLayerImplTest, ClampTilesToMaxTileSize) {
}
TEST_F(PictureLayerImplTest, ClampSingleTileToToMaxTileSize) {
- // The default max tile size is larger than 400x400.
- gfx::Size tile_size(400, 400);
gfx::Size layer_bounds(500, 500);
-
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
-
- SetupTrees(pending_pile, active_pile);
+ SetupDefaultTrees(layer_bounds);
EXPECT_GE(active_layer_->tilings()->num_tilings(), 1u);
active_layer_->tilings()->tiling_at(0)->CreateAllTilesForTesting();
@@ -1599,8 +1607,10 @@ TEST_F(PictureLayerImplTest, ClampSingleTileToToMaxTileSize) {
TestWebGraphicsContext3D::Create();
context->set_max_texture_size(140);
host_impl_.DidLoseOutputSurface();
- host_impl_.InitializeRenderer(
- FakeOutputSurface::Create3d(context.Pass()).Pass());
+ scoped_ptr<OutputSurface> new_output_surface =
+ FakeOutputSurface::Create3d(context.Pass());
+ host_impl_.InitializeRenderer(new_output_surface.get());
+ output_surface_ = new_output_surface.Pass();
SetupDrawPropertiesAndUpdateTiles(active_layer_, 1.f, 1.f, 1.f, 1.f, 0.f,
false);
@@ -1622,17 +1632,13 @@ TEST_F(PictureLayerImplTest, ClampSingleTileToToMaxTileSize) {
TEST_F(PictureLayerImplTest, DisallowTileDrawQuads) {
scoped_ptr<RenderPass> render_pass = RenderPass::Create();
- gfx::Size tile_size(400, 400);
gfx::Size layer_bounds(1300, 1900);
-
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ gfx::Rect layer_rect(layer_bounds);
gfx::Rect layer_invalidation(150, 200, 30, 180);
- SetupTreesWithInvalidation(pending_pile, active_pile, layer_invalidation);
+ SetupDefaultTreesWithInvalidation(layer_bounds, layer_invalidation);
+ active_layer_->SetContentsOpaque(true);
active_layer_->draw_properties().visible_layer_rect = gfx::Rect(layer_bounds);
AppendQuadsData data;
@@ -1640,28 +1646,85 @@ TEST_F(PictureLayerImplTest, DisallowTileDrawQuads) {
active_layer_->AppendQuads(render_pass.get(), &data);
active_layer_->DidDraw(nullptr);
+ ASSERT_EQ(1u, render_pass->quad_list.size());
+ EXPECT_EQ(DrawQuad::PICTURE_CONTENT,
+ render_pass->quad_list.front()->material);
+ EXPECT_EQ(render_pass->quad_list.front()->rect, layer_rect);
+ EXPECT_EQ(render_pass->quad_list.front()->opaque_rect, layer_rect);
+ EXPECT_EQ(render_pass->quad_list.front()->visible_rect, layer_rect);
+}
+
+TEST_F(PictureLayerImplTest, ResourcelessPartialRecording) {
+ scoped_ptr<RenderPass> render_pass = RenderPass::Create();
+
+ gfx::Size tile_size(400, 400);
+ gfx::Size layer_bounds(700, 650);
+ gfx::Rect layer_rect(layer_bounds);
+ SetInitialDeviceScaleFactor(2.f);
+
+ gfx::Rect recorded_viewport(20, 30, 40, 50);
+ scoped_refptr<FakeDisplayListRasterSource> active_raster_source =
+ FakeDisplayListRasterSource::CreatePartiallyFilled(layer_bounds,
+ recorded_viewport);
+
+ SetupPendingTree(active_raster_source);
+ ActivateTree();
+
+ active_layer_->SetContentsOpaque(true);
+ gfx::Rect visible_rect(30, 35, 10, 5);
+ active_layer_->draw_properties().visible_layer_rect = visible_rect;
+
+ AppendQuadsData data;
+ active_layer_->WillDraw(DRAW_MODE_RESOURCELESS_SOFTWARE, nullptr);
+ active_layer_->AppendQuads(render_pass.get(), &data);
+ active_layer_->DidDraw(nullptr);
+
+ gfx::Rect scaled_visible = gfx::ScaleToEnclosingRect(visible_rect, 2.f);
+ gfx::Rect scaled_recorded = gfx::ScaleToEnclosingRect(recorded_viewport, 2.f);
+ gfx::Rect quad_visible = gfx::IntersectRects(scaled_visible, scaled_recorded);
+
ASSERT_EQ(1U, render_pass->quad_list.size());
EXPECT_EQ(DrawQuad::PICTURE_CONTENT,
render_pass->quad_list.front()->material);
+ const DrawQuad* quad = render_pass->quad_list.front();
+ EXPECT_EQ(quad_visible, quad->rect);
+ EXPECT_EQ(quad_visible, quad->opaque_rect);
+ EXPECT_EQ(quad_visible, quad->visible_rect);
+}
+
+TEST_F(PictureLayerImplTest, ResourcelessEmptyRecording) {
+ scoped_ptr<RenderPass> render_pass = RenderPass::Create();
+
+ gfx::Size layer_bounds(700, 650);
+ scoped_refptr<FakeDisplayListRasterSource> active_raster_source =
+ FakeDisplayListRasterSource::CreatePartiallyFilled(layer_bounds,
+ gfx::Rect());
+ SetupPendingTree(active_raster_source);
+ ActivateTree();
+
+ active_layer_->SetContentsOpaque(true);
+ active_layer_->draw_properties().visible_layer_rect = gfx::Rect(layer_bounds);
+
+ AppendQuadsData data;
+ active_layer_->WillDraw(DRAW_MODE_RESOURCELESS_SOFTWARE, nullptr);
+ active_layer_->AppendQuads(render_pass.get(), &data);
+ active_layer_->DidDraw(nullptr);
+
+ EXPECT_EQ(0U, render_pass->quad_list.size());
}
TEST_F(PictureLayerImplTest, SolidColorLayerHasVisibleFullCoverage) {
scoped_ptr<RenderPass> render_pass = RenderPass::Create();
- gfx::Size tile_size(1000, 1000);
gfx::Size layer_bounds(1500, 1500);
gfx::Rect visible_rect(250, 250, 1000, 1000);
- scoped_ptr<FakePicturePile> empty_recording =
- FakePicturePile::CreateEmptyPile(tile_size, layer_bounds);
- empty_recording->SetIsSolidColor(true);
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilledSolidColor(layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> active_raster_source =
+ FakeDisplayListRasterSource::CreateFilledSolidColor(layer_bounds);
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFromPile(empty_recording.get(), nullptr);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateFromPile(empty_recording.get(), nullptr);
-
- SetupTrees(pending_pile, active_pile);
+ SetupTrees(pending_raster_source, active_raster_source);
active_layer_->draw_properties().visible_layer_rect = visible_rect;
@@ -1680,29 +1743,26 @@ TEST_F(PictureLayerImplTest, SolidColorLayerHasVisibleFullCoverage) {
EXPECT_TRUE(remaining.IsEmpty());
}
-TEST_F(PictureLayerImplTest, TileScalesWithSolidColorPile) {
+TEST_F(PictureLayerImplTest, TileScalesWithSolidColorRasterSource) {
gfx::Size layer_bounds(200, 200);
- gfx::Size tile_size(host_impl_.settings().default_tile_size);
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateEmptyPileThatThinksItHasRecordings(
- tile_size, layer_bounds, false);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateEmptyPileThatThinksItHasRecordings(
- tile_size, layer_bounds, true);
-
- SetupTrees(pending_pile, active_pile);
- // Solid color pile should not allow tilings at any scale.
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> active_raster_source =
+ FakeDisplayListRasterSource::CreateFilledSolidColor(layer_bounds);
+
+ SetupTrees(pending_raster_source, active_raster_source);
+ // Solid color raster source should not allow tilings at any scale.
EXPECT_FALSE(active_layer_->CanHaveTilings());
EXPECT_EQ(0.f, active_layer_->ideal_contents_scale());
- // Activate non-solid-color pending pile makes active layer can have tilings.
+ // Activate non-solid-color pending raster source makes active layer can have
+ // tilings.
ActivateTree();
EXPECT_TRUE(active_layer_->CanHaveTilings());
EXPECT_GT(active_layer_->ideal_contents_scale(), 0.f);
}
TEST_F(NoLowResPictureLayerImplTest, MarkRequiredOffscreenTiles) {
- gfx::Size tile_size(100, 100);
gfx::Size layer_bounds(200, 200);
gfx::Transform transform;
@@ -1716,9 +1776,10 @@ TEST_F(NoLowResPictureLayerImplTest, MarkRequiredOffscreenTiles) {
transform,
resourceless_software_draw);
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- SetupPendingTreeWithFixedTileSize(pending_pile, tile_size, Region());
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
+ SetupPendingTreeWithFixedTileSize(pending_raster_source, gfx::Size(100, 100),
+ Region());
EXPECT_EQ(1u, pending_layer_->num_tilings());
EXPECT_EQ(viewport, pending_layer_->visible_rect_for_tile_priority());
@@ -1757,11 +1818,7 @@ TEST_F(NoLowResPictureLayerImplTest,
gfx::Rect external_viewport_for_tile_priority(400, 200);
gfx::Rect visible_layer_rect(200, 400);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- SetupTreesWithFixedTileSize(pending_pile, active_pile, tile_size, Region());
+ SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size, Region());
ASSERT_EQ(1u, pending_layer_->num_tilings());
ASSERT_EQ(1.f, pending_layer_->HighResTiling()->contents_scale());
@@ -1840,10 +1897,10 @@ TEST_F(PictureLayerImplTest, HighResTileIsComplete) {
gfx::Size tile_size(100, 100);
gfx::Size layer_bounds(200, 200);
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
- SetupPendingTreeWithFixedTileSize(pending_pile, tile_size, Region());
+ SetupPendingTreeWithFixedTileSize(pending_raster_source, tile_size, Region());
ActivateTree();
// All high res tiles have resources.
@@ -1870,9 +1927,9 @@ TEST_F(PictureLayerImplTest, HighResTileIsIncomplete) {
gfx::Size tile_size(100, 100);
gfx::Size layer_bounds(200, 200);
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- SetupPendingTreeWithFixedTileSize(pending_pile, tile_size, Region());
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
+ SetupPendingTreeWithFixedTileSize(pending_raster_source, tile_size, Region());
ActivateTree();
scoped_ptr<RenderPass> render_pass = RenderPass::Create();
@@ -1893,9 +1950,9 @@ TEST_F(PictureLayerImplTest, HighResTileIsIncompleteLowResComplete) {
gfx::Size tile_size(100, 100);
gfx::Size layer_bounds(200, 200);
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- SetupPendingTreeWithFixedTileSize(pending_pile, tile_size, Region());
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
+ SetupPendingTreeWithFixedTileSize(pending_raster_source, tile_size, Region());
ActivateTree();
std::vector<Tile*> low_tiles =
@@ -1920,9 +1977,9 @@ TEST_F(PictureLayerImplTest, LowResTileIsIncomplete) {
gfx::Size tile_size(100, 100);
gfx::Size layer_bounds(200, 200);
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- SetupPendingTreeWithFixedTileSize(pending_pile, tile_size, Region());
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
+ SetupPendingTreeWithFixedTileSize(pending_raster_source, tile_size, Region());
ActivateTree();
// All high res tiles have resources except one.
@@ -1958,13 +2015,9 @@ TEST_F(PictureLayerImplTest,
gfx::Size viewport_size(400, 400);
host_impl_.SetViewportSize(viewport_size);
- host_impl_.SetDeviceScaleFactor(2.f);
+ SetInitialDeviceScaleFactor(2.f);
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- SetupTreesWithFixedTileSize(pending_pile, active_pile, tile_size, Region());
+ SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size, Region());
// One ideal tile exists, this will get used when drawing.
std::vector<Tile*> ideal_tiles;
@@ -2026,10 +2079,9 @@ TEST_F(PictureLayerImplTest, HighResRequiredWhenActiveAllReady) {
// All active tiles ready, so pending can only activate with all high res
// tiles.
pending_layer_->HighResTiling()->UpdateAllRequiredStateForTesting();
- pending_layer_->LowResTiling()->UpdateAllRequiredStateForTesting();
+ EXPECT_FALSE(pending_layer_->LowResTiling());
AssertAllTilesRequired(pending_layer_->HighResTiling());
- AssertNoTilesRequired(pending_layer_->LowResTiling());
}
TEST_F(PictureLayerImplTest, HighResRequiredWhenMissingHighResFlagOn) {
@@ -2049,12 +2101,11 @@ TEST_F(PictureLayerImplTest, HighResRequiredWhenMissingHighResFlagOn) {
host_impl_.SetRequiresHighResToDraw();
pending_layer_->HighResTiling()->UpdateAllRequiredStateForTesting();
- pending_layer_->LowResTiling()->UpdateAllRequiredStateForTesting();
+ EXPECT_FALSE(pending_layer_->LowResTiling());
active_layer_->HighResTiling()->UpdateAllRequiredStateForTesting();
active_layer_->LowResTiling()->UpdateAllRequiredStateForTesting();
EXPECT_TRUE(pending_layer_->HighResTiling()->AllTilesForTesting().empty());
- EXPECT_TRUE(pending_layer_->LowResTiling()->AllTilesForTesting().empty());
AssertAllTilesRequired(active_layer_->HighResTiling());
AssertNoTilesRequired(active_layer_->LowResTiling());
}
@@ -2071,7 +2122,7 @@ TEST_F(PictureLayerImplTest, AllHighResRequiredEvenIfNotChanged) {
// Since there are no invalidations, pending tree should have no tiles.
EXPECT_TRUE(pending_layer_->HighResTiling()->AllTilesForTesting().empty());
- EXPECT_TRUE(pending_layer_->LowResTiling()->AllTilesForTesting().empty());
+ EXPECT_FALSE(pending_layer_->LowResTiling());
active_layer_->HighResTiling()->UpdateAllRequiredStateForTesting();
active_layer_->LowResTiling()->UpdateAllRequiredStateForTesting();
@@ -2091,11 +2142,10 @@ TEST_F(PictureLayerImplTest, DisallowRequiredForActivation) {
EXPECT_FALSE(some_active_tile->draw_info().IsReadyToDraw());
EXPECT_TRUE(pending_layer_->HighResTiling()->AllTilesForTesting().empty());
- EXPECT_TRUE(pending_layer_->LowResTiling()->AllTilesForTesting().empty());
+ EXPECT_FALSE(pending_layer_->LowResTiling());
active_layer_->HighResTiling()->set_can_require_tiles_for_activation(false);
active_layer_->LowResTiling()->set_can_require_tiles_for_activation(false);
pending_layer_->HighResTiling()->set_can_require_tiles_for_activation(false);
- pending_layer_->LowResTiling()->set_can_require_tiles_for_activation(false);
// If we disallow required for activation, no tiles can be required.
active_layer_->HighResTiling()->UpdateAllRequiredStateForTesting();
@@ -2109,18 +2159,18 @@ TEST_F(PictureLayerImplTest, NothingRequiredIfActiveMissingTiles) {
gfx::Size layer_bounds(400, 400);
gfx::Size tile_size(100, 100);
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- // This pile will create tilings, but has no recordings so will not create any
- // tiles. This is attempting to simulate scrolling past the end of recorded
- // content on the active layer, where the recordings are so far away that
- // no tiles are created.
- bool is_solid_color = false;
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateEmptyPileThatThinksItHasRecordings(
- tile_size, layer_bounds, is_solid_color);
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
+ // This raster source will create tilings, but has no recordings so will not
+ // create any tiles. This is attempting to simulate scrolling past the end of
+ // recorded content on the active layer, where the recordings are so far away
+ // that no tiles are created.
+ scoped_refptr<FakeDisplayListRasterSource> active_raster_source =
+ FakeDisplayListRasterSource::CreatePartiallyFilled(layer_bounds,
+ gfx::Rect());
- SetupTreesWithFixedTileSize(pending_pile, active_pile, tile_size, Region());
+ SetupTreesWithFixedTileSize(pending_raster_source, active_raster_source,
+ tile_size, Region());
// Active layer has tilings, but no tiles due to missing recordings.
EXPECT_TRUE(active_layer_->CanHaveTilings());
@@ -2130,21 +2180,21 @@ TEST_F(PictureLayerImplTest, NothingRequiredIfActiveMissingTiles) {
// Since the active layer has no tiles at all, the pending layer doesn't
// need content in order to activate.
pending_layer_->HighResTiling()->UpdateAllRequiredStateForTesting();
- pending_layer_->LowResTiling()->UpdateAllRequiredStateForTesting();
+ EXPECT_FALSE(pending_layer_->LowResTiling());
AssertNoTilesRequired(pending_layer_->HighResTiling());
- AssertNoTilesRequired(pending_layer_->LowResTiling());
}
TEST_F(PictureLayerImplTest, HighResRequiredIfActiveCantHaveTiles) {
gfx::Size layer_bounds(400, 400);
gfx::Size tile_size(100, 100);
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateEmptyPile(tile_size, layer_bounds);
- SetupTreesWithFixedTileSize(pending_pile, active_pile, tile_size, Region());
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> active_raster_source =
+ FakeDisplayListRasterSource::CreateEmpty(layer_bounds);
+ SetupTreesWithFixedTileSize(pending_raster_source, active_raster_source,
+ tile_size, Region());
// Active layer can't have tiles.
EXPECT_FALSE(active_layer_->CanHaveTilings());
@@ -2154,10 +2204,9 @@ TEST_F(PictureLayerImplTest, HighResRequiredIfActiveCantHaveTiles) {
// This can happen if a layer exists for a while and switches from
// not being able to have content to having content.
pending_layer_->HighResTiling()->UpdateAllRequiredStateForTesting();
- pending_layer_->LowResTiling()->UpdateAllRequiredStateForTesting();
+ EXPECT_FALSE(pending_layer_->LowResTiling());
AssertAllTilesRequired(pending_layer_->HighResTiling());
- AssertNoTilesRequired(pending_layer_->LowResTiling());
}
TEST_F(PictureLayerImplTest, HighResRequiredWhenActiveHasDifferentBounds) {
@@ -2165,41 +2214,37 @@ TEST_F(PictureLayerImplTest, HighResRequiredWhenActiveHasDifferentBounds) {
gfx::Size active_layer_bounds(200, 200);
gfx::Size tile_size(100, 100);
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, pending_layer_bounds);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, active_layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(pending_layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> active_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(active_layer_bounds);
- SetupTreesWithFixedTileSize(pending_pile, active_pile, tile_size, Region());
+ SetupTreesWithFixedTileSize(pending_raster_source, active_raster_source,
+ tile_size, Region());
// Since the active layer has different bounds, the pending layer needs all
// high res tiles in order to activate.
pending_layer_->HighResTiling()->UpdateAllRequiredStateForTesting();
- pending_layer_->LowResTiling()->UpdateAllRequiredStateForTesting();
+ EXPECT_FALSE(pending_layer_->LowResTiling());
active_layer_->HighResTiling()->UpdateAllRequiredStateForTesting();
active_layer_->LowResTiling()->UpdateAllRequiredStateForTesting();
AssertAllTilesRequired(pending_layer_->HighResTiling());
AssertAllTilesRequired(active_layer_->HighResTiling());
AssertNoTilesRequired(active_layer_->LowResTiling());
- // Since the test doesn't invalidate the resized region, we expect that the
- // same low res tile would exist (which means we don't create a new one of the
- // pending tree).
- EXPECT_TRUE(pending_layer_->LowResTiling()->AllTilesForTesting().empty());
}
TEST_F(PictureLayerImplTest, ActivateUninitializedLayer) {
- gfx::Size tile_size(100, 100);
gfx::Size layer_bounds(400, 400);
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
host_impl_.CreatePendingTree();
LayerTreeImpl* pending_tree = host_impl_.pending_tree();
scoped_ptr<FakePictureLayerImpl> pending_layer =
FakePictureLayerImpl::CreateWithRasterSource(pending_tree, id_,
- pending_pile);
+ pending_raster_source);
pending_layer->SetDrawsContent(true);
pending_tree->SetRootLayer(pending_layer.Pass());
@@ -2224,12 +2269,11 @@ TEST_F(PictureLayerImplTest, ActivateUninitializedLayer) {
TEST_F(PictureLayerImplTest, ShareTilesOnNextFrame) {
gfx::Size layer_bounds(1500, 1500);
- gfx::Size tile_size(100, 100);
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
- SetupPendingTree(pending_pile);
+ SetupPendingTree(pending_raster_source);
PictureLayerTiling* tiling = pending_layer_->HighResTiling();
gfx::Rect first_invalidate = tiling->TilingDataForTesting().TileBounds(0, 0);
@@ -2242,18 +2286,16 @@ TEST_F(PictureLayerImplTest, ShareTilesOnNextFrame) {
ActivateTree();
// Make a pending tree with an invalidated raster tile 0,0.
- SetupPendingTreeWithInvalidation(pending_pile, first_invalidate);
+ SetupPendingTreeWithInvalidation(pending_raster_source, first_invalidate);
// Activate and make a pending tree with an invalidated raster tile 1,1.
ActivateTree();
- SetupPendingTreeWithInvalidation(pending_pile, second_invalidate);
+ SetupPendingTreeWithInvalidation(pending_raster_source, second_invalidate);
PictureLayerTiling* pending_tiling = pending_layer_->tilings()->tiling_at(0);
PictureLayerTiling* active_tiling = active_layer_->tilings()->tiling_at(0);
- // pending_tiling->CreateAllTilesForTesting();
-
// Tile 0,0 not exist on pending, but tile 1,1 should.
EXPECT_TRUE(active_tiling->TileAt(0, 0));
EXPECT_TRUE(active_tiling->TileAt(1, 0));
@@ -2306,20 +2348,20 @@ TEST_F(PictureLayerImplTest, PendingHasNoTilesWithNoInvalidation) {
}
TEST_F(PictureLayerImplTest, ShareInvalidActiveTreeTiles) {
- gfx::Size tile_size(100, 100);
gfx::Size layer_bounds(1500, 1500);
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- SetupTreesWithInvalidation(pending_pile, active_pile, gfx::Rect(1, 1));
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> active_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
+ SetupTreesWithInvalidation(pending_raster_source, active_raster_source,
+ gfx::Rect(1, 1));
// Activate the invalidation.
ActivateTree();
// Make another pending tree without any invalidation in it.
- scoped_refptr<FakePicturePileImpl> pending_pile2 =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- SetupPendingTree(pending_pile2);
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source2 =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
+ SetupPendingTree(pending_raster_source2);
EXPECT_GE(active_layer_->num_tilings(), 1u);
EXPECT_GE(pending_layer_->num_tilings(), 1u);
@@ -2371,15 +2413,14 @@ TEST_F(PictureLayerImplTest, RecreateInvalidPendingTreeTiles) {
TEST_F(PictureLayerImplTest, SyncTilingAfterGpuRasterizationToggles) {
host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));
- gfx::Size tile_size(100, 100);
gfx::Size layer_bounds(10, 10);
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> active_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
- SetupTrees(pending_pile, active_pile);
+ SetupTrees(pending_raster_source, active_raster_source);
EXPECT_TRUE(pending_layer_->tilings()->FindTilingWithScale(1.f));
EXPECT_TRUE(active_layer_->tilings()->FindTilingWithScale(1.f));
@@ -2403,7 +2444,7 @@ TEST_F(PictureLayerImplTest, SyncTilingAfterGpuRasterizationToggles) {
ActivateTree();
EXPECT_TRUE(active_layer_->tilings()->FindTilingWithScale(1.f));
- SetupPendingTree(pending_pile);
+ SetupPendingTree(pending_raster_source);
EXPECT_TRUE(pending_layer_->tilings()->FindTilingWithScale(1.f));
// Toggling the gpu rasterization clears all tilings on both trees.
@@ -2422,14 +2463,12 @@ TEST_F(PictureLayerImplTest, SyncTilingAfterGpuRasterizationToggles) {
}
TEST_F(PictureLayerImplTest, HighResCreatedWhenBoundsShrink) {
- gfx::Size tile_size(100, 100);
-
// Put 0.5 as high res.
- host_impl_.SetDeviceScaleFactor(0.5f);
+ SetInitialDeviceScaleFactor(0.5f);
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, gfx::Size(10, 10));
- SetupPendingTree(pending_pile);
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(gfx::Size(10, 10));
+ SetupPendingTree(pending_raster_source);
// Sanity checks.
EXPECT_EQ(1u, pending_layer_->tilings()->num_tilings());
@@ -2438,9 +2477,9 @@ TEST_F(PictureLayerImplTest, HighResCreatedWhenBoundsShrink) {
ActivateTree();
// Now, set the bounds to be 1x1, so that minimum contents scale becomes 1.
- pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, gfx::Size(1, 1));
- SetupPendingTree(pending_pile);
+ pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(gfx::Size(1, 1));
+ SetupPendingTree(pending_raster_source);
// Another sanity check.
EXPECT_EQ(1.f, pending_layer_->MinimumContentsScale());
@@ -2463,8 +2502,11 @@ TEST_F(PictureLayerImplTest, LowResTilingWithoutGpuRasterization) {
SetupDefaultTrees(layer_bounds);
EXPECT_FALSE(host_impl_.use_gpu_rasterization());
- // Should have a low-res and a high-res tiling.
- EXPECT_EQ(2u, pending_layer_->tilings()->num_tilings());
+ // Should have only a high-res tiling.
+ EXPECT_EQ(1u, pending_layer_->tilings()->num_tilings());
+ ActivateTree();
+ // Should add a high and a low res for active tree.
+ EXPECT_EQ(2u, active_layer_->tilings()->num_tilings());
}
TEST_F(PictureLayerImplTest, NoLowResTilingWithGpuRasterization) {
@@ -2479,6 +2521,9 @@ TEST_F(PictureLayerImplTest, NoLowResTilingWithGpuRasterization) {
EXPECT_TRUE(host_impl_.use_gpu_rasterization());
// Should only have the high-res tiling.
EXPECT_EQ(1u, pending_layer_->tilings()->num_tilings());
+ ActivateTree();
+ // Should only have the high-res tiling.
+ EXPECT_EQ(1u, active_layer_->tilings()->num_tilings());
}
TEST_F(PictureLayerImplTest, RequiredTilesWithGpuRasterization) {
@@ -2665,6 +2710,7 @@ TEST_F(PictureLayerImplTest, HighResTilingDuringAnimationForCpuRasterization) {
maximum_animation_scale,
starting_animation_scale, animating_transform);
EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 3.f);
+ EXPECT_BOTH_TRUE(GetRasterSource()->ShouldAttemptToUseDistanceFieldText());
// Further changes to scale during the animation should not cause a new
// high-res tiling to get created.
@@ -2799,6 +2845,7 @@ TEST_F(PictureLayerImplTest, HighResTilingDuringAnimationForGpuRasterization) {
maximum_animation_scale,
starting_animation_scale, animating_transform);
EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 1.f);
+ EXPECT_BOTH_FALSE(GetRasterSource()->ShouldAttemptToUseDistanceFieldText());
// Since we're GPU-rasterizing, starting an animation should cause tiling
// resolution to get set to the current contents scale.
@@ -2810,6 +2857,7 @@ TEST_F(PictureLayerImplTest, HighResTilingDuringAnimationForGpuRasterization) {
maximum_animation_scale,
starting_animation_scale, animating_transform);
EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 2.f);
+ EXPECT_BOTH_TRUE(GetRasterSource()->ShouldAttemptToUseDistanceFieldText());
// Further changes to scale during the animation should cause a new high-res
// tiling to get created.
@@ -2844,14 +2892,13 @@ TEST_F(PictureLayerImplTest, TilingSetRasterQueue) {
host_impl_.SetViewportSize(gfx::Size(500, 500));
- gfx::Size recording_tile_size(100, 100);
gfx::Size layer_bounds(1000, 1000);
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(recording_tile_size, layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
- SetupPendingTree(pending_pile);
- EXPECT_EQ(2u, pending_layer_->num_tilings());
+ SetupPendingTree(pending_raster_source);
+ EXPECT_EQ(1u, pending_layer_->num_tilings());
std::set<Tile*> unique_tiles;
bool reached_prepaint = false;
@@ -2968,26 +3015,9 @@ TEST_F(PictureLayerImplTest, TilingSetRasterQueue) {
draw_info.SetSolidColorForTesting(SK_ColorRED);
}
- non_ideal_tile_count = 0;
- low_res_tile_count = 0;
- high_res_tile_count = 0;
queue.reset(new TilingSetRasterQueueAll(
pending_layer_->picture_layer_tiling_set(), true));
- while (!queue->IsEmpty()) {
- PrioritizedTile prioritized_tile = queue->Top();
- TilePriority priority = prioritized_tile.priority();
-
- EXPECT_TRUE(prioritized_tile.tile());
-
- non_ideal_tile_count += priority.resolution == NON_IDEAL_RESOLUTION;
- low_res_tile_count += priority.resolution == LOW_RESOLUTION;
- high_res_tile_count += priority.resolution == HIGH_RESOLUTION;
- queue->Pop();
- }
-
- EXPECT_EQ(0, non_ideal_tile_count);
- EXPECT_EQ(1, low_res_tile_count);
- EXPECT_EQ(0, high_res_tile_count);
+ EXPECT_TRUE(queue->IsEmpty());
}
TEST_F(PictureLayerImplTest, TilingSetRasterQueueActiveTree) {
@@ -2995,13 +3025,12 @@ TEST_F(PictureLayerImplTest, TilingSetRasterQueueActiveTree) {
host_impl_.SetViewportSize(gfx::Size(500, 500));
- gfx::Size tile_size(100, 100);
gfx::Size layer_bounds(1000, 1000);
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
- SetupPendingTree(pending_pile);
+ SetupPendingTree(pending_raster_source);
ActivateTree();
EXPECT_EQ(2u, active_layer_->num_tilings());
@@ -3024,15 +3053,11 @@ TEST_F(PictureLayerImplTest, TilingSetRasterQueueActiveTree) {
}
TEST_F(PictureLayerImplTest, TilingSetRasterQueueRequiredNoHighRes) {
- scoped_ptr<FakePicturePile> empty_recording =
- FakePicturePile::CreateEmptyPile(gfx::Size(256, 256),
- gfx::Size(1024, 1024));
- empty_recording->SetIsSolidColor(true);
-
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFromPile(empty_recording.get(), nullptr);
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilledSolidColor(
+ gfx::Size(1024, 1024));
- SetupPendingTree(pending_pile);
+ SetupPendingTree(pending_raster_source);
EXPECT_FALSE(
pending_layer_->picture_layer_tiling_set()->FindTilingWithResolution(
HIGH_RESOLUTION));
@@ -3045,19 +3070,18 @@ TEST_F(PictureLayerImplTest, TilingSetRasterQueueRequiredNoHighRes) {
}
TEST_F(PictureLayerImplTest, TilingSetEvictionQueue) {
- gfx::Size tile_size(100, 100);
gfx::Size layer_bounds(1000, 1000);
float low_res_factor = host_impl_.settings().low_res_contents_scale_factor;
host_impl_.SetViewportSize(gfx::Size(500, 500));
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
- // TODO(vmpstr): Add a test with tilings other than high/low res on the active
- // tree.
- SetupPendingTree(pending_pile);
- EXPECT_EQ(2u, pending_layer_->num_tilings());
+ // TODO(vmpstr): Add a test with tilings other than high res on the active
+ // tree (crbug.com/519607).
+ SetupPendingTree(pending_raster_source);
+ EXPECT_EQ(1u, pending_layer_->num_tilings());
std::vector<Tile*> all_tiles;
for (size_t i = 0; i < pending_layer_->num_tilings(); ++i) {
@@ -3087,8 +3111,8 @@ TEST_F(PictureLayerImplTest, TilingSetEvictionQueue) {
}
// Sanity checks.
- EXPECT_EQ(17u, all_tiles.size());
- EXPECT_EQ(17u, all_tiles_set.size());
+ EXPECT_EQ(16u, all_tiles.size());
+ EXPECT_EQ(16u, all_tiles_set.size());
EXPECT_GT(number_of_marked_tiles, 1u);
EXPECT_GT(number_of_unmarked_tiles, 1u);
@@ -3196,9 +3220,9 @@ TEST_F(PictureLayerImplTest, Occlusion) {
LayerTestCommon::LayerImplTest impl;
host_impl_.SetViewportSize(viewport_size);
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(layer_bounds, layer_bounds);
- SetupPendingTreeWithFixedTileSize(pending_pile, tile_size, Region());
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
+ SetupPendingTreeWithFixedTileSize(pending_raster_source, tile_size, Region());
ActivateTree();
std::vector<Tile*> tiles =
@@ -3287,7 +3311,7 @@ TEST_F(PictureLayerImplTest, LowResReadyToDrawNotEnoughToActivate) {
EXPECT_FALSE(host_impl_.tile_manager()->IsReadyToActivate());
// Initialize all low-res tiles.
- pending_layer_->SetAllTilesReadyInTiling(pending_layer_->LowResTiling());
+ EXPECT_FALSE(pending_layer_->LowResTiling());
pending_layer_->SetAllTilesReadyInTiling(active_layer_->LowResTiling());
// Low-res tiles should not be enough.
@@ -3319,28 +3343,6 @@ TEST_F(PictureLayerImplTest, HighResReadyToDrawEnoughToActivate) {
EXPECT_TRUE(host_impl_.tile_manager()->IsReadyToActivate());
}
-TEST_F(PictureLayerImplTest,
- ActiveHighResReadyAndPendingLowResReadyNotEnoughToActivate) {
- gfx::Size tile_size(100, 100);
- gfx::Size layer_bounds(1000, 1000);
-
- // Make sure pending tree has tiles.
- gfx::Rect invalidation(gfx::Point(50, 50), tile_size);
- SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size, invalidation);
-
- // Initialize all high-res tiles in the active layer.
- active_layer_->SetAllTilesReadyInTiling(active_layer_->HighResTiling());
- // And all the low-res tiles in the pending layer.
- pending_layer_->SetAllTilesReadyInTiling(pending_layer_->LowResTiling());
-
- // The pending high-res tiles are not ready, so we cannot activate.
- EXPECT_FALSE(host_impl_.tile_manager()->IsReadyToActivate());
-
- // When the pending high-res tiles are ready, we can activate.
- pending_layer_->SetAllTilesReadyInTiling(pending_layer_->HighResTiling());
- EXPECT_TRUE(host_impl_.tile_manager()->IsReadyToActivate());
-}
-
TEST_F(PictureLayerImplTest, ActiveHighResReadyNotEnoughToActivate) {
gfx::Size tile_size(100, 100);
gfx::Size layer_bounds(1000, 1000);
@@ -3355,21 +3357,14 @@ TEST_F(PictureLayerImplTest, ActiveHighResReadyNotEnoughToActivate) {
// The pending high-res tiles are not ready, so we cannot activate.
EXPECT_FALSE(host_impl_.tile_manager()->IsReadyToActivate());
- // When the pending pending high-res tiles are ready, we can activate.
+ // When the pending high-res tiles are ready, we can activate.
pending_layer_->SetAllTilesReadyInTiling(pending_layer_->HighResTiling());
EXPECT_TRUE(host_impl_.tile_manager()->IsReadyToActivate());
}
TEST_F(NoLowResPictureLayerImplTest, ManageTilingsCreatesTilings) {
- gfx::Size tile_size(400, 400);
gfx::Size layer_bounds(1300, 1900);
-
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
-
- SetupTrees(pending_pile, active_pile);
+ SetupDefaultTrees(layer_bounds);
float low_res_factor = host_impl_.settings().low_res_contents_scale_factor;
EXPECT_LT(low_res_factor, 1.f);
@@ -3426,15 +3421,8 @@ TEST_F(NoLowResPictureLayerImplTest, ManageTilingsCreatesTilings) {
}
TEST_F(NoLowResPictureLayerImplTest, PendingLayerOnlyHasHighResTiling) {
- gfx::Size tile_size(400, 400);
gfx::Size layer_bounds(1300, 1900);
-
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
-
- SetupTrees(pending_pile, active_pile);
+ SetupDefaultTrees(layer_bounds);
float low_res_factor = host_impl_.settings().low_res_contents_scale_factor;
EXPECT_LT(low_res_factor, 1.f);
@@ -3518,18 +3506,18 @@ TEST_F(NoLowResPictureLayerImplTest, NothingRequiredIfActiveMissingTiles) {
gfx::Size layer_bounds(400, 400);
gfx::Size tile_size(100, 100);
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- // This pile will create tilings, but has no recordings so will not create any
- // tiles. This is attempting to simulate scrolling past the end of recorded
- // content on the active layer, where the recordings are so far away that
- // no tiles are created.
- bool is_solid_color = false;
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateEmptyPileThatThinksItHasRecordings(
- tile_size, layer_bounds, is_solid_color);
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
+ // This raster source will create tilings, but has no recordings so will not
+ // create any tiles. This is attempting to simulate scrolling past the end of
+ // recorded content on the active layer, where the recordings are so far away
+ // that no tiles are created.
+ scoped_refptr<FakeDisplayListRasterSource> active_raster_source =
+ FakeDisplayListRasterSource::CreatePartiallyFilled(layer_bounds,
+ gfx::Rect());
- SetupTreesWithFixedTileSize(pending_pile, active_pile, tile_size, Region());
+ SetupTreesWithFixedTileSize(pending_raster_source, active_raster_source,
+ tile_size, Region());
// Active layer has tilings, but no tiles due to missing recordings.
EXPECT_TRUE(active_layer_->CanHaveTilings());
@@ -3550,16 +3538,8 @@ TEST_F(NoLowResPictureLayerImplTest, NothingRequiredIfActiveMissingTiles) {
TEST_F(NoLowResPictureLayerImplTest, InvalidViewportForPrioritizingTiles) {
host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));
-
- gfx::Size tile_size(100, 100);
gfx::Size layer_bounds(400, 400);
-
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
-
- SetupTreesWithInvalidation(pending_pile, active_pile, Region());
+ SetupDefaultTrees(layer_bounds);
SetupDrawPropertiesAndUpdateTiles(active_layer_, 1.f, 1.f, 1.f, 1.f, 0.f,
false);
@@ -3626,17 +3606,9 @@ TEST_F(NoLowResPictureLayerImplTest, InvalidViewportForPrioritizingTiles) {
}
TEST_F(NoLowResPictureLayerImplTest, CleanUpTilings) {
- gfx::Size tile_size(400, 400);
gfx::Size layer_bounds(1300, 1900);
-
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
-
std::vector<PictureLayerTiling*> used_tilings;
-
- SetupTrees(pending_pile, active_pile);
+ SetupDefaultTrees(layer_bounds);
float low_res_factor = host_impl_.settings().low_res_contents_scale_factor;
EXPECT_LT(low_res_factor, 1.f);
@@ -3743,15 +3715,8 @@ TEST_F(NoLowResPictureLayerImplTest, CleanUpTilings) {
}
TEST_F(NoLowResPictureLayerImplTest, ReleaseResources) {
- gfx::Size tile_size(400, 400);
gfx::Size layer_bounds(1300, 1900);
-
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
-
- SetupTrees(pending_pile, active_pile);
+ SetupDefaultTrees(layer_bounds);
EXPECT_EQ(1u, pending_layer_->tilings()->num_tilings());
EXPECT_EQ(1u, active_layer_->tilings()->num_tilings());
@@ -3779,17 +3744,9 @@ TEST_F(NoLowResPictureLayerImplTest, ReleaseResources) {
TEST_F(PictureLayerImplTest, SharedQuadStateContainsMaxTilingScale) {
scoped_ptr<RenderPass> render_pass = RenderPass::Create();
- gfx::Size tile_size(400, 400);
gfx::Size layer_bounds(1000, 2000);
-
host_impl_.SetViewportSize(gfx::Size(10000, 20000));
-
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
-
- SetupTrees(pending_pile, active_pile);
+ SetupDefaultTrees(layer_bounds);
ResetTilingsAndRasterScales();
SetupDrawPropertiesAndUpdateTiles(active_layer_, 2.5f, 1.f, 1.f, 1.f, 0.f,
@@ -3826,10 +3783,12 @@ TEST_F(PictureLayerImplTest, SharedQuadStateContainsMaxTilingScale) {
class PictureLayerImplTestWithDelegatingRenderer : public PictureLayerImplTest {
public:
- PictureLayerImplTestWithDelegatingRenderer() : PictureLayerImplTest() {}
+ PictureLayerImplTestWithDelegatingRenderer() : PictureLayerImplTest() {
+ output_surface_ = FakeOutputSurface::CreateDelegating3d();
+ }
void InitializeRenderer() override {
- host_impl_.InitializeRenderer(FakeOutputSurface::CreateDelegating3d());
+ host_impl_.InitializeRenderer(output_surface_.get());
}
};
@@ -3837,13 +3796,12 @@ TEST_F(PictureLayerImplTestWithDelegatingRenderer,
DelegatingRendererWithTileOOM) {
// This test is added for crbug.com/402321, where quad should be produced when
// raster on demand is not allowed and tile is OOM.
- gfx::Size tile_size = host_impl_.settings().default_tile_size;
gfx::Size layer_bounds(1000, 1000);
// Create tiles.
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- SetupPendingTree(pending_pile);
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
+ SetupPendingTree(pending_raster_source);
pending_layer_->SetBounds(layer_bounds);
ActivateTree();
bool update_lcd_text = false;
@@ -3858,6 +3816,7 @@ TEST_F(PictureLayerImplTestWithDelegatingRenderer,
// state. We also need to update tree priority separately.
GlobalStateThatImpactsTilePriority state;
size_t max_tiles = 1;
+ gfx::Size tile_size(host_impl_.settings().default_tile_size);
size_t memory_limit = max_tiles * 4 * tile_size.width() * tile_size.height();
size_t resource_limit = max_tiles;
ManagedMemoryPolicy policy(memory_limit,
@@ -3947,9 +3906,9 @@ TEST_F(OcclusionTrackingPictureLayerImplTest,
host_impl_.SetViewportSize(viewport_size);
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- SetupPendingTreeWithFixedTileSize(pending_pile, tile_size, Region());
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
+ SetupPendingTreeWithFixedTileSize(pending_raster_source, tile_size, Region());
// No occlusion.
int unoccluded_tile_count = 0;
@@ -4036,9 +3995,9 @@ TEST_F(OcclusionTrackingPictureLayerImplTest,
host_impl_.SetViewportSize(viewport_size);
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- SetupPendingTreeWithFixedTileSize(pending_pile, tile_size, Region());
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
+ SetupPendingTreeWithFixedTileSize(pending_raster_source, tile_size, Region());
// No occlusion.
int occluded_tile_count = 0;
@@ -4151,12 +4110,12 @@ TEST_F(OcclusionTrackingPictureLayerImplTest, OcclusionForDifferentScales) {
gfx::Size viewport_size(500, 500);
gfx::Point occluding_layer_position(310, 0);
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
host_impl_.SetViewportSize(viewport_size);
- SetupPendingTreeWithFixedTileSize(pending_pile, tile_size, Region());
+ SetupPendingTreeWithFixedTileSize(pending_raster_source, tile_size, Region());
ASSERT_TRUE(pending_layer_->CanHaveTilings());
pending_layer_->AddChild(LayerImpl::Create(host_impl_.pending_tree(), 1));
@@ -4168,11 +4127,11 @@ TEST_F(OcclusionTrackingPictureLayerImplTest, OcclusionForDifferentScales) {
pending_layer_->tilings()->RemoveAllTilings();
float low_res_factor = host_impl_.settings().low_res_contents_scale_factor;
- pending_layer_->AddTiling(low_res_factor);
- pending_layer_->AddTiling(0.3f);
- pending_layer_->AddTiling(0.7f);
- pending_layer_->AddTiling(1.0f);
- pending_layer_->AddTiling(2.0f);
+ pending_layer_->AddTiling(low_res_factor)->set_resolution(LOW_RESOLUTION);
+ pending_layer_->AddTiling(0.3f)->set_resolution(HIGH_RESOLUTION);
+ pending_layer_->AddTiling(0.7f)->set_resolution(HIGH_RESOLUTION);
+ pending_layer_->AddTiling(1.0f)->set_resolution(HIGH_RESOLUTION);
+ pending_layer_->AddTiling(2.0f)->set_resolution(HIGH_RESOLUTION);
host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));
// UpdateDrawProperties with the occluding layer.
@@ -4219,19 +4178,18 @@ TEST_F(OcclusionTrackingPictureLayerImplTest, OcclusionForDifferentScales) {
}
TEST_F(OcclusionTrackingPictureLayerImplTest, DifferentOcclusionOnTrees) {
- gfx::Size tile_size(102, 102);
gfx::Size layer_bounds(1000, 1000);
gfx::Size viewport_size(1000, 1000);
gfx::Point occluding_layer_position(310, 0);
gfx::Rect invalidation_rect(230, 230, 102, 102);
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> active_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
host_impl_.SetViewportSize(viewport_size);
- SetupPendingTree(active_pile);
+ SetupPendingTree(active_raster_source);
// Partially occlude the active layer.
pending_layer_->AddChild(LayerImpl::Create(host_impl_.pending_tree(), 2));
@@ -4265,7 +4223,7 @@ TEST_F(OcclusionTrackingPictureLayerImplTest, DifferentOcclusionOnTrees) {
}
// Partially invalidate the pending layer.
- SetupPendingTreeWithInvalidation(pending_pile, invalidation_rect);
+ SetupPendingTreeWithInvalidation(pending_raster_source, invalidation_rect);
for (size_t i = 0; i < active_layer_->num_tilings(); ++i) {
PictureLayerTiling* tiling = active_layer_->tilings()->tiling_at(i);
@@ -4278,10 +4236,16 @@ TEST_F(OcclusionTrackingPictureLayerImplTest, DifferentOcclusionOnTrees) {
if (!*iter)
continue;
const Tile* tile = *iter;
+ EXPECT_TRUE(tile);
// All tiles are unoccluded, because the pending tree has no occlusion.
EXPECT_FALSE(prioritized_tiles[tile].is_occluded());
+ if (tiling->resolution() == LOW_RESOLUTION) {
+ EXPECT_FALSE(active_layer_->GetPendingOrActiveTwinTiling(tiling));
+ continue;
+ }
+
Tile* twin_tile = active_layer_->GetPendingOrActiveTwinTiling(tiling)
->TileAt(iter.i(), iter.j());
gfx::Rect scaled_content_rect = ScaleToEnclosingRect(
@@ -4289,12 +4253,10 @@ TEST_F(OcclusionTrackingPictureLayerImplTest, DifferentOcclusionOnTrees) {
if (scaled_content_rect.Intersects(invalidation_rect)) {
// Tiles inside the invalidation rect exist on both trees.
- EXPECT_TRUE(tile);
EXPECT_TRUE(twin_tile);
EXPECT_NE(tile, twin_tile);
} else {
// Tiles outside the invalidation rect only exist on the active tree.
- EXPECT_TRUE(tile);
EXPECT_FALSE(twin_tile);
}
}
@@ -4313,14 +4275,14 @@ TEST_F(OcclusionTrackingPictureLayerImplTest,
gfx::Rect invalidation_rect(230, 230, 152, 152);
host_impl_.SetViewportSize(viewport_size);
- host_impl_.SetDeviceScaleFactor(2.f);
+ SetInitialDeviceScaleFactor(2.f);
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> active_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
- SetupPendingTreeWithFixedTileSize(active_pile, tile_size, Region());
+ SetupPendingTreeWithFixedTileSize(active_raster_source, tile_size, Region());
// Partially occlude the active layer.
pending_layer_->AddChild(LayerImpl::Create(host_impl_.pending_tree(), 2));
@@ -4334,7 +4296,8 @@ TEST_F(OcclusionTrackingPictureLayerImplTest,
// Partially invalidate the pending layer. Tiles inside the invalidation rect
// are created.
- SetupPendingTreeWithFixedTileSize(pending_pile, tile_size, invalidation_rect);
+ SetupPendingTreeWithFixedTileSize(pending_raster_source, tile_size,
+ invalidation_rect);
// Partially occlude the pending layer in a different way.
pending_layer_->AddChild(LayerImpl::Create(host_impl_.pending_tree(), 3));
@@ -4344,7 +4307,7 @@ TEST_F(OcclusionTrackingPictureLayerImplTest,
pending_occluding_layer->SetContentsOpaque(true);
pending_occluding_layer->SetPosition(pending_occluding_layer_position);
- EXPECT_EQ(2u, pending_layer_->num_tilings());
+ EXPECT_EQ(1u, pending_layer_->num_tilings());
EXPECT_EQ(2u, active_layer_->num_tilings());
host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));
@@ -4355,8 +4318,8 @@ TEST_F(OcclusionTrackingPictureLayerImplTest,
// The expected number of occluded tiles on each of the 2 tilings for each of
// the 3 tree priorities.
size_t expected_occluded_tile_count_on_pending[] = {4u, 0u};
- size_t expected_occluded_tile_count_on_active[] = {12u, 1u};
- size_t total_expected_occluded_tile_count_on_trees[] = {13u, 4u};
+ size_t expected_occluded_tile_count_on_active[] = {12u, 3u};
+ size_t total_expected_occluded_tile_count_on_trees[] = {15u, 4u};
// Verify number of occluded tiles on the pending layer for each tiling.
for (size_t i = 0; i < pending_layer_->num_tilings(); ++i) {
@@ -4450,18 +4413,17 @@ TEST_F(OcclusionTrackingPictureLayerImplTest,
}
TEST_F(PictureLayerImplTest, PendingOrActiveTwinLayer) {
- gfx::Size tile_size(102, 102);
gfx::Size layer_bounds(1000, 1000);
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- SetupPendingTree(pile);
+ scoped_refptr<FakeDisplayListRasterSource> raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
+ SetupPendingTree(raster_source);
EXPECT_FALSE(pending_layer_->GetPendingOrActiveTwinLayer());
ActivateTree();
EXPECT_FALSE(active_layer_->GetPendingOrActiveTwinLayer());
- SetupPendingTree(pile);
+ SetupPendingTree(raster_source);
EXPECT_TRUE(pending_layer_->GetPendingOrActiveTwinLayer());
EXPECT_TRUE(active_layer_->GetPendingOrActiveTwinLayer());
EXPECT_EQ(pending_layer_, active_layer_->GetPendingOrActiveTwinLayer());
@@ -4598,15 +4560,8 @@ TEST_F(PictureLayerImplTest, NonSolidToSolidNoTilings) {
TEST_F(PictureLayerImplTest, ChangeInViewportAllowsTilingUpdates) {
host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));
- gfx::Size tile_size(100, 100);
gfx::Size layer_bounds(400, 4000);
-
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
-
- SetupTrees(pending_pile, active_pile);
+ SetupDefaultTrees(layer_bounds);
Region invalidation;
gfx::Rect viewport = gfx::Rect(0, 0, 100, 100);
@@ -4664,19 +4619,14 @@ TEST_F(PictureLayerImplTest, CloneMissingRecordings) {
gfx::Size tile_size(100, 100);
gfx::Size layer_bounds(400, 400);
- scoped_refptr<FakePicturePileImpl> filled_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> filled_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
- scoped_ptr<FakePicturePile> partial_recording =
- FakePicturePile::CreateEmptyPile(tile_size, layer_bounds);
- for (int i = 1; i < partial_recording->tiling().num_tiles_x(); ++i) {
- for (int j = 1; j < partial_recording->tiling().num_tiles_y(); ++j)
- partial_recording->AddRecordingAt(i, j);
- }
- scoped_refptr<FakePicturePileImpl> partial_pile =
- FakePicturePileImpl::CreateFromPile(partial_recording.get(), nullptr);
+ scoped_refptr<FakeDisplayListRasterSource> partial_raster_source =
+ FakeDisplayListRasterSource::CreatePartiallyFilled(
+ layer_bounds, gfx::Rect(100, 100, 300, 300));
- SetupPendingTreeWithFixedTileSize(filled_pile, tile_size, Region());
+ SetupPendingTreeWithFixedTileSize(filled_raster_source, tile_size, Region());
ActivateTree();
PictureLayerTiling* pending_tiling = old_pending_layer_->HighResTiling();
@@ -4686,10 +4636,10 @@ TEST_F(PictureLayerImplTest, CloneMissingRecordings) {
EXPECT_EQ(0u, pending_tiling->AllTilesForTesting().size());
EXPECT_EQ(5u * 5u, active_tiling->AllTilesForTesting().size());
- // Now put a partially-recorded pile on the pending tree (and invalidate
- // everything, since the main thread PicturePile will invalidate dropped
- // recordings). This will cause us to be missing some tiles.
- SetupPendingTreeWithFixedTileSize(partial_pile, tile_size,
+ // Now put a partially-recorded raster source on the pending tree (and
+ // invalidate everything, since the main thread recording will invalidate
+ // dropped recordings). This will cause us to be missing some tiles.
+ SetupPendingTreeWithFixedTileSize(partial_raster_source, tile_size,
Region(gfx::Rect(layer_bounds)));
EXPECT_EQ(3u * 3u, pending_tiling->AllTilesForTesting().size());
EXPECT_FALSE(pending_tiling->TileAt(0, 0));
@@ -4708,7 +4658,7 @@ TEST_F(PictureLayerImplTest, CloneMissingRecordings) {
// Now put a full recording on the pending tree again. We'll get all our tiles
// back.
- SetupPendingTreeWithFixedTileSize(filled_pile, tile_size,
+ SetupPendingTreeWithFixedTileSize(filled_raster_source, tile_size,
Region(gfx::Rect(layer_bounds)));
EXPECT_EQ(5u * 5u, pending_tiling->AllTilesForTesting().size());
Tile* tile00 = pending_tiling->TileAt(0, 0);
@@ -4734,14 +4684,14 @@ TEST_F(PictureLayerImplTest, ScrollPastLiveTilesRectAndBack) {
gfx::Size viewport_size(100, 100);
host_impl_.SetViewportSize(viewport_size);
- host_impl_.SetDeviceScaleFactor(1.f);
+ SetInitialDeviceScaleFactor(1.f);
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> active_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
- SetupPendingTreeWithFixedTileSize(active_pile, tile_size, Region());
+ SetupPendingTreeWithFixedTileSize(active_raster_source, tile_size, Region());
ActivateTree();
EXPECT_TRUE(active_layer_->HighResTiling()->has_tiles());
@@ -4750,11 +4700,12 @@ TEST_F(PictureLayerImplTest, ScrollPastLiveTilesRectAndBack) {
gfx::Transform(), // transform
gfx::Rect(), // clip
gfx::Rect(), // viewport
- gfx::Rect(0, 1000, 100, 100), // viewport_rect_for_tile_priority
+ gfx::Rect(0, 5000, 100, 100), // viewport_rect_for_tile_priority
gfx::Transform(), // transform_for_tile_priority
false);
- SetupPendingTreeWithFixedTileSize(pending_pile, tile_size, gfx::Rect());
+ SetupPendingTreeWithFixedTileSize(pending_raster_source, tile_size,
+ gfx::Rect());
EXPECT_FALSE(pending_layer_->HighResTiling()->has_tiles());
EXPECT_TRUE(pending_layer_->HighResTiling()->live_tiles_rect().IsEmpty());
@@ -4770,7 +4721,8 @@ TEST_F(PictureLayerImplTest, ScrollPastLiveTilesRectAndBack) {
gfx::Transform(), // transform_for_tile_priority
false);
- SetupPendingTreeWithFixedTileSize(pending_pile, tile_size, gfx::Rect());
+ SetupPendingTreeWithFixedTileSize(pending_raster_source, tile_size,
+ gfx::Rect());
EXPECT_FALSE(pending_layer_->HighResTiling()->has_tiles());
EXPECT_FALSE(pending_layer_->HighResTiling()->live_tiles_rect().IsEmpty());
@@ -4782,19 +4734,13 @@ TEST_F(PictureLayerImplTest, ScrollPastLiveTilesRectAndBack) {
TEST_F(PictureLayerImplTest, ScrollPropagatesToPending) {
host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));
- gfx::Size tile_size(102, 102);
gfx::Size layer_bounds(1000, 1000);
gfx::Size viewport_size(100, 100);
host_impl_.SetViewportSize(viewport_size);
- host_impl_.SetDeviceScaleFactor(1.f);
-
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ SetInitialDeviceScaleFactor(1.f);
- SetupTrees(pending_pile, active_pile);
+ SetupDefaultTrees(layer_bounds);
active_layer_->SetCurrentScrollOffset(gfx::ScrollOffset(0.0, 50.0));
host_impl_.active_tree()->UpdateDrawProperties(false);
@@ -4819,11 +4765,11 @@ TEST_F(PictureLayerImplTest, UpdateLCDInvalidatesPendingTree) {
gfx::Size viewport_size(100, 100);
host_impl_.SetViewportSize(viewport_size);
- host_impl_.SetDeviceScaleFactor(1.f);
+ SetInitialDeviceScaleFactor(1.f);
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- SetupPendingTreeWithFixedTileSize(pending_pile, tile_size, Region());
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilledLCD(layer_bounds);
+ SetupPendingTreeWithFixedTileSize(pending_raster_source, tile_size, Region());
EXPECT_TRUE(pending_layer_->RasterSourceUsesLCDText());
EXPECT_TRUE(pending_layer_->HighResTiling()->has_tiles());
@@ -4840,7 +4786,7 @@ TEST_F(PictureLayerImplTest, UpdateLCDInvalidatesPendingTree) {
pending_layer_->UpdateCanUseLCDTextAfterCommit();
EXPECT_FALSE(pending_layer_->RasterSourceUsesLCDText());
- EXPECT_NE(pending_pile.get(), pending_layer_->raster_source());
+ EXPECT_NE(pending_raster_source.get(), pending_layer_->raster_source());
EXPECT_TRUE(pending_layer_->HighResTiling()->has_tiles());
tiles = pending_layer_->HighResTiling()->AllTilesForTesting();
prioritized_tiles = pending_layer_->HighResTiling()
@@ -4856,9 +4802,9 @@ TEST_F(PictureLayerImplTest, TilingAllTilesDone) {
gfx::Size layer_bounds(1000, 1000);
// Create tiles.
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- SetupPendingTree(pending_pile);
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
+ SetupPendingTree(pending_raster_source);
pending_layer_->SetBounds(layer_bounds);
ActivateTree();
host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting(
@@ -4966,19 +4912,11 @@ TEST_F(TileSizeTest, TileSizes) {
EXPECT_EQ(result.height(), 500 + 2);
}
-TEST_F(NoLowResPictureLayerImplTest, HighResLowResCollision) {
- gfx::Size tile_size(400, 400);
+TEST_F(NoLowResPictureLayerImplTest, LowResWasHighResCollision) {
gfx::Size layer_bounds(1300, 1900);
float low_res_factor = host_impl_.settings().low_res_contents_scale_factor;
-
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
-
- // Set up the high and low res tilings before pinch zoom.
- SetupTrees(pending_pile, active_pile);
+ SetupDefaultTrees(layer_bounds);
ResetTilingsAndRasterScales();
float page_scale = 2.f;
@@ -4996,5 +4934,67 @@ TEST_F(NoLowResPictureLayerImplTest, HighResLowResCollision) {
EXPECT_EQ(zoomed, pending_layer_->tilings()->tiling_at(0)->contents_scale());
}
+TEST_F(PictureLayerImplTest, HighResWasLowResCollision) {
+ gfx::Size layer_bounds(1300, 1900);
+
+ float low_res_factor = host_impl_.settings().low_res_contents_scale_factor;
+
+ SetupDefaultTrees(layer_bounds);
+ ResetTilingsAndRasterScales();
+
+ float page_scale = 4.f;
+ float low_res = page_scale * low_res_factor;
+ float extra_low_res = low_res * low_res_factor;
+ SetupDrawPropertiesAndUpdateTiles(active_layer_, page_scale, 1.0f, page_scale,
+ 1.0f, 0.f, false);
+ EXPECT_EQ(2u, active_layer_->tilings()->num_tilings());
+ EXPECT_EQ(page_scale,
+ active_layer_->tilings()->tiling_at(0)->contents_scale());
+ EXPECT_EQ(low_res, active_layer_->tilings()->tiling_at(1)->contents_scale());
+
+ // Grab a current low res tile.
+ PictureLayerTiling* old_low_res_tiling =
+ active_layer_->tilings()->tiling_at(1);
+ Tile* old_low_res_tile = active_layer_->tilings()->tiling_at(1)->TileAt(0, 0);
+
+ // The tiling knows it has low res content.
+ EXPECT_TRUE(active_layer_->tilings()
+ ->tiling_at(1)
+ ->may_contain_low_resolution_tiles());
+
+ host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));
+
+ // Zoom in to exactly the low res factor so that the previous low res
+ // would be equal to the current high res.
+ SetupDrawPropertiesAndUpdateTiles(active_layer_, low_res, 1.0f, low_res, 1.0f,
+ 0.f, false);
+ // 3 tilings. The old high res, the new high res (old low res) and the new low
+ // res.
+ EXPECT_EQ(3u, active_layer_->num_tilings());
+
+ PictureLayerTilingSet* tilings = active_layer_->tilings();
+ EXPECT_EQ(page_scale, tilings->tiling_at(0)->contents_scale());
+ EXPECT_EQ(low_res, tilings->tiling_at(1)->contents_scale());
+ EXPECT_EQ(extra_low_res, tilings->tiling_at(2)->contents_scale());
+
+ EXPECT_EQ(NON_IDEAL_RESOLUTION, tilings->tiling_at(0)->resolution());
+ EXPECT_EQ(HIGH_RESOLUTION, tilings->tiling_at(1)->resolution());
+ EXPECT_EQ(LOW_RESOLUTION, tilings->tiling_at(2)->resolution());
+
+ // The old low res tile was destroyed and replaced.
+ EXPECT_EQ(old_low_res_tiling, tilings->tiling_at(1));
+ EXPECT_NE(old_low_res_tile, tilings->tiling_at(1)->TileAt(0, 0));
+ EXPECT_TRUE(tilings->tiling_at(1)->TileAt(0, 0));
+
+ // New high res tiling.
+ EXPECT_FALSE(tilings->tiling_at(0)->may_contain_low_resolution_tiles());
+ // New low res tiling.
+ EXPECT_TRUE(tilings->tiling_at(2)->may_contain_low_resolution_tiles());
+
+ // This tiling will be high res now, it won't contain low res content since it
+ // was all destroyed.
+ EXPECT_FALSE(tilings->tiling_at(1)->may_contain_low_resolution_tiles());
+}
+
} // namespace
} // namespace cc
diff --git a/chromium/cc/layers/picture_layer_unittest.cc b/chromium/cc/layers/picture_layer_unittest.cc
index b607f2eff99..cb73d15a5e9 100644
--- a/chromium/cc/layers/picture_layer_unittest.cc
+++ b/chromium/cc/layers/picture_layer_unittest.cc
@@ -7,6 +7,8 @@
#include "base/thread_task_runner_handle.h"
#include "cc/layers/content_layer_client.h"
#include "cc/layers/picture_layer_impl.h"
+#include "cc/playback/display_item_list_settings.h"
+#include "cc/test/fake_display_list_recording_source.h"
#include "cc/test/fake_layer_tree_host.h"
#include "cc/test/fake_picture_layer.h"
#include "cc/test/fake_picture_layer_impl.h"
@@ -27,10 +29,10 @@ class MockContentLayerClient : public ContentLayerClient {
scoped_refptr<DisplayItemList> PaintContentsToDisplayList(
const gfx::Rect& clip,
PaintingControlSetting picture_control) override {
- NOTIMPLEMENTED();
- return nullptr;
+ return DisplayItemList::Create(clip, DisplayItemListSettings());
}
bool FillsBoundsCompletely() const override { return false; };
+ size_t GetApproximateUnsharedMemoryUsage() const override { return 0; }
};
TEST(PictureLayerTest, NoTilesIfEmptyBounds) {
@@ -77,46 +79,40 @@ TEST(PictureLayerTest, NoTilesIfEmptyBounds) {
}
TEST(PictureLayerTest, SuitableForGpuRasterization) {
+ scoped_ptr<FakeDisplayListRecordingSource> recording_source_owned(
+ new FakeDisplayListRecordingSource);
+ FakeDisplayListRecordingSource* recording_source =
+ recording_source_owned.get();
+
MockContentLayerClient client;
- scoped_refptr<PictureLayer> layer =
- PictureLayer::Create(LayerSettings(), &client);
+ scoped_refptr<FakePictureLayer> layer =
+ FakePictureLayer::CreateWithRecordingSource(
+ LayerSettings(), &client, recording_source_owned.Pass());
+
FakeLayerTreeHostClient host_client(FakeLayerTreeHostClient::DIRECT_3D);
TestTaskGraphRunner task_graph_runner;
scoped_ptr<FakeLayerTreeHost> host =
FakeLayerTreeHost::Create(&host_client, &task_graph_runner);
host->SetRootLayer(layer);
- RecordingSource* recording_source = layer->GetRecordingSourceForTesting();
+
+ // Update layers to initialize the recording source.
+ gfx::Size layer_bounds(200, 200);
+ gfx::Rect layer_rect(layer_bounds);
+ Region invalidation(layer_rect);
+ recording_source->UpdateAndExpandInvalidation(
+ &client, &invalidation, layer_bounds, layer_rect, 1,
+ RecordingSource::RECORD_NORMALLY);
// Layer is suitable for gpu rasterization by default.
EXPECT_TRUE(recording_source->IsSuitableForGpuRasterization());
EXPECT_TRUE(layer->IsSuitableForGpuRasterization());
// Veto gpu rasterization.
- recording_source->SetUnsuitableForGpuRasterizationForTesting();
+ recording_source->SetUnsuitableForGpuRasterization();
EXPECT_FALSE(recording_source->IsSuitableForGpuRasterization());
EXPECT_FALSE(layer->IsSuitableForGpuRasterization());
}
-TEST(PictureLayerTest, UseTileGridSize) {
- LayerTreeSettings settings;
- settings.default_tile_grid_size = gfx::Size(123, 123);
-
- MockContentLayerClient client;
- scoped_refptr<PictureLayer> layer =
- PictureLayer::Create(LayerSettings(), &client);
- FakeLayerTreeHostClient host_client(FakeLayerTreeHostClient::DIRECT_3D);
- TestTaskGraphRunner task_graph_runner;
- scoped_ptr<FakeLayerTreeHost> host =
- FakeLayerTreeHost::Create(&host_client, &task_graph_runner, settings);
- host->SetRootLayer(layer);
-
- // Tile-grid is set according to its setting.
- gfx::Size size =
- layer->GetRecordingSourceForTesting()->GetTileGridSizeForTesting();
- EXPECT_EQ(size.width(), 123);
- EXPECT_EQ(size.height(), 123);
-}
-
// PicturePile uses the source frame number as a unit for measuring invalidation
// frequency. When a pile moves between compositors, the frame number increases
// non-monotonically. This executes that code path under this scenario allowing
@@ -125,7 +121,6 @@ TEST(PictureLayerTest, NonMonotonicSourceFrameNumber) {
LayerTreeSettings settings;
settings.single_thread_proxy_scheduler = false;
settings.use_zero_copy = true;
- settings.use_one_copy = false;
FakeLayerTreeHostClient host_client1(FakeLayerTreeHostClient::DIRECT_3D);
FakeLayerTreeHostClient host_client2(FakeLayerTreeHostClient::DIRECT_3D);
diff --git a/chromium/cc/layers/render_surface.cc b/chromium/cc/layers/render_surface.cc
deleted file mode 100644
index 35dde100836..00000000000
--- a/chromium/cc/layers/render_surface.cc
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cc/layers/render_surface.h"
-
-#include "cc/base/math_util.h"
-#include "cc/layers/layer.h"
-#include "ui/gfx/transform.h"
-
-namespace cc {
-
-RenderSurface::RenderSurface(Layer* owning_layer)
- : owning_layer_(owning_layer),
- draw_opacity_(1),
- draw_opacity_is_animating_(false),
- target_surface_transforms_are_animating_(false),
- screen_space_transforms_are_animating_(false),
- is_clipped_(false),
- contributes_to_drawn_surface_(false),
- nearest_occlusion_immune_ancestor_(nullptr) {
-}
-
-RenderSurface::~RenderSurface() {
- for (size_t i = 0; i < layer_list_.size(); ++i) {
- DCHECK(!layer_list_.at(i)->render_surface()) <<
- "RenderSurfaces should be cleared from the contributing layers " <<
- "before destroying this surface to avoid leaking a circular " <<
- "reference on the contributing layer. Probably the " <<
- "RenderSurfaceLayerList should just be destroyed before destroying " <<
- "any RenderSurfaces on layers.";
- }
-}
-
-gfx::RectF RenderSurface::DrawableContentRect() const {
- gfx::RectF drawable_content_rect =
- MathUtil::MapClippedRect(draw_transform_, content_rect_);
- if (owning_layer_->has_replica())
- drawable_content_rect.Union(
- MathUtil::MapClippedRect(replica_draw_transform_, content_rect_));
- return drawable_content_rect;
-}
-
-void RenderSurface::ClearLayerLists() {
- layer_list_.clear();
-}
-
-} // namespace cc
diff --git a/chromium/cc/layers/render_surface.h b/chromium/cc/layers/render_surface.h
deleted file mode 100644
index 29401e29951..00000000000
--- a/chromium/cc/layers/render_surface.h
+++ /dev/null
@@ -1,147 +0,0 @@
-// Copyright 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-
-#ifndef CC_LAYERS_RENDER_SURFACE_H_
-#define CC_LAYERS_RENDER_SURFACE_H_
-
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/memory/ref_counted.h"
-#include "cc/base/cc_export.h"
-#include "cc/layers/layer_lists.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/geometry/rect_f.h"
-#include "ui/gfx/transform.h"
-
-namespace cc {
-
-class Layer;
-
-class CC_EXPORT RenderSurface {
- public:
- explicit RenderSurface(Layer* owning_layer);
- ~RenderSurface();
-
- // Returns the rect that encloses the RenderSurfaceImpl including any
- // reflection.
- gfx::RectF DrawableContentRect() const;
-
- void SetContentRect(const gfx::Rect& content_rect) {
- content_rect_ = content_rect;
- }
- gfx::Rect content_rect() const { return content_rect_; }
-
- void SetDrawOpacity(float opacity) { draw_opacity_ = opacity; }
- float draw_opacity() const { return draw_opacity_; }
-
- void SetDrawOpacityIsAnimating(bool draw_opacity_is_animating) {
- draw_opacity_is_animating_ = draw_opacity_is_animating;
- }
- bool draw_opacity_is_animating() const { return draw_opacity_is_animating_; }
-
- void SetDrawTransform(const gfx::Transform& draw_transform) {
- draw_transform_ = draw_transform;
- }
- const gfx::Transform& draw_transform() const { return draw_transform_; }
-
- void SetScreenSpaceTransform(const gfx::Transform& screen_space_transform) {
- screen_space_transform_ = screen_space_transform;
- }
- const gfx::Transform& screen_space_transform() const {
- return screen_space_transform_;
- }
-
- void SetReplicaDrawTransform(const gfx::Transform& replica_draw_transform) {
- replica_draw_transform_ = replica_draw_transform;
- }
- const gfx::Transform& replica_draw_transform() const {
- return replica_draw_transform_;
- }
-
- void SetReplicaScreenSpaceTransform(
- const gfx::Transform& replica_screen_space_transform) {
- replica_screen_space_transform_ = replica_screen_space_transform;
- }
- const gfx::Transform& replica_screen_space_transform() const {
- return replica_screen_space_transform_;
- }
-
- void SetTargetSurfaceTransformsAreAnimating(bool animating) {
- target_surface_transforms_are_animating_ = animating;
- }
- bool target_surface_transforms_are_animating() const {
- return target_surface_transforms_are_animating_;
- }
- void SetScreenSpaceTransformsAreAnimating(bool animating) {
- screen_space_transforms_are_animating_ = animating;
- }
- bool screen_space_transforms_are_animating() const {
- return screen_space_transforms_are_animating_;
- }
-
- bool is_clipped() const { return is_clipped_; }
- void SetIsClipped(bool is_clipped) { is_clipped_ = is_clipped; }
-
- gfx::Rect clip_rect() const { return clip_rect_; }
- void SetClipRect(const gfx::Rect& clip_rect) { clip_rect_ = clip_rect; }
-
- // When false, the RenderSurface does not contribute to another target
- // RenderSurface that is being drawn for the current frame. It could still be
- // drawn to as a target, but its output will not be a part of any other
- // surface.
- bool contributes_to_drawn_surface() const {
- return contributes_to_drawn_surface_;
- }
- void set_contributes_to_drawn_surface(bool contributes_to_drawn_surface) {
- contributes_to_drawn_surface_ = contributes_to_drawn_surface;
- }
-
- LayerList& layer_list() { return layer_list_; }
- // A no-op since DelegatedRendererLayers on the main thread don't have any
- // RenderPasses so they can't contribute to a surface.
- void AddContributingDelegatedRenderPassLayer(Layer* layer) {}
-
- void SetNearestOcclusionImmuneAncestor(RenderSurface* surface) {
- nearest_occlusion_immune_ancestor_ = surface;
- }
- const RenderSurface* nearest_occlusion_immune_ancestor() const {
- return nearest_occlusion_immune_ancestor_;
- }
-
- void ClearLayerLists();
-
- private:
- Layer* owning_layer_;
-
- // Uses this surface's space.
- gfx::Rect content_rect_;
-
- float draw_opacity_;
- bool draw_opacity_is_animating_;
- gfx::Transform draw_transform_;
- gfx::Transform screen_space_transform_;
- gfx::Transform replica_draw_transform_;
- gfx::Transform replica_screen_space_transform_;
- bool target_surface_transforms_are_animating_;
- bool screen_space_transforms_are_animating_;
-
- bool is_clipped_;
- bool contributes_to_drawn_surface_;
-
- // Uses the space of the surface's target surface.
- gfx::Rect clip_rect_;
-
- LayerList layer_list_;
-
- // The nearest ancestor target surface that will contain the contents of this
- // surface, and that ignores outside occlusion. This can point to itself.
- RenderSurface* nearest_occlusion_immune_ancestor_;
-
- DISALLOW_COPY_AND_ASSIGN(RenderSurface);
-};
-
-} // namespace cc
-#endif // CC_LAYERS_RENDER_SURFACE_H_
diff --git a/chromium/cc/layers/render_surface_draw_properties.cc b/chromium/cc/layers/render_surface_draw_properties.cc
new file mode 100644
index 00000000000..22131fd0424
--- /dev/null
+++ b/chromium/cc/layers/render_surface_draw_properties.cc
@@ -0,0 +1,14 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/layers/render_surface_draw_properties.h"
+
+namespace cc {
+
+RenderSurfaceDrawProperties::RenderSurfaceDrawProperties()
+ : draw_opacity(0.f), is_clipped(false) {}
+
+RenderSurfaceDrawProperties::~RenderSurfaceDrawProperties() {}
+
+} // namespace cc
diff --git a/chromium/cc/layers/render_surface_draw_properties.h b/chromium/cc/layers/render_surface_draw_properties.h
new file mode 100644
index 00000000000..f648909a81d
--- /dev/null
+++ b/chromium/cc/layers/render_surface_draw_properties.h
@@ -0,0 +1,45 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_LAYERS_RENDER_SURFACE_DRAW_PROPERTIES_H_
+#define CC_LAYERS_RENDER_SURFACE_DRAW_PROPERTIES_H_
+
+#include "cc/base/cc_export.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/transform.h"
+
+namespace cc {
+
+// Container for properties that render surfaces need to compute before they can
+// be drawn.
+struct CC_EXPORT RenderSurfaceDrawProperties {
+ RenderSurfaceDrawProperties();
+ ~RenderSurfaceDrawProperties();
+
+ float draw_opacity;
+
+ // Transforms from the surface's own space to the space of its target surface.
+ gfx::Transform draw_transform;
+
+ // Transforms from the surface's own space to the viewport.
+ gfx::Transform screen_space_transform;
+
+ // If the surface has a replica, these transform from the replica's space to
+ // the space of the target surface and the viewport.
+ gfx::Transform replica_draw_transform;
+ gfx::Transform replica_screen_space_transform;
+
+ // This is in the surface's own space.
+ gfx::Rect content_rect;
+
+ // This is in the space of the surface's target surface.
+ gfx::Rect clip_rect;
+
+ // True if the surface needs to be clipped by clip_rect.
+ bool is_clipped;
+};
+
+} // namespace cc
+
+#endif // CC_LAYERS_RENDER_SURFACE_DRAW_PROPERTIES_H_
diff --git a/chromium/cc/layers/render_surface_impl.cc b/chromium/cc/layers/render_surface_impl.cc
index ebb3016c64d..560c75c5b51 100644
--- a/chromium/cc/layers/render_surface_impl.cc
+++ b/chromium/cc/layers/render_surface_impl.cc
@@ -28,9 +28,6 @@ namespace cc {
RenderSurfaceImpl::RenderSurfaceImpl(LayerImpl* owning_layer)
: owning_layer_(owning_layer),
surface_property_changed_(false),
- draw_opacity_is_animating_(false),
- target_surface_transforms_are_animating_(false),
- screen_space_transforms_are_animating_(false),
is_clipped_(false),
contributes_to_drawn_surface_(false),
draw_opacity_(1),
@@ -44,10 +41,10 @@ RenderSurfaceImpl::~RenderSurfaceImpl() {}
gfx::RectF RenderSurfaceImpl::DrawableContentRect() const {
gfx::RectF drawable_content_rect =
- MathUtil::MapClippedRect(draw_transform_, content_rect_);
+ MathUtil::MapClippedRect(draw_transform_, gfx::RectF(content_rect_));
if (owning_layer_->has_replica()) {
- drawable_content_rect.Union(
- MathUtil::MapClippedRect(replica_draw_transform_, content_rect_));
+ drawable_content_rect.Union(MathUtil::MapClippedRect(
+ replica_draw_transform_, gfx::RectF(content_rect_)));
}
return drawable_content_rect;
@@ -74,6 +71,31 @@ int RenderSurfaceImpl::OwningLayerId() const {
return owning_layer_ ? owning_layer_->id() : 0;
}
+bool RenderSurfaceImpl::HasReplica() const {
+ return owning_layer_->has_replica();
+}
+
+const LayerImpl* RenderSurfaceImpl::ReplicaLayer() const {
+ return owning_layer_->replica_layer();
+}
+
+int RenderSurfaceImpl::TransformTreeIndex() const {
+ return owning_layer_->transform_tree_index();
+}
+
+int RenderSurfaceImpl::ClipTreeIndex() const {
+ return owning_layer_->clip_tree_index();
+}
+
+int RenderSurfaceImpl::EffectTreeIndex() const {
+ return owning_layer_->effect_tree_index();
+}
+
+int RenderSurfaceImpl::TargetEffectTreeIndex() const {
+ if (!owning_layer_->parent() || !owning_layer_->parent()->render_target())
+ return -1;
+ return owning_layer_->parent()->render_target()->effect_tree_index();
+}
void RenderSurfaceImpl::SetClipRect(const gfx::Rect& clip_rect) {
if (clip_rect_ == clip_rect)
@@ -91,6 +113,20 @@ void RenderSurfaceImpl::SetContentRect(const gfx::Rect& content_rect) {
content_rect_ = content_rect;
}
+void RenderSurfaceImpl::SetContentRectFromPropertyTrees(
+ const gfx::Rect& content_rect) {
+ if (content_rect_from_property_trees_ == content_rect)
+ return;
+
+ surface_property_changed_ = true;
+ content_rect_from_property_trees_ = content_rect;
+}
+
+void RenderSurfaceImpl::SetAccumulatedContentRect(
+ const gfx::Rect& content_rect) {
+ accumulated_content_rect_ = content_rect;
+}
+
bool RenderSurfaceImpl::SurfacePropertyChanged() const {
// Surface property changes are tracked as follows:
//
@@ -186,9 +222,9 @@ void RenderSurfaceImpl::AppendQuads(RenderPass* render_pass,
gfx::Vector2dF owning_layer_draw_scale =
MathUtil::ComputeTransform2dScaleComponents(
owning_layer_->draw_transform(), 1.f);
- gfx::SizeF unclipped_mask_target_size =
- gfx::ScaleSize(owning_layer_->bounds(), owning_layer_draw_scale.x(),
- owning_layer_draw_scale.y());
+ gfx::SizeF unclipped_mask_target_size = gfx::ScaleSize(
+ gfx::SizeF(owning_layer_->bounds()), owning_layer_draw_scale.x(),
+ owning_layer_draw_scale.y());
mask_uv_scale = gfx::Vector2dF(
content_rect_.width() / unclipped_mask_target_size.width(),
content_rect_.height() / unclipped_mask_target_size.height());
diff --git a/chromium/cc/layers/render_surface_impl.h b/chromium/cc/layers/render_surface_impl.h
index 80a4f720b7b..283f0eb47b6 100644
--- a/chromium/cc/layers/render_surface_impl.h
+++ b/chromium/cc/layers/render_surface_impl.h
@@ -54,11 +54,6 @@ class CC_EXPORT RenderSurfaceImpl {
return nearest_occlusion_immune_ancestor_;
}
- void SetDrawOpacityIsAnimating(bool draw_opacity_is_animating) {
- draw_opacity_is_animating_ = draw_opacity_is_animating;
- }
- bool draw_opacity_is_animating() const { return draw_opacity_is_animating_; }
-
SkColor GetDebugBorderColor() const;
SkColor GetReplicaDebugBorderColor() const;
@@ -92,19 +87,6 @@ class CC_EXPORT RenderSurfaceImpl {
return replica_screen_space_transform_;
}
- void SetTargetSurfaceTransformsAreAnimating(bool animating) {
- target_surface_transforms_are_animating_ = animating;
- }
- bool target_surface_transforms_are_animating() const {
- return target_surface_transforms_are_animating_;
- }
- void SetScreenSpaceTransformsAreAnimating(bool animating) {
- screen_space_transforms_are_animating_ = animating;
- }
- bool screen_space_transforms_are_animating() const {
- return screen_space_transforms_are_animating_;
- }
-
void SetIsClipped(bool is_clipped) { is_clipped_ = is_clipped; }
bool is_clipped() const { return is_clipped_; }
@@ -125,6 +107,16 @@ class CC_EXPORT RenderSurfaceImpl {
void SetContentRect(const gfx::Rect& content_rect);
gfx::Rect content_rect() const { return content_rect_; }
+ void SetContentRectFromPropertyTrees(const gfx::Rect& content_rect);
+ gfx::Rect content_rect_from_property_trees() const {
+ return content_rect_from_property_trees_;
+ }
+
+ void SetAccumulatedContentRect(const gfx::Rect& content_rect);
+ gfx::Rect accumulated_content_rect() const {
+ return accumulated_content_rect_;
+ }
+
const Occlusion& occlusion_in_content_space() const {
return occlusion_in_content_space_;
}
@@ -137,6 +129,8 @@ class CC_EXPORT RenderSurfaceImpl {
void ClearLayerLists();
int OwningLayerId() const;
+ bool HasReplica() const;
+ const LayerImpl* ReplicaLayer() const;
void ResetPropertyChangedFlag() { surface_property_changed_ = false; }
bool SurfacePropertyChanged() const;
@@ -156,15 +150,20 @@ class CC_EXPORT RenderSurfaceImpl {
AppendQuadsData* append_quads_data,
RenderPassId render_pass_id);
+ int TransformTreeIndex() const;
+ int ClipTreeIndex() const;
+ int EffectTreeIndex() const;
+ int TargetEffectTreeIndex() const;
+
private:
LayerImpl* owning_layer_;
// Uses this surface's space.
gfx::Rect content_rect_;
+ gfx::Rect content_rect_from_property_trees_;
+ // Is used to calculate the content rect from property trees.
+ gfx::Rect accumulated_content_rect_;
bool surface_property_changed_ : 1;
- bool draw_opacity_is_animating_ : 1;
- bool target_surface_transforms_are_animating_ : 1;
- bool screen_space_transforms_are_animating_ : 1;
bool is_clipped_ : 1;
bool contributes_to_drawn_surface_ : 1;
diff --git a/chromium/cc/layers/scrollbar_layer_impl_base.cc b/chromium/cc/layers/scrollbar_layer_impl_base.cc
index 1d07a8349e4..6696e498bd0 100644
--- a/chromium/cc/layers/scrollbar_layer_impl_base.cc
+++ b/chromium/cc/layers/scrollbar_layer_impl_base.cc
@@ -42,6 +42,11 @@ void ScrollbarLayerImplBase::PushPropertiesTo(LayerImpl* layer) {
PushScrollClipPropertiesTo(layer);
}
+void ScrollbarLayerImplBase::DidBecomeActive() {
+ LayerImpl::DidBecomeActive();
+ UpdatePropertyTreeOpacity();
+}
+
void ScrollbarLayerImplBase::PushScrollClipPropertiesTo(LayerImpl* layer) {
DCHECK(layer->ToScrollbarLayer());
layer->ToScrollbarLayer()->SetScrollLayerAndClipLayerByIds(ScrollLayerId(),
diff --git a/chromium/cc/layers/scrollbar_layer_impl_base.h b/chromium/cc/layers/scrollbar_layer_impl_base.h
index da7fa52d1f1..339dcc9f890 100644
--- a/chromium/cc/layers/scrollbar_layer_impl_base.h
+++ b/chromium/cc/layers/scrollbar_layer_impl_base.h
@@ -47,6 +47,7 @@ class CC_EXPORT ScrollbarLayerImplBase : public LayerImpl {
bool CanScrollOrientation() const;
void PushPropertiesTo(LayerImpl* layer) override;
+ void DidBecomeActive() override;
ScrollbarLayerImplBase* ToScrollbarLayer() override;
void PushScrollClipPropertiesTo(LayerImpl* layer);
diff --git a/chromium/cc/layers/scrollbar_layer_unittest.cc b/chromium/cc/layers/scrollbar_layer_unittest.cc
index 0042204505e..f631fcea0f7 100644
--- a/chromium/cc/layers/scrollbar_layer_unittest.cc
+++ b/chromium/cc/layers/scrollbar_layer_unittest.cc
@@ -121,7 +121,6 @@ class ScrollbarLayerTest : public testing::Test {
ScrollbarLayerTest() : fake_client_(FakeLayerTreeHostClient::DIRECT_3D) {
layer_tree_settings_.single_thread_proxy_scheduler = false;
layer_tree_settings_.use_zero_copy = true;
- layer_tree_settings_.use_one_copy = false;
LayerTreeHost::InitParams params;
params.client = &fake_client_;
@@ -488,8 +487,8 @@ TEST_F(ScrollbarLayerTest, LayerDrivenSolidColorDrawQuads) {
layer_tree_host_->CommitAndCreateLayerImplTree();
LayerImpl* scroll_layer_impl = layer_impl_tree_root->children()[0];
- ScrollbarLayerImplBase* scrollbar_layer_impl =
- static_cast<PaintedScrollbarLayerImpl*>(scroll_layer_impl->children()[1]);
+ auto* scrollbar_layer_impl =
+ static_cast<ScrollbarLayerImplBase*>(scroll_layer_impl->children()[1]);
// Choose layer bounds to give max_scroll_offset = (8, 8).
layer_impl_tree_root->SetBounds(gfx::Size(2, 2));
@@ -600,9 +599,9 @@ TEST_F(ScrollbarLayerSolidColorThumbTest, SolidColorThumbVerticalAdjust) {
layers[0]->SetBounds(gfx::Size(100, 3));
layers[1]->SetBounds(gfx::Size(3, 100));
- EXPECT_EQ(gfx::RectF(20.f, 0.f, 20.f, 3.f),
+ EXPECT_EQ(gfx::Rect(20, 0, 20, 3),
horizontal_scrollbar_layer_->ComputeThumbQuadRect());
- EXPECT_EQ(gfx::RectF(0.f, 20.f, 3.f, 20.f),
+ EXPECT_EQ(gfx::Rect(0, 20, 3, 20),
vertical_scrollbar_layer_->ComputeThumbQuadRect());
horizontal_scrollbar_layer_->SetVerticalAdjust(10.f);
@@ -713,10 +712,7 @@ class ScrollbarLayerTestResourceCreationAndRelease : public ScrollbarLayerTest {
layer_tree_root->SetScrollOffset(gfx::ScrollOffset(10, 20));
layer_tree_root->SetBounds(gfx::Size(100, 200));
content_layer->SetBounds(gfx::Size(100, 200));
- scrollbar_layer->draw_properties().visible_layer_rect =
- gfx::Rect(0, 0, 100, 200);
- scrollbar_layer->CreateRenderSurface();
- scrollbar_layer->draw_properties().render_target = scrollbar_layer.get();
+ scrollbar_layer->set_visible_layer_rect(gfx::Rect(0, 0, 100, 200));
testing::Mock::VerifyAndClearExpectations(layer_tree_host_.get());
EXPECT_EQ(scrollbar_layer->layer_tree_host(), layer_tree_host_.get());
@@ -731,8 +727,6 @@ class ScrollbarLayerTestResourceCreationAndRelease : public ScrollbarLayerTest {
EXPECT_EQ(expected_deleted, layer_tree_host_->TotalUIResourceDeleted());
testing::Mock::VerifyAndClearExpectations(layer_tree_host_.get());
-
- scrollbar_layer->ClearRenderSurface();
}
};
@@ -775,12 +769,7 @@ TEST_F(ScrollbarLayerTestResourceCreationAndRelease, TestResourceUpdate) {
scrollbar_layer->SetPosition(scrollbar_location);
layer_tree_root->SetBounds(gfx::Size(100, 200));
content_layer->SetBounds(gfx::Size(100, 200));
-
- scrollbar_layer->draw_properties().visible_layer_rect =
- gfx::Rect(0, 0, 100, 200);
-
- scrollbar_layer->CreateRenderSurface();
- scrollbar_layer->draw_properties().render_target = scrollbar_layer.get();
+ scrollbar_layer->set_visible_layer_rect(gfx::Rect(0, 0, 100, 200));
testing::Mock::VerifyAndClearExpectations(layer_tree_host_.get());
EXPECT_EQ(scrollbar_layer->layer_tree_host(), layer_tree_host_.get());
@@ -802,6 +791,7 @@ TEST_F(ScrollbarLayerTestResourceCreationAndRelease, TestResourceUpdate) {
resource_count = 0;
expected_created = 2;
expected_deleted = 2;
+ scrollbar_layer->SetBounds(gfx::Size(0, 0));
scrollbar_layer->fake_scrollbar()->set_track_rect(gfx::Rect(0, 0, 0, 0));
EXPECT_TRUE(scrollbar_layer->Update());
EXPECT_EQ(0, scrollbar_layer->track_resource_id());
@@ -824,6 +814,7 @@ TEST_F(ScrollbarLayerTestResourceCreationAndRelease, TestResourceUpdate) {
resource_count = 2;
expected_created = 4;
expected_deleted = 2;
+ scrollbar_layer->SetBounds(gfx::Size(100, 15));
scrollbar_layer->fake_scrollbar()->set_track_rect(gfx::Rect(30, 10, 50, 10));
EXPECT_TRUE(scrollbar_layer->Update());
EXPECT_NE(0, scrollbar_layer->track_resource_id());
@@ -846,6 +837,7 @@ TEST_F(ScrollbarLayerTestResourceCreationAndRelease, TestResourceUpdate) {
resource_count = 0;
expected_created = 5;
expected_deleted = 5;
+ scrollbar_layer->SetBounds(gfx::Size(0, 0));
scrollbar_layer->fake_scrollbar()->set_track_rect(gfx::Rect(0, 0, 0, 0));
EXPECT_TRUE(scrollbar_layer->Update());
EXPECT_EQ(0, scrollbar_layer->track_resource_id());
@@ -857,15 +849,27 @@ TEST_F(ScrollbarLayerTestResourceCreationAndRelease, TestResourceUpdate) {
resource_count = 2;
expected_created = 7;
expected_deleted = 5;
+ scrollbar_layer->SetBounds(gfx::Size(100, 15));
scrollbar_layer->fake_scrollbar()->set_track_rect(gfx::Rect(30, 10, 50, 10));
scrollbar_layer->fake_scrollbar()->set_has_thumb(true);
EXPECT_TRUE(scrollbar_layer->Update());
EXPECT_NE(0, scrollbar_layer->track_resource_id());
EXPECT_NE(0, scrollbar_layer->thumb_resource_id());
- resource_count = 1;
- expected_created = 8;
+ resource_count = 2;
+ expected_created = 9;
expected_deleted = 7;
+ scrollbar_layer->fake_scrollbar()->set_track_rect(gfx::Rect(0, 0, 0, 0));
+ EXPECT_TRUE(scrollbar_layer->Update());
+ EXPECT_NE(0, scrollbar_layer->track_resource_id());
+ EXPECT_NE(0, scrollbar_layer->thumb_resource_id());
+ EXPECT_EQ(resource_count, layer_tree_host_->UIResourceCount());
+ EXPECT_EQ(expected_created, layer_tree_host_->TotalUIResourceCreated());
+ EXPECT_EQ(expected_deleted, layer_tree_host_->TotalUIResourceDeleted());
+
+ resource_count = 1;
+ expected_created = 10;
+ expected_deleted = 9;
scrollbar_layer->fake_scrollbar()->set_track_rect(gfx::Rect(30, 10, 50, 10));
scrollbar_layer->fake_scrollbar()->set_has_thumb(false);
scrollbar_layer->SetBounds(gfx::Size(90, 15));
@@ -886,7 +890,6 @@ TEST_F(ScrollbarLayerTestResourceCreationAndRelease, TestResourceUpdate) {
EXPECT_EQ(expected_deleted, layer_tree_host_->TotalUIResourceDeleted());
testing::Mock::VerifyAndClearExpectations(layer_tree_host_.get());
- scrollbar_layer->ClearRenderSurface();
}
class ScaledScrollbarLayerTestResourceCreation : public ScrollbarLayerTest {
@@ -909,10 +912,8 @@ class ScaledScrollbarLayerTestResourceCreation : public ScrollbarLayerTest {
scrollbar_layer->SetPosition(scrollbar_location);
layer_tree_root->SetBounds(gfx::Size(100, 200));
content_layer->SetBounds(gfx::Size(100, 200));
- scrollbar_layer->draw_properties().visible_layer_rect =
- gfx::Rect(scrollbar_location, scrollbar_layer->bounds());
- scrollbar_layer->CreateRenderSurface();
- scrollbar_layer->draw_properties().render_target = scrollbar_layer.get();
+ scrollbar_layer->set_visible_layer_rect(
+ gfx::Rect(scrollbar_location, scrollbar_layer->bounds()));
testing::Mock::VerifyAndClearExpectations(layer_tree_host_.get());
EXPECT_EQ(scrollbar_layer->layer_tree_host(), layer_tree_host_.get());
@@ -940,8 +941,6 @@ class ScaledScrollbarLayerTestResourceCreation : public ScrollbarLayerTest {
scrollbar_layer->internal_content_bounds().height());
testing::Mock::VerifyAndClearExpectations(layer_tree_host_.get());
-
- scrollbar_layer->ClearRenderSurface();
}
};
@@ -971,7 +970,7 @@ class ScaledScrollbarLayerTestScaledRasterization : public ScrollbarLayerTest {
scrollbar_layer->SetPosition(scrollbar_rect.origin());
scrollbar_layer->fake_scrollbar()->set_location(scrollbar_rect.origin());
scrollbar_layer->fake_scrollbar()->set_track_rect(scrollbar_rect);
- scrollbar_layer->draw_properties().visible_layer_rect = scrollbar_rect;
+ scrollbar_layer->set_visible_layer_rect(scrollbar_rect);
layer_tree_host_->SetDeviceScaleFactor(test_scale);
diff --git a/chromium/cc/layers/solid_color_layer_impl_unittest.cc b/chromium/cc/layers/solid_color_layer_impl_unittest.cc
index 59ef6ba70fa..a27f22971d0 100644
--- a/chromium/cc/layers/solid_color_layer_impl_unittest.cc
+++ b/chromium/cc/layers/solid_color_layer_impl_unittest.cc
@@ -113,7 +113,7 @@ TEST(SolidColorLayerImplTest, VerifyCorrectBlendModeInQuad) {
scoped_ptr<SolidColorLayerImpl> layer =
SolidColorLayerImpl::Create(host_impl.active_tree(), 1);
layer->SetBounds(layer_size);
- layer->draw_properties().blend_mode = blend_mode;
+ layer->set_draw_blend_mode(blend_mode);
AppendQuadsData data;
layer->AppendQuads(render_pass.get(), &data);
@@ -143,9 +143,8 @@ TEST(SolidColorLayerImplTest, VerifyOpaqueRect) {
FakeLayerTreeHost::Create(&client, &task_graph_runner);
host->SetRootLayer(root);
- RenderSurfaceLayerList render_surface_layer_list;
- LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
- root.get(), gfx::Size(500, 500), &render_surface_layer_list);
+ LayerTreeHostCommon::CalcDrawPropsMainInputs inputs(root.get(),
+ gfx::Size(500, 500));
LayerTreeHostCommon::CalculateDrawProperties(&inputs);
EXPECT_FALSE(layer->contents_opaque());
diff --git a/chromium/cc/layers/solid_color_scrollbar_layer_impl.cc b/chromium/cc/layers/solid_color_scrollbar_layer_impl.cc
index 0b78de7f8c7..beb9cb6886d 100644
--- a/chromium/cc/layers/solid_color_scrollbar_layer_impl.cc
+++ b/chromium/cc/layers/solid_color_scrollbar_layer_impl.cc
@@ -116,4 +116,8 @@ void SolidColorScrollbarLayerImpl::AppendQuads(
shared_quad_state, thumb_quad_rect, visible_quad_rect, color_, false);
}
+const char* SolidColorScrollbarLayerImpl::LayerTypeAsString() const {
+ return "cc::SolidColorScrollbarLayerImpl";
+}
+
} // namespace cc
diff --git a/chromium/cc/layers/solid_color_scrollbar_layer_impl.h b/chromium/cc/layers/solid_color_scrollbar_layer_impl.h
index df6179d3ef6..1cb03c76269 100644
--- a/chromium/cc/layers/solid_color_scrollbar_layer_impl.h
+++ b/chromium/cc/layers/solid_color_scrollbar_layer_impl.h
@@ -46,6 +46,8 @@ class CC_EXPORT SolidColorScrollbarLayerImpl : public ScrollbarLayerImplBase {
bool IsThumbResizable() const override;
private:
+ const char* LayerTypeAsString() const override;
+
int thumb_thickness_;
int track_start_;
SkColor color_;
diff --git a/chromium/cc/layers/surface_layer_impl.cc b/chromium/cc/layers/surface_layer_impl.cc
index 0cd4f248645..546af40c522 100644
--- a/chromium/cc/layers/surface_layer_impl.cc
+++ b/chromium/cc/layers/surface_layer_impl.cc
@@ -6,6 +6,7 @@
#include "base/trace_event/trace_event_argument.h"
#include "cc/debug/debug_colors.h"
+#include "cc/quads/solid_color_draw_quad.h"
#include "cc/quads/surface_draw_quad.h"
#include "cc/trees/occlusion.h"
@@ -57,13 +58,12 @@ void SurfaceLayerImpl::PushPropertiesTo(LayerImpl* layer) {
void SurfaceLayerImpl::AppendQuads(RenderPass* render_pass,
AppendQuadsData* append_quads_data) {
+ AppendRainbowDebugBorder(render_pass);
+
SharedQuadState* shared_quad_state =
render_pass->CreateAndAppendSharedQuadState();
PopulateScaledSharedQuadState(shared_quad_state, surface_scale_);
- AppendDebugBorderQuad(render_pass, surface_size_, shared_quad_state,
- append_quads_data);
-
if (surface_id_.is_null())
return;
@@ -85,6 +85,93 @@ void SurfaceLayerImpl::GetDebugBorderProperties(SkColor* color,
*width = DebugColors::SurfaceLayerBorderWidth(layer_tree_impl());
}
+void SurfaceLayerImpl::AppendRainbowDebugBorder(RenderPass* render_pass) {
+ if (!ShowDebugBorders())
+ return;
+
+ SharedQuadState* shared_quad_state =
+ render_pass->CreateAndAppendSharedQuadState();
+ PopulateSharedQuadState(shared_quad_state);
+
+ SkColor color;
+ float border_width;
+ GetDebugBorderProperties(&color, &border_width);
+
+ SkColor colors[] = {
+ 0x80ff0000, // Red.
+ 0x80ffa500, // Orange.
+ 0x80ffff00, // Yellow.
+ 0x80008000, // Green.
+ 0x800000ff, // Blue.
+ 0x80ee82ee, // Violet.
+ };
+ const int kNumColors = arraysize(colors);
+
+ const int kStripeWidth = 300;
+ const int kStripeHeight = 300;
+
+ for (int i = 0;; ++i) {
+ // For horizontal lines.
+ int x = kStripeWidth * i;
+ int width = std::min(kStripeWidth, bounds().width() - x - 1);
+
+ // For vertical lines.
+ int y = kStripeHeight * i;
+ int height = std::min(kStripeHeight, bounds().height() - y - 1);
+
+ gfx::Rect top(x, 0, width, border_width);
+ gfx::Rect bottom(x, bounds().height() - border_width, width, border_width);
+ gfx::Rect left(0, y, border_width, height);
+ gfx::Rect right(bounds().width() - border_width, y, border_width, height);
+
+ if (top.IsEmpty() && left.IsEmpty())
+ break;
+
+ if (!top.IsEmpty()) {
+ bool force_anti_aliasing_off = false;
+ SolidColorDrawQuad* top_quad =
+ render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
+ top_quad->SetNew(shared_quad_state, top, top, colors[i % kNumColors],
+ force_anti_aliasing_off);
+
+ SolidColorDrawQuad* bottom_quad =
+ render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
+ bottom_quad->SetNew(shared_quad_state, bottom, bottom,
+ colors[kNumColors - 1 - (i % kNumColors)],
+ force_anti_aliasing_off);
+
+ if (contents_opaque()) {
+ // Draws a stripe filling the layer vertically with the same color and
+ // width as the horizontal stipes along the layer's top border.
+ SolidColorDrawQuad* solid_quad =
+ render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
+ // The inner fill is more transparent then the border.
+ static const float kFillOpacity = 0.1f;
+ SkColor fill_color = SkColorSetA(
+ colors[i % kNumColors],
+ static_cast<uint8_t>(SkColorGetA(colors[i % kNumColors]) *
+ kFillOpacity));
+ gfx::Rect fill_rect(x, 0, width, bounds().height());
+ solid_quad->SetNew(shared_quad_state, fill_rect, fill_rect, fill_color,
+ force_anti_aliasing_off);
+ }
+ }
+ if (!left.IsEmpty()) {
+ bool force_anti_aliasing_off = false;
+ SolidColorDrawQuad* left_quad =
+ render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
+ left_quad->SetNew(shared_quad_state, left, left,
+ colors[kNumColors - 1 - (i % kNumColors)],
+ force_anti_aliasing_off);
+
+ SolidColorDrawQuad* right_quad =
+ render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
+ right_quad->SetNew(shared_quad_state, right, right,
+ colors[i % kNumColors], force_anti_aliasing_off);
+ }
+ }
+}
+
void SurfaceLayerImpl::AsValueInto(base::trace_event::TracedValue* dict) const {
LayerImpl::AsValueInto(dict);
dict->SetInteger("surface_id", surface_id_.id);
diff --git a/chromium/cc/layers/surface_layer_impl.h b/chromium/cc/layers/surface_layer_impl.h
index b190b3af940..2bf6a9a008a 100644
--- a/chromium/cc/layers/surface_layer_impl.h
+++ b/chromium/cc/layers/surface_layer_impl.h
@@ -34,6 +34,7 @@ class CC_EXPORT SurfaceLayerImpl : public LayerImpl {
private:
void GetDebugBorderProperties(SkColor* color, float* width) const override;
+ void AppendRainbowDebugBorder(RenderPass* render_pass);
void AsValueInto(base::trace_event::TracedValue* dict) const override;
const char* LayerTypeAsString() const override;
diff --git a/chromium/cc/layers/surface_layer_unittest.cc b/chromium/cc/layers/surface_layer_unittest.cc
index eac14a0c245..e35b88683d8 100644
--- a/chromium/cc/layers/surface_layer_unittest.cc
+++ b/chromium/cc/layers/surface_layer_unittest.cc
@@ -143,23 +143,43 @@ class SurfaceLayerSwapPromise : public LayerTreeTest {
gfx::Size bounds(100, 100);
layer_tree_host()->SetViewportSize(bounds);
+
+ blank_layer_ = SolidColorLayer::Create(layer_settings());
+ blank_layer_->SetIsDrawable(true);
+ blank_layer_->SetBounds(gfx::Size(10, 10));
+
PostSetNeedsCommitToMainThread();
}
+ virtual void ChangeTree() = 0;
+
void DidCommitAndDrawFrame() override {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::Bind(&SurfaceLayerSwapPromise::ChangeTree,
base::Unretained(this)));
}
- void ChangeTree() {
+ protected:
+ int commit_count_;
+ bool sequence_was_satisfied_;
+ scoped_refptr<SurfaceLayer> layer_;
+ scoped_refptr<Layer> blank_layer_;
+ SurfaceSequence satisfied_sequence_;
+
+ SurfaceId required_id_;
+ std::set<SurfaceSequence> required_set_;
+};
+
+// Check that SurfaceSequence is sent through swap promise.
+class SurfaceLayerSwapPromiseWithDraw : public SurfaceLayerSwapPromise {
+ public:
+ SurfaceLayerSwapPromiseWithDraw() : SurfaceLayerSwapPromise() {}
+
+ void ChangeTree() override {
++commit_count_;
switch (commit_count_) {
case 1:
// Remove SurfaceLayer from tree to cause SwapPromise to be created.
- blank_layer_ = SolidColorLayer::Create(layer_settings());
- blank_layer_->SetIsDrawable(true);
- blank_layer_->SetBounds(gfx::Size(10, 10));
layer_tree_host()->SetRootLayer(blank_layer_);
break;
case 2:
@@ -193,21 +213,49 @@ class SurfaceLayerSwapPromise : public LayerTreeTest {
// callback.
EXPECT_TRUE(satisfied_sequence_.is_null());
}
-
- private:
- int commit_count_;
- bool sequence_was_satisfied_;
- scoped_refptr<SurfaceLayer> layer_;
- scoped_refptr<Layer> blank_layer_;
- SurfaceSequence satisfied_sequence_;
-
- SurfaceId required_id_;
- std::set<SurfaceSequence> required_set_;
};
// TODO(jbauman): Reenable on single thread once http://crbug.com/421923 is
// fixed.
-MULTI_THREAD_TEST_F(SurfaceLayerSwapPromise);
+MULTI_THREAD_TEST_F(SurfaceLayerSwapPromiseWithDraw);
+
+// Check that SurfaceSequence is sent through swap promise and resolved when
+// swap fails.
+class SurfaceLayerSwapPromiseWithoutDraw : public SurfaceLayerSwapPromise {
+ public:
+ SurfaceLayerSwapPromiseWithoutDraw() : SurfaceLayerSwapPromise() {}
+
+ DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
+ LayerTreeHostImpl::FrameData* frame,
+ DrawResult draw_result) override {
+ return DRAW_ABORTED_MISSING_HIGH_RES_CONTENT;
+ }
+
+ void ChangeTree() override {
+ ++commit_count_;
+ switch (commit_count_) {
+ case 1:
+ // Remove SurfaceLayer from tree to cause SwapPromise to be created.
+ layer_tree_host()->SetRootLayer(blank_layer_);
+ break;
+ case 2:
+ layer_tree_host()->SetNeedsCommit();
+ break;
+ default:
+ EndTest();
+ break;
+ }
+ }
+
+ void AfterTest() override {
+ EXPECT_TRUE(required_id_ == SurfaceId(1));
+ EXPECT_EQ(1u, required_set_.size());
+ // Sequence should have been satisfied with the callback.
+ EXPECT_TRUE(satisfied_sequence_ == SurfaceSequence(1u, 1u));
+ }
+};
+
+MULTI_THREAD_TEST_F(SurfaceLayerSwapPromiseWithoutDraw);
} // namespace
} // namespace cc
diff --git a/chromium/cc/layers/texture_layer.cc b/chromium/cc/layers/texture_layer.cc
index 20741fddad8..c9fb61b86a0 100644
--- a/chromium/cc/layers/texture_layer.cc
+++ b/chromium/cc/layers/texture_layer.cc
@@ -34,7 +34,6 @@ TextureLayer::TextureLayer(const LayerSettings& settings,
uv_bottom_right_(1.f, 1.f),
premultiplied_alpha_(true),
blend_background_color_(false),
- rate_limit_context_(false),
needs_set_mailbox_(false) {
vertex_opacity_[0] = 1.0f;
vertex_opacity_[1] = 1.0f;
@@ -46,8 +45,6 @@ TextureLayer::~TextureLayer() {
}
void TextureLayer::ClearClient() {
- if (rate_limit_context_ && client_ && layer_tree_host())
- layer_tree_host()->StopRateLimiter();
client_ = nullptr;
ClearTexture();
UpdateDrawsContent(HasDrawableContent());
@@ -118,13 +115,6 @@ void TextureLayer::SetBlendBackgroundColor(bool blend) {
SetNeedsCommit();
}
-void TextureLayer::SetRateLimitContext(bool rate_limit) {
- if (!rate_limit && rate_limit_context_ && client_ && layer_tree_host())
- layer_tree_host()->StopRateLimiter();
-
- rate_limit_context_ = rate_limit;
-}
-
void TextureLayer::SetTextureMailboxInternal(
const TextureMailbox& mailbox,
scoped_ptr<SingleReleaseCallback> release_callback,
@@ -185,9 +175,6 @@ void TextureLayer::SetTextureMailboxWithoutReleaseCallback(
void TextureLayer::SetNeedsDisplayRect(const gfx::Rect& dirty_rect) {
Layer::SetNeedsDisplayRect(dirty_rect);
-
- if (rate_limit_context_ && client_ && layer_tree_host() && DrawsContent())
- layer_tree_host()->StartRateLimiter();
}
void TextureLayer::SetLayerTreeHost(LayerTreeHost* host) {
@@ -196,10 +183,6 @@ void TextureLayer::SetLayerTreeHost(LayerTreeHost* host) {
return;
}
- if (layer_tree_host()) {
- if (rate_limit_context_ && client_)
- layer_tree_host()->StopRateLimiter();
- }
// If we're removed from the tree, the TextureLayerImpl will be destroyed, and
// we will need to set the mailbox again on a new TextureLayerImpl the next
// time we push.
diff --git a/chromium/cc/layers/texture_layer.h b/chromium/cc/layers/texture_layer.h
index 53f2d8d4065..0c0b2ec237d 100644
--- a/chromium/cc/layers/texture_layer.h
+++ b/chromium/cc/layers/texture_layer.h
@@ -124,11 +124,6 @@ class CC_EXPORT TextureLayer : public Layer {
// at draw time. Defaults to false.
void SetBlendBackgroundColor(bool blend);
- // Sets whether this context should rate limit on damage to prevent too many
- // frames from being queued up before the compositor gets a chance to run.
- // Requires a non-nil client. Defaults to false.
- void SetRateLimitContext(bool rate_limit);
-
// Code path for plugins which supply their own mailbox.
void SetTextureMailbox(const TextureMailbox& mailbox,
scoped_ptr<SingleReleaseCallback> release_callback);
@@ -167,7 +162,6 @@ class CC_EXPORT TextureLayer : public Layer {
float vertex_opacity_[4];
bool premultiplied_alpha_;
bool blend_background_color_;
- bool rate_limit_context_;
scoped_ptr<TextureMailboxHolder::MainThreadReference> holder_ref_;
bool needs_set_mailbox_;
diff --git a/chromium/cc/layers/texture_layer_unittest.cc b/chromium/cc/layers/texture_layer_unittest.cc
index 97bb7a15b20..8c138c35bd4 100644
--- a/chromium/cc/layers/texture_layer_unittest.cc
+++ b/chromium/cc/layers/texture_layer_unittest.cc
@@ -11,6 +11,7 @@
#include "base/callback.h"
#include "base/location.h"
#include "base/single_thread_task_runner.h"
+#include "base/synchronization/lock.h"
#include "base/synchronization/waitable_event.h"
#include "base/thread_task_runner_handle.h"
#include "base/threading/thread.h"
@@ -188,6 +189,7 @@ class TextureLayerTest : public testing::Test {
TextureLayerTest()
: fake_client_(
FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D)),
+ output_surface_(FakeOutputSurface::Create3d()),
host_impl_(&proxy_, &shared_bitmap_manager_, &task_graph_runner_),
test_data_(&shared_bitmap_manager_) {}
@@ -213,6 +215,7 @@ class TextureLayerTest : public testing::Test {
FakeLayerTreeHostClient fake_client_;
TestSharedBitmapManager shared_bitmap_manager_;
TestTaskGraphRunner task_graph_runner_;
+ scoped_ptr<OutputSurface> output_surface_;
FakeLayerTreeHostImpl host_impl_;
CommonMailboxObjects test_data_;
LayerSettings layer_settings_;
@@ -235,55 +238,6 @@ TEST_F(TextureLayerTest, CheckPropertyChangeCausesCorrectBehavior) {
EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetBlendBackgroundColor(true));
}
-TEST_F(TextureLayerTest, RateLimiter) {
- FakeTextureLayerClient client;
- scoped_refptr<TextureLayer> test_layer =
- TextureLayer::CreateForMailbox(layer_settings_, &client);
- test_layer->SetIsDrawable(true);
- EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
- layer_tree_host_->SetRootLayer(test_layer);
-
- // Don't rate limit until we invalidate.
- EXPECT_CALL(*layer_tree_host_, StartRateLimiter()).Times(0);
- test_layer->SetRateLimitContext(true);
- Mock::VerifyAndClearExpectations(layer_tree_host_.get());
-
- // Do rate limit after we invalidate.
- EXPECT_CALL(*layer_tree_host_, StartRateLimiter());
- test_layer->SetNeedsDisplay();
- Mock::VerifyAndClearExpectations(layer_tree_host_.get());
-
- // Stop rate limiter when we don't want it any more.
- EXPECT_CALL(*layer_tree_host_, StopRateLimiter());
- test_layer->SetRateLimitContext(false);
- Mock::VerifyAndClearExpectations(layer_tree_host_.get());
-
- // Or we clear the client.
- test_layer->SetRateLimitContext(true);
- EXPECT_CALL(*layer_tree_host_, StopRateLimiter());
- EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
- test_layer->ClearClient();
- Mock::VerifyAndClearExpectations(layer_tree_host_.get());
-
- // Reset to a layer with a client, that started the rate limiter.
- test_layer = TextureLayer::CreateForMailbox(layer_settings_, &client);
- test_layer->SetIsDrawable(true);
- test_layer->SetRateLimitContext(true);
- EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
- layer_tree_host_->SetRootLayer(test_layer);
- EXPECT_CALL(*layer_tree_host_, StartRateLimiter()).Times(0);
- Mock::VerifyAndClearExpectations(layer_tree_host_.get());
- EXPECT_CALL(*layer_tree_host_, StartRateLimiter());
- test_layer->SetNeedsDisplay();
- Mock::VerifyAndClearExpectations(layer_tree_host_.get());
-
- // Stop rate limiter when we're removed from the tree.
- EXPECT_CALL(*layer_tree_host_, StopRateLimiter());
- EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1);
- layer_tree_host_->SetRootLayer(nullptr);
- Mock::VerifyAndClearExpectations(layer_tree_host_.get());
-}
-
class TestMailboxHolder : public TextureLayer::TextureMailboxHolder {
public:
using TextureLayer::TextureMailboxHolder::Create;
@@ -823,10 +777,19 @@ class TextureLayerMailboxIsActivatedDuringCommit : public LayerTreeTest {
}
void WillActivateTreeOnThread(LayerTreeHostImpl* impl) override {
+ base::AutoLock lock(activate_count_lock_);
++activate_count_;
}
void DidCommit() override {
+ // The first frame doesn't cause anything to be returned so it does not
+ // need to wait for activation.
+ if (layer_tree_host()->source_frame_number() > 1) {
+ base::AutoLock lock(activate_count_lock_);
+ // The activate happened before commit is done on the main side.
+ EXPECT_EQ(activate_count_, layer_tree_host()->source_frame_number());
+ }
+
switch (layer_tree_host()->source_frame_number()) {
case 1:
// The first mailbox has been activated. Set a new mailbox, and
@@ -846,31 +809,14 @@ class TextureLayerMailboxIsActivatedDuringCommit : public LayerTreeTest {
}
void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
- switch (host_impl->active_tree()->source_frame_number()) {
- case 0: {
- // The activate for the 1st mailbox should have happened before now.
- EXPECT_EQ(1, activate_count_);
- break;
- }
- case 1: {
- // The activate for the 2nd mailbox should have happened before now.
- EXPECT_EQ(2, activate_count_);
- break;
- }
- case 2: {
- // The activate to remove the layer should have happened before now.
- EXPECT_EQ(3, activate_count_);
- break;
- }
- case 3: {
- NOTREACHED();
- break;
- }
- }
+ // The activate didn't happen before commit is done on the impl side (but it
+ // should happen before the main thread is done).
+ EXPECT_EQ(activate_count_, host_impl->sync_tree()->source_frame_number());
}
void AfterTest() override {}
+ base::Lock activate_count_lock_;
int activate_count_;
scoped_refptr<Layer> root_;
scoped_refptr<TextureLayer> layer_;
@@ -889,7 +835,7 @@ class TextureLayerImplWithMailboxTest : public TextureLayerTest {
TextureLayerTest::SetUp();
layer_tree_host_ =
MockLayerTreeHost::Create(&fake_client_, &task_graph_runner_);
- EXPECT_TRUE(host_impl_.InitializeRenderer(FakeOutputSurface::Create3d()));
+ EXPECT_TRUE(host_impl_.InitializeRenderer(output_surface_.get()));
}
bool WillDraw(TextureLayerImpl* layer, DrawMode mode) {
diff --git a/chromium/cc/layers/ui_resource_layer_impl_unittest.cc b/chromium/cc/layers/ui_resource_layer_impl_unittest.cc
index e31d68ae6e5..826c53f8181 100644
--- a/chromium/cc/layers/ui_resource_layer_impl_unittest.cc
+++ b/chromium/cc/layers/ui_resource_layer_impl_unittest.cc
@@ -60,9 +60,10 @@ TEST(UIResourceLayerImplTest, VerifyDrawQuads) {
FakeImplProxy proxy;
TestSharedBitmapManager shared_bitmap_manager;
TestTaskGraphRunner task_graph_runner;
+ scoped_ptr<OutputSurface> output_surface = FakeOutputSurface::Create3d();
FakeUIResourceLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager,
&task_graph_runner);
- host_impl.InitializeRenderer(FakeOutputSurface::Create3d());
+ host_impl.InitializeRenderer(output_surface.get());
// Make sure we're appending quads when there are valid values.
gfx::Size bitmap_size(100, 100);
@@ -106,9 +107,10 @@ TEST(UIResourceLayerImplTest, VerifySetOpaqueOnSkBitmap) {
FakeImplProxy proxy;
TestSharedBitmapManager shared_bitmap_manager;
TestTaskGraphRunner task_graph_runner;
+ scoped_ptr<OutputSurface> output_surface = FakeOutputSurface::Create3d();
FakeUIResourceLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager,
&task_graph_runner);
- host_impl.InitializeRenderer(FakeOutputSurface::Create3d());
+ host_impl.InitializeRenderer(output_surface.get());
gfx::Size bitmap_size(100, 100);
gfx::Size layer_size(100, 100);;
@@ -136,9 +138,10 @@ TEST(UIResourceLayerImplTest, VerifySetOpaqueOnLayer) {
FakeImplProxy proxy;
TestSharedBitmapManager shared_bitmap_manager;
TestTaskGraphRunner task_graph_runner;
+ scoped_ptr<OutputSurface> output_surface = FakeOutputSurface::Create3d();
FakeUIResourceLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager,
&task_graph_runner);
- host_impl.InitializeRenderer(FakeOutputSurface::Create3d());
+ host_impl.InitializeRenderer(output_surface.get());
gfx::Size bitmap_size(100, 100);
gfx::Size layer_size(100, 100);
diff --git a/chromium/cc/layers/video_frame_provider_client_impl_unittest.cc b/chromium/cc/layers/video_frame_provider_client_impl_unittest.cc
index 05385e46e56..4cbd493e0d5 100644
--- a/chromium/cc/layers/video_frame_provider_client_impl_unittest.cc
+++ b/chromium/cc/layers/video_frame_provider_client_impl_unittest.cc
@@ -31,7 +31,7 @@ class VideoFrameProviderClientImplTest : public testing::Test,
VideoFrameProviderClientImplTest()
: client_impl_(VideoFrameProviderClientImpl::Create(&provider_, this)),
video_layer_impl_(nullptr),
- test_frame_(media::VideoFrame::CreateFrame(media::VideoFrame::YV12,
+ test_frame_(media::VideoFrame::CreateFrame(media::PIXEL_FORMAT_YV12,
gfx::Size(10, 10),
gfx::Rect(10, 10),
gfx::Size(10, 10),
diff --git a/chromium/cc/layers/video_layer_impl.cc b/chromium/cc/layers/video_layer_impl.cc
index 2233583ed09..3313aa5cfb1 100644
--- a/chromium/cc/layers/video_layer_impl.cc
+++ b/chromium/cc/layers/video_layer_impl.cc
@@ -225,10 +225,9 @@ void VideoLayerImpl::AppendQuads(RenderPass* render_pass,
int videoframe_color_space;
if (frame_->metadata()->GetInteger(media::VideoFrameMetadata::COLOR_SPACE,
&videoframe_color_space)) {
- if (videoframe_color_space == media::VideoFrame::COLOR_SPACE_JPEG) {
+ if (videoframe_color_space == media::COLOR_SPACE_JPEG) {
color_space = YUVVideoDrawQuad::JPEG;
- } else if (videoframe_color_space ==
- media::VideoFrame::COLOR_SPACE_HD_REC709) {
+ } else if (videoframe_color_space == media::COLOR_SPACE_HD_REC709) {
color_space = YUVVideoDrawQuad::REC_709;
}
}
@@ -237,7 +236,7 @@ void VideoLayerImpl::AppendQuads(RenderPass* render_pass,
gfx::Size uv_tex_size;
if (frame_->HasTextures()) {
- DCHECK_EQ(media::VideoFrame::I420, frame_->format());
+ DCHECK_EQ(media::PIXEL_FORMAT_I420, frame_->format());
DCHECK_EQ(3u, frame_resources_.size()); // Alpha is not supported yet.
DCHECK(visible_rect.origin().IsOrigin());
DCHECK(visible_rect.size() == coded_size);
@@ -328,7 +327,8 @@ void VideoLayerImpl::AppendQuads(RenderPass* render_pass,
io_surface_quad->SetNew(shared_quad_state, quad_rect, opaque_rect,
visible_quad_rect, visible_rect.size(),
frame_resources_[0].id,
- IOSurfaceDrawQuad::UNFLIPPED);
+ IOSurfaceDrawQuad::UNFLIPPED,
+ frame_resources_[0].allow_overlay);
ValidateQuadResources(io_surface_quad);
break;
}
diff --git a/chromium/cc/layers/video_layer_impl_unittest.cc b/chromium/cc/layers/video_layer_impl_unittest.cc
index da2de85d9ef..28ba58acc2d 100644
--- a/chromium/cc/layers/video_layer_impl_unittest.cc
+++ b/chromium/cc/layers/video_layer_impl_unittest.cc
@@ -35,12 +35,9 @@ TEST(VideoLayerImplTest, Occlusion) {
LayerTestCommon::LayerImplTest impl;
DebugSetImplThreadAndMainThreadBlocked(impl.proxy());
- scoped_refptr<media::VideoFrame> video_frame =
- media::VideoFrame::CreateFrame(media::VideoFrame::YV12,
- gfx::Size(10, 10),
- gfx::Rect(10, 10),
- gfx::Size(10, 10),
- base::TimeDelta());
+ scoped_refptr<media::VideoFrame> video_frame = media::VideoFrame::CreateFrame(
+ media::PIXEL_FORMAT_YV12, gfx::Size(10, 10), gfx::Rect(10, 10),
+ gfx::Size(10, 10), base::TimeDelta());
FakeVideoFrameProvider provider;
provider.set_frame(video_frame);
@@ -118,7 +115,7 @@ TEST(VideoLayerImplTest, OccludesOtherLayers) {
EXPECT_FALSE(draw_properties.occlusion_in_content_space.IsOccluded(visible));
scoped_refptr<media::VideoFrame> video_frame = media::VideoFrame::CreateFrame(
- media::VideoFrame::YV12, gfx::Size(10, 10), gfx::Rect(10, 10),
+ media::PIXEL_FORMAT_YV12, gfx::Size(10, 10), gfx::Rect(10, 10),
gfx::Size(10, 10), base::TimeDelta());
provider.set_frame(video_frame);
active_tree->set_needs_update_draw_properties();
@@ -152,12 +149,9 @@ TEST(VideoLayerImplTest, Rotated0) {
LayerTestCommon::LayerImplTest impl;
DebugSetImplThreadAndMainThreadBlocked(impl.proxy());
- scoped_refptr<media::VideoFrame> video_frame =
- media::VideoFrame::CreateFrame(media::VideoFrame::YV12,
- gfx::Size(20, 10),
- gfx::Rect(20, 10),
- gfx::Size(20, 10),
- base::TimeDelta());
+ scoped_refptr<media::VideoFrame> video_frame = media::VideoFrame::CreateFrame(
+ media::PIXEL_FORMAT_YV12, gfx::Size(20, 10), gfx::Rect(20, 10),
+ gfx::Size(20, 10), base::TimeDelta());
FakeVideoFrameProvider provider;
provider.set_frame(video_frame);
@@ -191,12 +185,9 @@ TEST(VideoLayerImplTest, Rotated90) {
LayerTestCommon::LayerImplTest impl;
DebugSetImplThreadAndMainThreadBlocked(impl.proxy());
- scoped_refptr<media::VideoFrame> video_frame =
- media::VideoFrame::CreateFrame(media::VideoFrame::YV12,
- gfx::Size(20, 10),
- gfx::Rect(20, 10),
- gfx::Size(20, 10),
- base::TimeDelta());
+ scoped_refptr<media::VideoFrame> video_frame = media::VideoFrame::CreateFrame(
+ media::PIXEL_FORMAT_YV12, gfx::Size(20, 10), gfx::Rect(20, 10),
+ gfx::Size(20, 10), base::TimeDelta());
FakeVideoFrameProvider provider;
provider.set_frame(video_frame);
@@ -230,12 +221,9 @@ TEST(VideoLayerImplTest, Rotated180) {
LayerTestCommon::LayerImplTest impl;
DebugSetImplThreadAndMainThreadBlocked(impl.proxy());
- scoped_refptr<media::VideoFrame> video_frame =
- media::VideoFrame::CreateFrame(media::VideoFrame::YV12,
- gfx::Size(20, 10),
- gfx::Rect(20, 10),
- gfx::Size(20, 10),
- base::TimeDelta());
+ scoped_refptr<media::VideoFrame> video_frame = media::VideoFrame::CreateFrame(
+ media::PIXEL_FORMAT_YV12, gfx::Size(20, 10), gfx::Rect(20, 10),
+ gfx::Size(20, 10), base::TimeDelta());
FakeVideoFrameProvider provider;
provider.set_frame(video_frame);
@@ -269,12 +257,9 @@ TEST(VideoLayerImplTest, Rotated270) {
LayerTestCommon::LayerImplTest impl;
DebugSetImplThreadAndMainThreadBlocked(impl.proxy());
- scoped_refptr<media::VideoFrame> video_frame =
- media::VideoFrame::CreateFrame(media::VideoFrame::YV12,
- gfx::Size(20, 10),
- gfx::Rect(20, 10),
- gfx::Size(20, 10),
- base::TimeDelta());
+ scoped_refptr<media::VideoFrame> video_frame = media::VideoFrame::CreateFrame(
+ media::PIXEL_FORMAT_YV12, gfx::Size(20, 10), gfx::Rect(20, 10),
+ gfx::Size(20, 10), base::TimeDelta());
FakeVideoFrameProvider provider;
provider.set_frame(video_frame);
@@ -315,7 +300,7 @@ TEST(VideoLayerImplTest, SoftwareVideoFrameGeneratesYUVQuad) {
mailbox_holder.mailbox.name[0] = 1;
scoped_refptr<media::VideoFrame> video_frame = media::VideoFrame::CreateFrame(
- media::VideoFrame::YV12, gfx::Size(20, 10), gfx::Rect(20, 10),
+ media::PIXEL_FORMAT_YV12, gfx::Size(20, 10), gfx::Rect(20, 10),
gfx::Size(20, 10), base::TimeDelta());
FakeVideoFrameProvider provider;
diff --git a/chromium/cc/layers/viewport.cc b/chromium/cc/layers/viewport.cc
index 059e0a491a9..80e711fd027 100644
--- a/chromium/cc/layers/viewport.cc
+++ b/chromium/cc/layers/viewport.cc
@@ -34,43 +34,41 @@ void Viewport::Pan(const gfx::Vector2dF& delta) {
Viewport::ScrollResult Viewport::ScrollBy(const gfx::Vector2dF& delta,
const gfx::Point& viewport_point,
- bool is_wheel_scroll,
+ bool is_direct_manipulation,
bool affect_top_controls) {
gfx::Vector2dF content_delta = delta;
- ScrollResult result;
- if (affect_top_controls && ShouldTopControlsConsumeScroll(delta)) {
- result.top_controls_applied_delta = ScrollTopControls(delta);
- content_delta -= result.top_controls_applied_delta;
- }
+ if (affect_top_controls && ShouldTopControlsConsumeScroll(delta))
+ content_delta -= ScrollTopControls(delta);
gfx::Vector2dF pending_content_delta = content_delta;
- if (OuterScrollLayer()) {
- pending_content_delta -= host_impl_->ScrollLayer(OuterScrollLayer(),
- pending_content_delta,
- viewport_point,
- is_wheel_scroll);
- }
+ pending_content_delta -= host_impl_->ScrollLayer(InnerScrollLayer(),
+ pending_content_delta,
+ viewport_point,
+ is_direct_manipulation);
+
+ ScrollResult result;
// TODO(bokan): This shouldn't be needed but removing it causes subtle
// viewport movement during top controls manipulation.
- if (!gfx::ToRoundedVector2d(pending_content_delta).IsZero()) {
- pending_content_delta -= host_impl_->ScrollLayer(InnerScrollLayer(),
+ if (gfx::ToRoundedVector2d(pending_content_delta).IsZero()) {
+ result.consumed_delta = delta;
+ } else {
+ pending_content_delta -= host_impl_->ScrollLayer(OuterScrollLayer(),
pending_content_delta,
viewport_point,
- is_wheel_scroll);
- result.unused_scroll_delta = AdjustOverscroll(pending_content_delta);
+ is_direct_manipulation);
+ result.consumed_delta = delta - AdjustOverscroll(pending_content_delta);
}
-
- result.applied_delta = content_delta - pending_content_delta;
+ result.content_scrolled_delta = content_delta - pending_content_delta;
return result;
}
void Viewport::SnapPinchAnchorIfWithinMargin(const gfx::Point& anchor) {
- gfx::SizeF viewport_size =
- host_impl_->active_tree()->InnerViewportContainerLayer()->bounds();
+ gfx::SizeF viewport_size = gfx::SizeF(
+ host_impl_->active_tree()->InnerViewportContainerLayer()->bounds());
if (anchor.x() < kPinchZoomSnapMarginDips)
pinch_anchor_adjustment_.set_x(-anchor.x());
@@ -89,8 +87,7 @@ void Viewport::PinchUpdate(float magnify_delta, const gfx::Point& anchor) {
// length of the screen edge, offset all updates by the amount so that we
// effectively snap the pinch zoom to the edge of the screen. This makes it
// easy to zoom in on position: fixed elements.
- if (host_impl_->settings().invert_viewport_scroll_order)
- SnapPinchAnchorIfWithinMargin(anchor);
+ SnapPinchAnchorIfWithinMargin(anchor);
pinch_zoom_active_ = true;
}
@@ -117,14 +114,7 @@ void Viewport::PinchUpdate(float magnify_delta, const gfx::Point& anchor) {
// be accounted for from the intended move.
move -= InnerScrollLayer()->ClampScrollToMaxScrollOffset();
- if (host_impl_->settings().invert_viewport_scroll_order) {
- Pan(move);
- } else {
- gfx::Point viewport_point;
- bool is_wheel_event = false;
- bool affect_top_controls = false;
- ScrollBy(move, viewport_point, is_wheel_event, affect_top_controls);
- }
+ Pan(move);
}
void Viewport::PinchEnd() {
@@ -152,6 +142,8 @@ bool Viewport::ShouldTopControlsConsumeScroll(
}
gfx::Vector2dF Viewport::AdjustOverscroll(const gfx::Vector2dF& delta) const {
+ // TODO(tdresser): Use a more rational epsilon. See crbug.com/510550 for
+ // details.
const float kEpsilon = 0.1f;
gfx::Vector2dF adjusted = delta;
@@ -160,16 +152,6 @@ gfx::Vector2dF Viewport::AdjustOverscroll(const gfx::Vector2dF& delta) const {
if (std::abs(adjusted.y()) < kEpsilon)
adjusted.set_y(0.0f);
- // Disable overscroll on axes which are impossible to scroll.
- if (host_impl_->settings().report_overscroll_only_for_scrollable_axes) {
- if (std::abs(MaxTotalScrollOffset().x()) <= kEpsilon ||
- !InnerScrollLayer()->user_scrollable_horizontal())
- adjusted.set_x(0.0f);
- if (std::abs(MaxTotalScrollOffset().y()) <= kEpsilon ||
- !InnerScrollLayer()->user_scrollable_vertical())
- adjusted.set_y(0.0f);
- }
-
return adjusted;
}
diff --git a/chromium/cc/layers/viewport.h b/chromium/cc/layers/viewport.h
index 01885d7774f..5d96cd3b283 100644
--- a/chromium/cc/layers/viewport.h
+++ b/chromium/cc/layers/viewport.h
@@ -25,10 +25,11 @@ class CC_EXPORT Viewport {
// determined.
static const int kPinchZoomSnapMarginDips = 100;
+ // TODO(tdresser): eventually |consumed_delta| should equal
+ // |content_scrolled_delta|. See crbug.com/510045 for details.
struct ScrollResult {
- gfx::Vector2dF applied_delta;
- gfx::Vector2dF unused_scroll_delta;
- gfx::Vector2dF top_controls_applied_delta;
+ gfx::Vector2dF consumed_delta;
+ gfx::Vector2dF content_scrolled_delta;
};
static scoped_ptr<Viewport> Create(LayerTreeHostImpl* host_impl);
diff --git a/chromium/cc/output/compositor_frame.cc b/chromium/cc/output/compositor_frame.cc
index e6d713d50e5..e612b28cfad 100644
--- a/chromium/cc/output/compositor_frame.cc
+++ b/chromium/cc/output/compositor_frame.cc
@@ -13,7 +13,6 @@ CompositorFrame::~CompositorFrame() {}
void CompositorFrame::AssignTo(CompositorFrame* target) {
target->delegated_frame_data = delegated_frame_data.Pass();
target->gl_frame_data = gl_frame_data.Pass();
- target->software_frame_data = software_frame_data.Pass();
target->metadata = metadata;
}
diff --git a/chromium/cc/output/compositor_frame.h b/chromium/cc/output/compositor_frame.h
index e5c8a334161..3ab1e8c2c9a 100644
--- a/chromium/cc/output/compositor_frame.h
+++ b/chromium/cc/output/compositor_frame.h
@@ -10,10 +10,12 @@
#include "cc/output/compositor_frame_metadata.h"
#include "cc/output/delegated_frame_data.h"
#include "cc/output/gl_frame_data.h"
-#include "cc/output/software_frame_data.h"
namespace cc {
+// A CompositorFrame struct contains the complete output of a compositor meant
+// for display.
+// TODO(fsamuel): Write more here.
class CC_EXPORT CompositorFrame {
public:
CompositorFrame();
@@ -22,7 +24,6 @@ class CC_EXPORT CompositorFrame {
CompositorFrameMetadata metadata;
scoped_ptr<DelegatedFrameData> delegated_frame_data;
scoped_ptr<GLFrameData> gl_frame_data;
- scoped_ptr<SoftwareFrameData> software_frame_data;
void AssignTo(CompositorFrame* target);
diff --git a/chromium/cc/output/compositor_frame_ack.cc b/chromium/cc/output/compositor_frame_ack.cc
index feb0bac3674..a411b42f5de 100644
--- a/chromium/cc/output/compositor_frame_ack.cc
+++ b/chromium/cc/output/compositor_frame_ack.cc
@@ -6,8 +6,7 @@
namespace cc {
-CompositorFrameAck::CompositorFrameAck()
- : last_software_frame_id(0) {}
+CompositorFrameAck::CompositorFrameAck() {}
CompositorFrameAck::~CompositorFrameAck() {}
diff --git a/chromium/cc/output/compositor_frame_ack.h b/chromium/cc/output/compositor_frame_ack.h
index 943a206e391..aa48fa157b3 100644
--- a/chromium/cc/output/compositor_frame_ack.h
+++ b/chromium/cc/output/compositor_frame_ack.h
@@ -19,7 +19,6 @@ class CC_EXPORT CompositorFrameAck {
ReturnedResourceArray resources;
scoped_ptr<GLFrameData> gl_frame_data;
- unsigned last_software_frame_id;
private:
DISALLOW_COPY_AND_ASSIGN(CompositorFrameAck);
diff --git a/chromium/cc/output/compositor_frame_metadata.cc b/chromium/cc/output/compositor_frame_metadata.cc
index dad78a0c822..b3a9b2d40a0 100644
--- a/chromium/cc/output/compositor_frame_metadata.cc
+++ b/chromium/cc/output/compositor_frame_metadata.cc
@@ -12,8 +12,8 @@ CompositorFrameMetadata::CompositorFrameMetadata()
min_page_scale_factor(0.f),
max_page_scale_factor(0.f),
root_overflow_x_hidden(false),
- root_overflow_y_hidden(false) {
-}
+ root_overflow_y_hidden(false),
+ root_background_color(SK_ColorWHITE) {}
CompositorFrameMetadata::~CompositorFrameMetadata() {
}
diff --git a/chromium/cc/output/compositor_frame_metadata.h b/chromium/cc/output/compositor_frame_metadata.h
index 999a6b4406a..72035e32afd 100644
--- a/chromium/cc/output/compositor_frame_metadata.h
+++ b/chromium/cc/output/compositor_frame_metadata.h
@@ -9,6 +9,7 @@
#include "cc/base/cc_export.h"
#include "cc/output/viewport_selection_bound.h"
+#include "third_party/skia/include/core/SkColor.h"
#include "ui/events/latency_info.h"
#include "ui/gfx/geometry/size_f.h"
#include "ui/gfx/geometry/vector2d_f.h"
@@ -42,6 +43,11 @@ class CC_EXPORT CompositorFrameMetadata {
gfx::Vector2dF location_bar_offset;
gfx::Vector2dF location_bar_content_translation;
+ // This color is usually obtained from the background color of the <body>
+ // element. It can be used for filling in gutter areas around the frame when
+ // it's too small to fill the box the parent reserved for it.
+ SkColor root_background_color;
+
// Provides selection region updates relative to the current viewport. If the
// selection is empty or otherwise unused, the bound types will indicate such.
ViewportSelection selection;
diff --git a/chromium/cc/output/context_provider.h b/chromium/cc/output/context_provider.h
index aa4367d97ff..47eff203548 100644
--- a/chromium/cc/output/context_provider.h
+++ b/chromium/cc/output/context_provider.h
@@ -7,6 +7,7 @@
#include "base/callback.h"
#include "base/memory/ref_counted.h"
+#include "base/synchronization/lock.h"
#include "cc/base/cc_export.h"
#include "gpu/command_buffer/common/capabilities.h"
@@ -26,10 +27,33 @@ struct ManagedMemoryPolicy;
class ContextProvider : public base::RefCountedThreadSafe<ContextProvider> {
public:
+ class ScopedContextLock {
+ public:
+ explicit ScopedContextLock(ContextProvider* context_provider)
+ : context_provider_(context_provider),
+ context_lock_(*context_provider_->GetLock()) {
+ // Allow current thread to use |context_provider_|.
+ context_provider_->DetachFromThread();
+ }
+ ~ScopedContextLock() {
+ // Allow usage by thread for which |context_provider_| is bound to.
+ context_provider_->DetachFromThread();
+ }
+
+ gpu::gles2::GLES2Interface* ContextGL() {
+ return context_provider_->ContextGL();
+ }
+
+ private:
+ ContextProvider* const context_provider_;
+ base::AutoLock context_lock_;
+ };
// Bind the 3d context to the current thread. This should be called before
// accessing the contexts. Calling it more than once should have no effect.
// Once this function has been called, the class should only be accessed
- // from the same thread.
+ // from the same thread unless the function has some explicitly specified
+ // rules for access on a different thread. See SetupLockOnMainThread(), which
+ // can be used to provide access from multiple threads.
virtual bool BindToCurrentThread() = 0;
virtual void DetachFromThread() {}
@@ -48,11 +72,13 @@ class ContextProvider : public base::RefCountedThreadSafe<ContextProvider> {
// See skia GrContext::resetContext for details.
virtual void InvalidateGrContext(uint32_t state) = 0;
- // Sets up a lock so this context can be used from multiple threads.
+ // Sets up a lock so this context can be used from multiple threads. After
+ // calling this, all functions without explicit thread usage constraints can
+ // be used on any thread while the lock returned by GetLock() is acquired.
virtual void SetupLock() = 0;
// Returns the lock that should be held if using this context from multiple
- // threads.
+ // threads. This can be called on any thread.
virtual base::Lock* GetLock() = 0;
// Returns the capabilities of the currently bound 3d context.
diff --git a/chromium/cc/output/delegating_renderer_unittest.cc b/chromium/cc/output/delegating_renderer_unittest.cc
index 3238d2d9028..b32e9a369fc 100644
--- a/chromium/cc/output/delegating_renderer_unittest.cc
+++ b/chromium/cc/output/delegating_renderer_unittest.cc
@@ -6,7 +6,6 @@
#include "cc/test/fake_output_surface.h"
#include "cc/test/layer_tree_test.h"
-#include "cc/test/render_pass_test_common.h"
#include "cc/test/render_pass_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -90,19 +89,17 @@ class DelegatingRendererTestResources : public DelegatingRendererTest {
frame->render_passes.clear();
frame->render_passes_by_id.clear();
- TestRenderPass* child_pass = AddRenderPass(&frame->render_passes,
- RenderPassId(2, 1),
- gfx::Rect(3, 3, 10, 10),
- gfx::Transform());
- child_pass->AppendOneOfEveryQuadType(host_impl->resource_provider(),
- RenderPassId(0, 0));
-
- TestRenderPass* pass = AddRenderPass(&frame->render_passes,
- RenderPassId(1, 1),
- gfx::Rect(3, 3, 10, 10),
- gfx::Transform());
- pass->AppendOneOfEveryQuadType(
- host_impl->resource_provider(), child_pass->id);
+ RenderPass* child_pass =
+ AddRenderPass(&frame->render_passes, RenderPassId(2, 1),
+ gfx::Rect(3, 3, 10, 10), gfx::Transform());
+ uint32_t mailbox_sync_point;
+ AddOneOfEveryQuadType(child_pass, host_impl->resource_provider(),
+ RenderPassId(0, 0), &mailbox_sync_point);
+
+ RenderPass* pass = AddRenderPass(&frame->render_passes, RenderPassId(1, 1),
+ gfx::Rect(3, 3, 10, 10), gfx::Transform());
+ AddOneOfEveryQuadType(pass, host_impl->resource_provider(), child_pass->id,
+ &mailbox_sync_point);
return draw_result;
}
diff --git a/chromium/cc/output/direct_renderer.cc b/chromium/cc/output/direct_renderer.cc
index 7ceaa00379f..f98151833e0 100644
--- a/chromium/cc/output/direct_renderer.cc
+++ b/chromium/cc/output/direct_renderer.cc
@@ -17,6 +17,7 @@
#include "cc/output/bsp_walk_action.h"
#include "cc/output/copy_output_request.h"
#include "cc/quads/draw_quad.h"
+#include "ui/gfx/geometry/quad_f.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/transform.h"
@@ -221,6 +222,20 @@ void DirectRenderer::DrawFrame(RenderPassList* render_passes_in_draw_order,
BeginDrawingFrame(&frame);
+ if (output_surface_->IsDisplayedAsOverlayPlane()) {
+ // Create the overlay candidate for the output surface, and mark it as
+ // always
+ // handled.
+ OverlayCandidate output_surface_plane;
+ output_surface_plane.display_rect =
+ gfx::RectF(root_render_pass->output_rect);
+ output_surface_plane.quad_rect_in_target_space =
+ root_render_pass->output_rect;
+ output_surface_plane.use_output_surface_for_resource = true;
+ output_surface_plane.overlay_handled = true;
+ frame.overlay_list.push_back(output_surface_plane);
+ }
+
// If we have any copy requests, we can't remove any quads for overlays,
// otherwise the framebuffer will be missing the overlay contents.
if (root_render_pass->copy_requests.empty()) {
@@ -445,7 +460,7 @@ void DirectRenderer::DrawRenderPass(DrawingFrame* frame,
for (auto it = quad_list.BackToFrontBegin(); it != quad_list.BackToFrontEnd();
++it) {
const DrawQuad& quad = **it;
- gfx::QuadF send_quad(quad.visible_rect);
+ gfx::QuadF send_quad(gfx::RectF(quad.visible_rect));
if (render_pass_is_clipped &&
ShouldSkipQuad(quad, render_pass_scissor_in_draw_space)) {
@@ -462,7 +477,7 @@ void DirectRenderer::DrawRenderPass(DrawingFrame* frame,
// polygons to go into the BSP tree.
if (quad.shared_quad_state->sorting_context_id != 0) {
scoped_ptr<DrawPolygon> new_polygon(new DrawPolygon(
- *it, quad.visible_rect,
+ *it, gfx::RectF(quad.visible_rect),
quad.shared_quad_state->quad_to_target_transform, next_polygon_id++));
if (new_polygon->points().size() > 2u) {
poly_list.push_back(new_polygon.Pass());
diff --git a/chromium/cc/output/filter_operations.cc b/chromium/cc/output/filter_operations.cc
index 92423de9b59..659acae64b0 100644
--- a/chromium/cc/output/filter_operations.cc
+++ b/chromium/cc/output/filter_operations.cc
@@ -61,22 +61,31 @@ void FilterOperations::GetOutsets(int* top,
*top = *right = *bottom = *left = 0;
for (size_t i = 0; i < operations_.size(); ++i) {
const FilterOperation& op = operations_[i];
- // TODO(ajuma): Add support for reference filters once SkImageFilter
- // reports its outsets.
- DCHECK(op.type() != FilterOperation::REFERENCE);
- if (op.type() == FilterOperation::BLUR ||
- op.type() == FilterOperation::DROP_SHADOW) {
- int spread = SpreadForStdDeviation(op.amount());
- if (op.type() == FilterOperation::BLUR) {
- *top += spread;
- *right += spread;
- *bottom += spread;
- *left += spread;
- } else {
- *top += spread - op.drop_shadow_offset().y();
- *right += spread + op.drop_shadow_offset().x();
- *bottom += spread + op.drop_shadow_offset().y();
- *left += spread - op.drop_shadow_offset().x();
+ // TODO(hendrikw): We should refactor some of this. See crbug.com/523534.
+ if (op.type() == FilterOperation::REFERENCE) {
+ SkIRect src = SkIRect::MakeWH(0, 0);
+ SkIRect dst;
+ bool result = op.image_filter()->filterBounds(src, SkMatrix::I(), &dst);
+ DCHECK(result);
+ *top += std::max(0, -dst.top());
+ *right += std::max(0, dst.right());
+ *bottom += std::max(0, dst.bottom());
+ *left += std::max(0, -dst.left());
+ } else {
+ if (op.type() == FilterOperation::BLUR ||
+ op.type() == FilterOperation::DROP_SHADOW) {
+ int spread = SpreadForStdDeviation(op.amount());
+ if (op.type() == FilterOperation::BLUR) {
+ *top += spread;
+ *right += spread;
+ *bottom += spread;
+ *left += spread;
+ } else {
+ *top += spread - op.drop_shadow_offset().y();
+ *right += spread + op.drop_shadow_offset().x();
+ *bottom += spread + op.drop_shadow_offset().y();
+ *left += spread - op.drop_shadow_offset().x();
+ }
}
}
}
@@ -85,13 +94,14 @@ void FilterOperations::GetOutsets(int* top,
bool FilterOperations::HasFilterThatMovesPixels() const {
for (size_t i = 0; i < operations_.size(); ++i) {
const FilterOperation& op = operations_[i];
- // TODO(ajuma): Once SkImageFilter reports its outsets, use those here to
- // determine whether a reference filter really moves pixels.
switch (op.type()) {
case FilterOperation::BLUR:
case FilterOperation::DROP_SHADOW:
case FilterOperation::ZOOM:
+ return true;
case FilterOperation::REFERENCE:
+ // TODO(hendrikw): SkImageFilter needs a function that tells us if the
+ // filter can move pixels. See crbug.com/523538.
return true;
case FilterOperation::OPACITY:
case FilterOperation::COLOR_MATRIX:
diff --git a/chromium/cc/output/filter_operations_unittest.cc b/chromium/cc/output/filter_operations_unittest.cc
index d6ae6ab500a..7717bde1213 100644
--- a/chromium/cc/output/filter_operations_unittest.cc
+++ b/chromium/cc/output/filter_operations_unittest.cc
@@ -6,6 +6,7 @@
#include "skia/ext/refptr.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/effects/SkBlurImageFilter.h"
+#include "third_party/skia/include/effects/SkDropShadowImageFilter.h"
#include "ui/gfx/geometry/point.h"
namespace cc {
@@ -23,6 +24,26 @@ TEST(FilterOperationsTest, GetOutsetsBlur) {
EXPECT_EQ(57, left);
}
+TEST(FilterOperationsTest, GetOutsetsDropShadowReferenceFilter) {
+ // TODO(hendrikw): We need to make outsets for reference filters be in line
+ // with non-reference filters. See crbug.com/523534
+ skia::RefPtr<SkImageFilter> filter =
+ skia::AdoptRef(SkDropShadowImageFilter::Create(
+ SkIntToScalar(3), SkIntToScalar(8), SkIntToScalar(4),
+ SkIntToScalar(9), SK_ColorBLACK,
+ SkDropShadowImageFilter::kDrawShadowAndForeground_ShadowMode));
+ FilterOperations ops;
+ ops.Append(FilterOperation::CreateReferenceFilter(filter));
+
+ int top, right, bottom, left;
+ top = right = bottom = left = 0;
+ ops.GetOutsets(&top, &right, &bottom, &left);
+ EXPECT_EQ(35, top);
+ EXPECT_EQ(9, right);
+ EXPECT_EQ(19, bottom);
+ EXPECT_EQ(15, left);
+}
+
TEST(FilterOperationsTest, GetOutsetsDropShadow) {
FilterOperations ops;
ops.Append(FilterOperation::CreateDropShadowFilter(gfx::Point(3, 8), 20, 0));
diff --git a/chromium/cc/output/gl_renderer.cc b/chromium/cc/output/gl_renderer.cc
index 3ffc676a66d..536ab50082d 100644
--- a/chromium/cc/output/gl_renderer.cc
+++ b/chromium/cc/output/gl_renderer.cc
@@ -381,6 +381,7 @@ GLRenderer::~GLRenderer() {
pending_async_read_pixels_.pop_back();
}
+ previous_swap_overlay_resources_.clear();
in_use_overlay_resources_.clear();
CleanupSharedObjects();
@@ -501,11 +502,6 @@ void GLRenderer::BeginDrawingFrame(DrawingFrame* frame) {
ReinitializeGLState();
}
-void GLRenderer::DoNoOp() {
- gl_->BindFramebuffer(GL_FRAMEBUFFER, 0);
- gl_->Flush();
-}
-
void GLRenderer::DoDrawQuad(DrawingFrame* frame,
const DrawQuad* quad,
const gfx::QuadF* clip_region) {
@@ -518,10 +514,6 @@ void GLRenderer::DoDrawQuad(DrawingFrame* frame,
case DrawQuad::INVALID:
NOTREACHED();
break;
- case DrawQuad::CHECKERBOARD:
- DrawCheckerboardQuad(frame, CheckerboardDrawQuad::MaterialCast(quad),
- clip_region);
- break;
case DrawQuad::DEBUG_BORDER:
DrawDebugBorderQuad(frame, DebugBorderDrawQuad::MaterialCast(quad));
break;
@@ -564,48 +556,6 @@ void GLRenderer::DoDrawQuad(DrawingFrame* frame,
}
}
-void GLRenderer::DrawCheckerboardQuad(const DrawingFrame* frame,
- const CheckerboardDrawQuad* quad,
- const gfx::QuadF* clip_region) {
- // TODO(enne) For now since checkerboards shouldn't be part of a 3D
- // context, clipping regions aren't supported so we skip drawing them
- // if this becomes the case.
- if (clip_region) {
- return;
- }
- SetBlendEnabled(quad->ShouldDrawWithBlending());
-
- const TileCheckerboardProgram* program = GetTileCheckerboardProgram();
- DCHECK(program && (program->initialized() || IsContextLost()));
- SetUseProgram(program->program());
-
- SkColor color = quad->color;
- gl_->Uniform4f(program->fragment_shader().color_location(),
- SkColorGetR(color) * (1.0f / 255.0f),
- SkColorGetG(color) * (1.0f / 255.0f),
- SkColorGetB(color) * (1.0f / 255.0f), 1);
-
- const int kCheckerboardWidth = 16;
- float frequency = 1.0f / kCheckerboardWidth;
-
- gfx::Rect tile_rect = quad->rect;
- float tex_offset_x =
- static_cast<int>(tile_rect.x() / quad->scale) % kCheckerboardWidth;
- float tex_offset_y =
- static_cast<int>(tile_rect.y() / quad->scale) % kCheckerboardWidth;
- float tex_scale_x = tile_rect.width() / quad->scale;
- float tex_scale_y = tile_rect.height() / quad->scale;
- gl_->Uniform4f(program->fragment_shader().tex_transform_location(),
- tex_offset_x, tex_offset_y, tex_scale_x, tex_scale_y);
-
- gl_->Uniform1f(program->fragment_shader().frequency_location(), frequency);
-
- SetShaderOpacity(quad->shared_quad_state->opacity,
- program->fragment_shader().alpha_location());
- DrawQuadGeometry(frame, quad->shared_quad_state->quad_to_target_transform,
- quad->rect, program->vertex_shader().matrix_location());
-}
-
// This function does not handle 3D sorting right now, since the debug border
// quads are just drawn as their original quads and not in split pieces. This
// results in some debug border quads drawing over foreground quads.
@@ -624,7 +574,7 @@ void GLRenderer::DrawDebugBorderQuad(const DrawingFrame* frame,
gfx::Transform render_matrix;
QuadRectTransform(&render_matrix,
quad->shared_quad_state->quad_to_target_transform,
- layer_rect);
+ gfx::RectF(layer_rect));
GLRenderer::ToGLMatrix(&gl_matrix[0],
frame->projection_matrix * render_matrix);
gl_->UniformMatrix4fv(program->vertex_shader().matrix_location(), 1, false,
@@ -805,21 +755,13 @@ void GLRenderer::RestoreBlendFuncToDefault(SkXfermode::Mode blend_mode) {
}
}
-bool GLRenderer::ShouldApplyBackgroundFilters(DrawingFrame* frame,
- const RenderPassDrawQuad* quad) {
+bool GLRenderer::ShouldApplyBackgroundFilters(const RenderPassDrawQuad* quad) {
if (quad->background_filters.IsEmpty())
return false;
- // TODO(danakj): We only allow background filters on an opaque render surface
- // because other surfaces may contain translucent pixels, and the contents
- // behind those translucent pixels wouldn't have the filter applied.
- if (frame->current_render_pass->has_transparent_background)
- return false;
+ // TODO(hendrikw): Look into allowing background filters to see pixels from
+ // other render targets. See crbug.com/314867.
- // TODO(ajuma): Add support for reference filters once
- // FilterOperations::GetOutsets supports reference filters.
- if (quad->background_filters.HasReferenceFilter())
- return false;
return true;
}
@@ -874,7 +816,7 @@ gfx::Rect GLRenderer::GetBackdropBoundingBoxForRenderPassQuad(
gfx::Rect backdrop_rect = gfx::ToEnclosingRect(MathUtil::MapClippedRect(
contents_device_transform, scaled_region.BoundingBox()));
- if (ShouldApplyBackgroundFilters(frame, quad)) {
+ if (ShouldApplyBackgroundFilters(quad)) {
int top, right, bottom, left;
quad->background_filters.GetOutsets(&top, &right, &bottom, &left);
backdrop_rect.Inset(-left, -top, -right, -bottom);
@@ -910,9 +852,9 @@ skia::RefPtr<SkImage> GLRenderer::ApplyBackgroundFilters(
DrawingFrame* frame,
const RenderPassDrawQuad* quad,
ScopedResource* background_texture) {
- DCHECK(ShouldApplyBackgroundFilters(frame, quad));
+ DCHECK(ShouldApplyBackgroundFilters(quad));
skia::RefPtr<SkImageFilter> filter = RenderSurfaceFilters::BuildImageFilter(
- quad->background_filters, background_texture->size());
+ quad->background_filters, gfx::SizeF(background_texture->size()));
skia::RefPtr<SkImage> background_with_filters = ApplyImageFilter(
ScopedUseGrContext::Create(this, frame), resource_provider_, quad->rect,
@@ -931,7 +873,7 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame,
gfx::Transform quad_rect_matrix;
QuadRectTransform(&quad_rect_matrix,
quad->shared_quad_state->quad_to_target_transform,
- quad->rect);
+ gfx::RectF(quad->rect));
gfx::Transform contents_device_transform =
frame->window_matrix * frame->projection_matrix * quad_rect_matrix;
contents_device_transform.FlattenTo2d();
@@ -960,7 +902,7 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame,
SkXfermode::Mode blend_mode = quad->shared_quad_state->blend_mode;
bool use_shaders_for_blending =
!CanApplyBlendModeUsingBlendFunc(blend_mode) ||
- ShouldApplyBackgroundFilters(frame, quad) ||
+ ShouldApplyBackgroundFilters(quad) ||
settings_->force_blending_with_shaders;
scoped_ptr<ScopedResource> background_texture;
@@ -985,7 +927,7 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame,
// LayerTreeHost::CalculateMemoryForRenderSurfaces.
background_texture = GetBackdropTexture(background_rect);
- if (ShouldApplyBackgroundFilters(frame, quad) && background_texture) {
+ if (ShouldApplyBackgroundFilters(quad) && background_texture) {
// Apply the background filters to R, so that it is applied in the
// pixels' coordinate space.
background_image =
@@ -1005,7 +947,7 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame,
if (!quad->mask_resource_id())
background_texture.reset();
} else if (CanApplyBlendModeUsingBlendFunc(blend_mode) &&
- ShouldApplyBackgroundFilters(frame, quad)) {
+ ShouldApplyBackgroundFilters(quad)) {
// Something went wrong with applying background filters to the backdrop.
use_shaders_for_blending = false;
background_texture.reset();
@@ -1028,7 +970,7 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame,
bool use_color_matrix = false;
if (!quad->filters.IsEmpty()) {
skia::RefPtr<SkImageFilter> filter = RenderSurfaceFilters::BuildImageFilter(
- quad->filters, contents_texture->size());
+ quad->filters, gfx::SizeF(contents_texture->size()));
if (filter) {
skia::RefPtr<SkColorFilter> cf;
@@ -1260,7 +1202,7 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame,
SetShaderOpacity(quad->shared_quad_state->opacity, locations.alpha);
SetShaderQuadF(surface_quad, locations.quad);
DrawQuadGeometry(frame, quad->shared_quad_state->quad_to_target_transform,
- quad->rect, locations.matrix);
+ gfx::RectF(quad->rect), locations.matrix);
// Flush the compositor context before the filter bitmap goes out of
// scope, so the draw gets processed before the filter texture gets deleted.
@@ -1349,7 +1291,7 @@ static gfx::QuadF GetDeviceQuadWithAntialiasingOnExteriorEdges(
const gfx::QuadF& tile_quad,
const gfx::QuadF* clip_region,
const DrawQuad* quad) {
- gfx::RectF tile_rect = quad->visible_rect;
+ auto tile_rect = gfx::RectF(quad->visible_rect);
gfx::PointF bottom_right = tile_quad.p3();
gfx::PointF bottom_left = tile_quad.p4();
@@ -1412,7 +1354,7 @@ float GetTotalQuadError(const gfx::QuadF* clipped_quad,
// correctly. This is necessary because we check the edges of this
// quad against the expected left/right/top/bottom for anti-aliasing.
void AlignQuadToBoundingBox(gfx::QuadF* clipped_quad) {
- gfx::QuadF bounding_quad = gfx::QuadF(clipped_quad->BoundingBox());
+ auto bounding_quad = gfx::QuadF(clipped_quad->BoundingBox());
gfx::QuadF best_rotation = *clipped_quad;
float least_error_amount = GetTotalQuadError(clipped_quad, &bounding_quad);
for (size_t i = 1; i < 4; ++i) {
@@ -1519,8 +1461,9 @@ void GLRenderer::SetupQuadForClippingAndAntialiasing(
if (use_aa_on_all_four_edges) {
device_quad = device_layer_edges.ToQuadF();
} else {
- gfx::QuadF tile_quad(local_clip_region ? *local_clip_region
- : gfx::QuadF(quad->visible_rect));
+ gfx::QuadF tile_quad(local_clip_region
+ ? *local_clip_region
+ : gfx::QuadF(gfx::RectF(quad->visible_rect)));
device_quad = GetDeviceQuadWithAntialiasingOnExteriorEdges(
device_layer_edges, device_transform, tile_quad, local_clip_region,
quad);
@@ -1557,7 +1500,7 @@ void GLRenderer::SetupRenderPassQuadForClippingAndAntialiasing(
// Apply anti-aliasing only to the edges that are not being clipped
if (local_clip_region) {
- gfx::QuadF tile_quad(quad->visible_rect);
+ gfx::QuadF tile_quad(gfx::RectF(quad->visible_rect));
GetScaledRegion(quad->rect, local_clip_region, &tile_quad);
device_quad = GetDeviceQuadWithAntialiasingOnExteriorEdges(
device_layer_edges, device_transform, tile_quad, local_clip_region,
@@ -1590,7 +1533,7 @@ void GLRenderer::DrawSolidColorQuad(const DrawingFrame* frame,
if (!device_transform.IsInvertible())
return;
- gfx::QuadF local_quad = gfx::QuadF(gfx::RectF(tile_rect));
+ auto local_quad = gfx::QuadF(gfx::RectF(tile_rect));
gfx::QuadF device_layer_quad;
bool use_aa = false;
@@ -1602,7 +1545,9 @@ void GLRenderer::DrawSolidColorQuad(const DrawingFrame* frame,
bool force_aa = false;
device_layer_quad = MathUtil::MapQuad(
device_transform,
- gfx::QuadF(quad->shared_quad_state->visible_quad_layer_rect), &clipped);
+ gfx::QuadF(
+ gfx::RectF(quad->shared_quad_state->visible_quad_layer_rect)),
+ &clipped);
use_aa = ShouldAntialiasQuad(device_layer_quad, clipped, force_aa);
}
@@ -1653,7 +1598,7 @@ void GLRenderer::DrawSolidColorQuad(const DrawingFrame* frame,
// quad_rect.
gfx::RectF centered_rect(
gfx::PointF(-0.5f * tile_rect.width(), -0.5f * tile_rect.height()),
- tile_rect.size());
+ gfx::SizeF(tile_rect.size()));
DrawQuadGeometry(frame, quad->shared_quad_state->quad_to_target_transform,
centered_rect, uniforms.matrix_location);
} else {
@@ -1720,7 +1665,9 @@ void GLRenderer::DrawContentQuad(const DrawingFrame* frame,
bool force_aa = false;
device_layer_quad = MathUtil::MapQuad(
device_transform,
- gfx::QuadF(quad->shared_quad_state->visible_quad_layer_rect), &clipped);
+ gfx::QuadF(
+ gfx::RectF(quad->shared_quad_state->visible_quad_layer_rect)),
+ &clipped);
use_aa = ShouldAntialiasQuad(device_layer_quad, clipped, force_aa);
}
@@ -1746,7 +1693,7 @@ void GLRenderer::DrawContentQuadAA(const DrawingFrame* frame,
gfx::Rect tile_rect = quad->visible_rect;
gfx::RectF tex_coord_rect = MathUtil::ScaleRectProportional(
- quad->tex_coord_rect, quad->rect, tile_rect);
+ quad->tex_coord_rect, gfx::RectF(quad->rect), gfx::RectF(tile_rect));
float tex_to_geom_scale_x = quad->rect.width() / quad->tex_coord_rect.width();
float tex_to_geom_scale_y =
quad->rect.height() / quad->tex_coord_rect.height();
@@ -1782,7 +1729,7 @@ void GLRenderer::DrawContentQuadAA(const DrawingFrame* frame,
TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired(
gl_, &highp_threshold_cache_, highp_threshold_min_, quad->texture_size);
- gfx::QuadF local_quad = gfx::QuadF(gfx::RectF(tile_rect));
+ auto local_quad = gfx::QuadF(gfx::RectF(tile_rect));
float edge[24];
SetupQuadForClippingAndAntialiasing(device_transform, quad, &aa_quad,
clip_region, &local_quad, edge);
@@ -1850,7 +1797,7 @@ void GLRenderer::DrawContentQuadAA(const DrawingFrame* frame,
// it. This is why this centered rect is used and not the original quad_rect.
gfx::RectF centered_rect(
gfx::PointF(-0.5f * tile_rect.width(), -0.5f * tile_rect.height()),
- tile_rect.size());
+ gfx::SizeF(tile_rect.size()));
DrawQuadGeometry(frame, quad->shared_quad_state->quad_to_target_transform,
centered_rect, uniforms.matrix_location);
}
@@ -1860,7 +1807,8 @@ void GLRenderer::DrawContentQuadNoAA(const DrawingFrame* frame,
ResourceId resource_id,
const gfx::QuadF* clip_region) {
gfx::RectF tex_coord_rect = MathUtil::ScaleRectProportional(
- quad->tex_coord_rect, quad->rect, quad->visible_rect);
+ quad->tex_coord_rect, gfx::RectF(quad->rect),
+ gfx::RectF(quad->visible_rect));
float tex_to_geom_scale_x = quad->rect.width() / quad->tex_coord_rect.width();
float tex_to_geom_scale_y =
quad->rect.height() / quad->tex_coord_rect.height();
@@ -1930,37 +1878,32 @@ void GLRenderer::DrawContentQuadNoAA(const DrawingFrame* frame,
// does, then vertices will match the texture mapping in the vertex buffer.
// The method SetShaderQuadF() changes the order of vertices and so it's
// not used here.
- gfx::QuadF tile_rect(quad->visible_rect);
+ gfx::QuadF tile_quad(gfx::RectF(quad->visible_rect));
float width = quad->visible_rect.width();
float height = quad->visible_rect.height();
gfx::PointF top_left = quad->visible_rect.origin();
if (clip_region) {
- tile_rect = *clip_region;
+ tile_quad = *clip_region;
float gl_uv[8] = {
- (tile_rect.p4().x() - top_left.x()) / width,
- (tile_rect.p4().y() - top_left.y()) / height,
- (tile_rect.p1().x() - top_left.x()) / width,
- (tile_rect.p1().y() - top_left.y()) / height,
- (tile_rect.p2().x() - top_left.x()) / width,
- (tile_rect.p2().y() - top_left.y()) / height,
- (tile_rect.p3().x() - top_left.x()) / width,
- (tile_rect.p3().y() - top_left.y()) / height,
+ (tile_quad.p4().x() - top_left.x()) / width,
+ (tile_quad.p4().y() - top_left.y()) / height,
+ (tile_quad.p1().x() - top_left.x()) / width,
+ (tile_quad.p1().y() - top_left.y()) / height,
+ (tile_quad.p2().x() - top_left.x()) / width,
+ (tile_quad.p2().y() - top_left.y()) / height,
+ (tile_quad.p3().x() - top_left.x()) / width,
+ (tile_quad.p3().y() - top_left.y()) / height,
};
PrepareGeometry(CLIPPED_BINDING);
clipped_geometry_->InitializeCustomQuadWithUVs(
- gfx::QuadF(quad->visible_rect), gl_uv);
+ gfx::QuadF(gfx::RectF(quad->visible_rect)), gl_uv);
} else {
PrepareGeometry(SHARED_BINDING);
}
float gl_quad[8] = {
- tile_rect.p4().x(),
- tile_rect.p4().y(),
- tile_rect.p1().x(),
- tile_rect.p1().y(),
- tile_rect.p2().x(),
- tile_rect.p2().y(),
- tile_rect.p3().x(),
- tile_rect.p3().y(),
+ tile_quad.p4().x(), tile_quad.p4().y(), tile_quad.p1().x(),
+ tile_quad.p1().y(), tile_quad.p2().x(), tile_quad.p2().y(),
+ tile_quad.p3().x(), tile_quad.p3().y(),
};
gl_->Uniform2fv(uniforms.quad_location, 4, gl_quad);
@@ -2167,7 +2110,7 @@ void GLRenderer::DrawYUVVideoQuad(const DrawingFrame* frame,
// un-antialiased quad should have and which vertex this is and the float
// quad passed in via uniform is the actual geometry that gets used to draw
// it. This is why this centered rect is used and not the original quad_rect.
- gfx::RectF tile_rect = quad->rect;
+ auto tile_rect = gfx::RectF(quad->rect);
gl_->UniformMatrix3fv(yuv_matrix_location, 1, 0, yuv_to_rgb);
gl_->Uniform3fv(yuv_adj_location, 1, yuv_adjust);
@@ -2219,7 +2162,8 @@ void GLRenderer::DrawStreamVideoQuad(const DrawingFrame* frame,
program->fragment_shader().alpha_location());
if (!clip_region) {
DrawQuadGeometry(frame, quad->shared_quad_state->quad_to_target_transform,
- quad->rect, program->vertex_shader().matrix_location());
+ gfx::RectF(quad->rect),
+ program->vertex_shader().matrix_location());
} else {
gfx::QuadF region_quad(*clip_region);
region_quad.Scale(1.0f / quad->rect.width(), 1.0f / quad->rect.height());
@@ -2227,8 +2171,9 @@ void GLRenderer::DrawStreamVideoQuad(const DrawingFrame* frame,
float uvs[8] = {0};
GetScaledUVs(quad->visible_rect, clip_region, uvs);
DrawQuadGeometryClippedByQuadF(
- frame, quad->shared_quad_state->quad_to_target_transform, quad->rect,
- region_quad, program->vertex_shader().matrix_location(), uvs);
+ frame, quad->shared_quad_state->quad_to_target_transform,
+ gfx::RectF(quad->rect), region_quad,
+ program->vertex_shader().matrix_location(), uvs);
}
}
@@ -2408,7 +2353,7 @@ void GLRenderer::EnqueueTextureQuad(const DrawingFrame* frame,
gfx::Transform quad_rect_matrix;
QuadRectTransform(&quad_rect_matrix,
quad->shared_quad_state->quad_to_target_transform,
- quad->rect);
+ gfx::RectF(quad->rect));
quad_rect_matrix = frame->projection_matrix * quad_rect_matrix;
Float16 m;
@@ -2474,13 +2419,13 @@ void GLRenderer::DrawIOSurfaceQuad(const DrawingFrame* frame,
if (!clip_region) {
DrawQuadGeometry(frame, quad->shared_quad_state->quad_to_target_transform,
- quad->rect, binding.matrix_location);
+ gfx::RectF(quad->rect), binding.matrix_location);
} else {
float uvs[8] = {0};
GetScaledUVs(quad->visible_rect, clip_region, uvs);
DrawQuadGeometryClippedByQuadF(
- frame, quad->shared_quad_state->quad_to_target_transform, quad->rect,
- *clip_region, binding.matrix_location, uvs);
+ frame, quad->shared_quad_state->quad_to_target_transform,
+ gfx::RectF(quad->rect), *clip_region, binding.matrix_location, uvs);
}
gl_->BindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
@@ -2494,7 +2439,7 @@ void GLRenderer::FinishDrawingFrame(DrawingFrame* frame) {
}
current_framebuffer_lock_ = nullptr;
- swap_buffer_rect_.Union(gfx::ToEnclosingRect(frame->root_damage_rect));
+ swap_buffer_rect_.Union(frame->root_damage_rect);
gl_->Disable(GL_BLEND);
blend_shadow_ = false;
@@ -2673,8 +2618,14 @@ void GLRenderer::SwapBuffers(const CompositorFrameMetadata& metadata) {
output_surface_->SwapBuffers(&compositor_frame);
// Release previously used overlay resources and hold onto the pending ones
- // until the next swap buffers.
- in_use_overlay_resources_.clear();
+ // until the next swap buffers. On some platforms, hold onto resources for
+ // an extra frame.
+ if (settings_->delay_releasing_overlay_resources) {
+ previous_swap_overlay_resources_.clear();
+ previous_swap_overlay_resources_.swap(in_use_overlay_resources_);
+ } else {
+ in_use_overlay_resources_.clear();
+ }
in_use_overlay_resources_.swap(pending_overlay_resources_);
swap_buffer_rect_ = gfx::Rect();
@@ -3027,17 +2978,6 @@ void GLRenderer::PrepareGeometry(BoundGeometry binding) {
bound_geometry_ = binding;
}
-const GLRenderer::TileCheckerboardProgram*
-GLRenderer::GetTileCheckerboardProgram() {
- if (!tile_checkerboard_program_.initialized()) {
- TRACE_EVENT0("cc", "GLRenderer::checkerboardProgram::initalize");
- tile_checkerboard_program_.Initialize(output_surface_->context_provider(),
- TEX_COORD_PRECISION_NA,
- SAMPLER_TYPE_NA);
- }
- return &tile_checkerboard_program_;
-}
-
const GLRenderer::DebugBorderProgram* GLRenderer::GetDebugBorderProgram() {
if (!debug_border_program_.initialized()) {
TRACE_EVENT0("cc", "GLRenderer::debugBorderProgram::initialize");
@@ -3499,8 +3439,6 @@ void GLRenderer::CleanupSharedObjects() {
video_stream_texture_program_[i].Cleanup(gl_);
}
- tile_checkerboard_program_.Cleanup(gl_);
-
debug_border_program_.Cleanup(gl_);
solid_color_program_.Cleanup(gl_);
solid_color_program_aa_.Cleanup(gl_);
@@ -3577,20 +3515,20 @@ void GLRenderer::ScheduleOverlays(DrawingFrame* frame) {
ResourceProvider::ResourceIdArray resources;
OverlayCandidateList& overlays = frame->overlay_list;
for (const OverlayCandidate& overlay : overlays) {
- // Skip primary plane.
- if (overlay.plane_z_order == 0)
- continue;
-
- pending_overlay_resources_.push_back(
- make_scoped_ptr(new ResourceProvider::ScopedReadLockGL(
- resource_provider_, overlay.resource_id)));
+ unsigned texture_id = 0;
+ if (overlay.use_output_surface_for_resource) {
+ texture_id = output_surface_->GetOverlayTextureId();
+ DCHECK(texture_id);
+ } else {
+ pending_overlay_resources_.push_back(
+ make_scoped_ptr(new ResourceProvider::ScopedReadLockGL(
+ resource_provider_, overlay.resource_id)));
+ texture_id = pending_overlay_resources_.back()->texture_id();
+ }
context_support_->ScheduleOverlayPlane(
- overlay.plane_z_order,
- overlay.transform,
- pending_overlay_resources_.back()->texture_id(),
- ToNearestRect(overlay.display_rect),
- overlay.uv_rect);
+ overlay.plane_z_order, overlay.transform, texture_id,
+ ToNearestRect(overlay.display_rect), overlay.uv_rect);
}
}
diff --git a/chromium/cc/output/gl_renderer.h b/chromium/cc/output/gl_renderer.h
index d80e1561502..a090324b820 100644
--- a/chromium/cc/output/gl_renderer.h
+++ b/chromium/cc/output/gl_renderer.h
@@ -13,7 +13,6 @@
#include "cc/output/gl_renderer_draw_cache.h"
#include "cc/output/program_binding.h"
#include "cc/output/renderer.h"
-#include "cc/quads/checkerboard_draw_quad.h"
#include "cc/quads/debug_border_draw_quad.h"
#include "cc/quads/io_surface_draw_quad.h"
#include "cc/quads/render_pass_draw_quad.h"
@@ -63,7 +62,6 @@ class CC_EXPORT GLRenderer : public DirectRenderer {
// Waits for rendering to finish.
void Finish() override;
- void DoNoOp() override;
void SwapBuffers(const CompositorFrameMetadata& metadata) override;
virtual bool IsContextLost();
@@ -154,9 +152,6 @@ class CC_EXPORT GLRenderer : public DirectRenderer {
void ClearFramebuffer(DrawingFrame* frame);
void SetViewport();
- void DrawCheckerboardQuad(const DrawingFrame* frame,
- const CheckerboardDrawQuad* quad,
- const gfx::QuadF* clip_region);
void DrawDebugBorderQuad(const DrawingFrame* frame,
const DebugBorderDrawQuad* quad);
static bool IsDefaultBlendMode(SkXfermode::Mode blend_mode) {
@@ -174,8 +169,7 @@ class CC_EXPORT GLRenderer : public DirectRenderer {
bool use_aa);
scoped_ptr<ScopedResource> GetBackdropTexture(const gfx::Rect& bounding_rect);
- static bool ShouldApplyBackgroundFilters(DrawingFrame* frame,
- const RenderPassDrawQuad* quad);
+ static bool ShouldApplyBackgroundFilters(const RenderPassDrawQuad* quad);
skia::RefPtr<SkImage> ApplyBackgroundFilters(
DrawingFrame* frame,
const RenderPassDrawQuad* quad,
@@ -268,6 +262,7 @@ class CC_EXPORT GLRenderer : public DirectRenderer {
OverlayResourceLockList;
OverlayResourceLockList pending_overlay_resources_;
OverlayResourceLockList in_use_overlay_resources_;
+ OverlayResourceLockList previous_swap_overlay_resources_;
RendererCapabilitiesImpl capabilities_;
@@ -294,8 +289,6 @@ class CC_EXPORT GLRenderer : public DirectRenderer {
TileProgramSwizzle;
typedef ProgramBinding<VertexShaderTile, FragmentShaderRGBATexSwizzleOpaque>
TileProgramSwizzleOpaque;
- typedef ProgramBinding<VertexShaderPosTex, FragmentShaderCheckerboard>
- TileCheckerboardProgram;
// Texture shaders.
typedef ProgramBinding<VertexShaderPosTexTransform,
@@ -362,8 +355,6 @@ class CC_EXPORT GLRenderer : public DirectRenderer {
const TileProgramSwizzleAA* GetTileProgramSwizzleAA(
TexCoordPrecision precision, SamplerType sampler);
- const TileCheckerboardProgram* GetTileCheckerboardProgram();
-
const RenderPassProgram* GetRenderPassProgram(TexCoordPrecision precision,
BlendMode blend_mode);
const RenderPassProgramAA* GetRenderPassProgramAA(TexCoordPrecision precision,
@@ -434,8 +425,6 @@ class CC_EXPORT GLRenderer : public DirectRenderer {
TileProgramSwizzleAA tile_program_swizzle_aa_[LAST_TEX_COORD_PRECISION +
1][LAST_SAMPLER_TYPE + 1];
- TileCheckerboardProgram tile_checkerboard_program_;
-
TextureProgram
texture_program_[LAST_TEX_COORD_PRECISION + 1][LAST_SAMPLER_TYPE + 1];
NonPremultipliedTextureProgram
diff --git a/chromium/cc/output/gl_renderer_unittest.cc b/chromium/cc/output/gl_renderer_unittest.cc
index 4b133c930a5..dd025f2383a 100644
--- a/chromium/cc/output/gl_renderer_unittest.cc
+++ b/chromium/cc/output/gl_renderer_unittest.cc
@@ -14,6 +14,7 @@
#include "cc/output/copy_output_request.h"
#include "cc/output/copy_output_result.h"
#include "cc/output/overlay_strategy_single_on_top.h"
+#include "cc/output/overlay_strategy_underlay.h"
#include "cc/output/texture_mailbox_deleter.h"
#include "cc/quads/texture_draw_quad.h"
#include "cc/resources/resource_provider.h"
@@ -24,7 +25,6 @@
#include "cc/test/fake_renderer_client.h"
#include "cc/test/fake_resource_provider.h"
#include "cc/test/pixel_test.h"
-#include "cc/test/render_pass_test_common.h"
#include "cc/test/render_pass_test_utils.h"
#include "cc/test/test_shared_bitmap_manager.h"
#include "cc/test/test_web_graphics_context_3d.h"
@@ -117,7 +117,6 @@ class GLRendererShaderPixelTest : public GLRendererPixelTest {
}
void TestBasicShaders() {
- EXPECT_PROGRAM_VALID(renderer()->GetTileCheckerboardProgram());
EXPECT_PROGRAM_VALID(renderer()->GetDebugBorderProgram());
EXPECT_PROGRAM_VALID(renderer()->GetSolidColorProgram());
EXPECT_PROGRAM_VALID(renderer()->GetSolidColorProgramAA());
@@ -546,10 +545,9 @@ TEST_F(GLRendererWithDefaultHarnessTest, ExternalStencil) {
output_surface_->set_has_external_stencil_test(true);
- TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
- RenderPassId(1, 0),
- viewport_rect,
- gfx::Transform());
+ RenderPass* root_pass =
+ AddRenderPass(&render_passes_in_draw_order_, RenderPassId(1, 0),
+ viewport_rect, gfx::Transform());
root_pass->has_transparent_background = false;
renderer_->DrawFrame(&render_passes_in_draw_order_,
@@ -743,10 +741,9 @@ TEST_F(GLRendererTest, OpaqueBackground) {
resource_provider.get());
gfx::Rect viewport_rect(1, 1);
- TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
- RenderPassId(1, 0),
- viewport_rect,
- gfx::Transform());
+ RenderPass* root_pass =
+ AddRenderPass(&render_passes_in_draw_order_, RenderPassId(1, 0),
+ viewport_rect, gfx::Transform());
root_pass->has_transparent_background = false;
// On DEBUG builds, render passes with opaque background clear to blue to
@@ -789,10 +786,9 @@ TEST_F(GLRendererTest, TransparentBackground) {
resource_provider.get());
gfx::Rect viewport_rect(1, 1);
- TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
- RenderPassId(1, 0),
- viewport_rect,
- gfx::Transform());
+ RenderPass* root_pass =
+ AddRenderPass(&render_passes_in_draw_order_, RenderPassId(1, 0),
+ viewport_rect, gfx::Transform());
root_pass->has_transparent_background = true;
EXPECT_CALL(*context, discardFramebufferEXT(GL_FRAMEBUFFER, 1, _)).Times(1);
@@ -974,11 +970,12 @@ TEST_F(GLRendererTest, ActiveTextureState) {
// During initialization we are allowed to set any texture parameters.
EXPECT_CALL(*context, texParameteri(_, _, _)).Times(AnyNumber());
- TestRenderPass* root_pass =
+ RenderPass* root_pass =
AddRenderPass(&render_passes_in_draw_order_, RenderPassId(1, 1),
gfx::Rect(100, 100), gfx::Transform());
- root_pass->AppendOneOfEveryQuadType(resource_provider.get(),
- RenderPassId(0, 0));
+ uint32_t mailbox_sync_point;
+ AddOneOfEveryQuadType(root_pass, resource_provider.get(), RenderPassId(0, 0),
+ &mailbox_sync_point);
renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
@@ -990,9 +987,7 @@ TEST_F(GLRendererTest, ActiveTextureState) {
// The sync points for all quads are waited on first. This sync point is
// for a texture quad drawn later in the frame.
- EXPECT_CALL(*context,
- waitSyncPoint(TestRenderPass::kSyncPointForMailboxTextureQuad))
- .Times(1);
+ EXPECT_CALL(*context, waitSyncPoint(mailbox_sync_point)).Times(1);
// yuv_quad is drawn with the default linear filter.
EXPECT_CALL(*context, drawElements(_, _, _, _));
@@ -1015,7 +1010,7 @@ TEST_F(GLRendererTest, ActiveTextureState) {
// The remaining quads also use GL_LINEAR because nearest neighbor
// filtering is currently only used with tile quads.
- EXPECT_CALL(*context, drawElements(_, _, _, _)).Times(7);
+ EXPECT_CALL(*context, drawElements(_, _, _, _)).Times(6);
}
gfx::Rect viewport_rect(100, 100);
@@ -1061,16 +1056,15 @@ TEST_F(GLRendererTest, ShouldClearRootRenderPass) {
gfx::Rect viewport_rect(10, 10);
RenderPassId child_pass_id(2, 0);
- TestRenderPass* child_pass =
+ RenderPass* child_pass =
AddRenderPass(&render_passes_in_draw_order_, child_pass_id, viewport_rect,
gfx::Transform());
AddQuad(child_pass, viewport_rect, SK_ColorBLUE);
RenderPassId root_pass_id(1, 0);
- TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
- root_pass_id,
- viewport_rect,
- gfx::Transform());
+ RenderPass* root_pass =
+ AddRenderPass(&render_passes_in_draw_order_, root_pass_id, viewport_rect,
+ gfx::Transform());
AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
@@ -1153,26 +1147,22 @@ TEST_F(GLRendererTest, ScissorTestWhenClearing) {
gfx::Rect grand_child_rect(25, 25);
RenderPassId grand_child_pass_id(3, 0);
- TestRenderPass* grand_child_pass =
- AddRenderPass(&render_passes_in_draw_order_,
- grand_child_pass_id,
- grand_child_rect,
- gfx::Transform());
+ RenderPass* grand_child_pass =
+ AddRenderPass(&render_passes_in_draw_order_, grand_child_pass_id,
+ grand_child_rect, gfx::Transform());
AddClippedQuad(grand_child_pass, grand_child_rect, SK_ColorYELLOW);
gfx::Rect child_rect(50, 50);
RenderPassId child_pass_id(2, 0);
- TestRenderPass* child_pass = AddRenderPass(&render_passes_in_draw_order_,
- child_pass_id,
- child_rect,
- gfx::Transform());
+ RenderPass* child_pass =
+ AddRenderPass(&render_passes_in_draw_order_, child_pass_id, child_rect,
+ gfx::Transform());
AddQuad(child_pass, child_rect, SK_ColorBLUE);
RenderPassId root_pass_id(1, 0);
- TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
- root_pass_id,
- viewport_rect,
- gfx::Transform());
+ RenderPass* root_pass =
+ AddRenderPass(&render_passes_in_draw_order_, root_pass_id, viewport_rect,
+ gfx::Transform());
AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
AddRenderPassQuad(root_pass, child_pass);
@@ -1248,10 +1238,9 @@ TEST_F(GLRendererTest, NoDiscardOnPartialUpdates) {
{
// Partial frame, should not discard.
RenderPassId root_pass_id(1, 0);
- TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
- root_pass_id,
- viewport_rect,
- gfx::Transform());
+ RenderPass* root_pass =
+ AddRenderPass(&render_passes_in_draw_order_, root_pass_id,
+ viewport_rect, gfx::Transform());
AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
root_pass->damage_rect = gfx::Rect(2, 2, 3, 3);
@@ -1267,10 +1256,9 @@ TEST_F(GLRendererTest, NoDiscardOnPartialUpdates) {
{
// Full frame, should discard.
RenderPassId root_pass_id(1, 0);
- TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
- root_pass_id,
- viewport_rect,
- gfx::Transform());
+ RenderPass* root_pass =
+ AddRenderPass(&render_passes_in_draw_order_, root_pass_id,
+ viewport_rect, gfx::Transform());
AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
root_pass->damage_rect = root_pass->output_rect;
@@ -1287,10 +1275,9 @@ TEST_F(GLRendererTest, NoDiscardOnPartialUpdates) {
// Full frame, external scissor is set, should not discard.
output_surface->set_has_external_stencil_test(true);
RenderPassId root_pass_id(1, 0);
- TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
- root_pass_id,
- viewport_rect,
- gfx::Transform());
+ RenderPass* root_pass =
+ AddRenderPass(&render_passes_in_draw_order_, root_pass_id,
+ viewport_rect, gfx::Transform());
AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
root_pass->damage_rect = root_pass->output_rect;
root_pass->has_transparent_background = false;
@@ -1309,10 +1296,9 @@ TEST_F(GLRendererTest, NoDiscardOnPartialUpdates) {
// Full frame, clipped, should not discard.
clip_rect = gfx::Rect(10, 10, 10, 10);
RenderPassId root_pass_id(1, 0);
- TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
- root_pass_id,
- viewport_rect,
- gfx::Transform());
+ RenderPass* root_pass =
+ AddRenderPass(&render_passes_in_draw_order_, root_pass_id,
+ viewport_rect, gfx::Transform());
AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
root_pass->damage_rect = root_pass->output_rect;
@@ -1329,10 +1315,9 @@ TEST_F(GLRendererTest, NoDiscardOnPartialUpdates) {
// Full frame, doesn't cover the surface, should not discard.
viewport_rect = gfx::Rect(10, 10, 10, 10);
RenderPassId root_pass_id(1, 0);
- TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
- root_pass_id,
- viewport_rect,
- gfx::Transform());
+ RenderPass* root_pass =
+ AddRenderPass(&render_passes_in_draw_order_, root_pass_id,
+ viewport_rect, gfx::Transform());
AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
root_pass->damage_rect = root_pass->output_rect;
@@ -1350,10 +1335,9 @@ TEST_F(GLRendererTest, NoDiscardOnPartialUpdates) {
clip_rect = gfx::Rect(100, 100);
viewport_rect = gfx::Rect(50, 50);
RenderPassId root_pass_id(1, 0);
- TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
- root_pass_id,
- viewport_rect,
- gfx::Transform());
+ RenderPass* root_pass =
+ AddRenderPass(&render_passes_in_draw_order_, root_pass_id,
+ viewport_rect, gfx::Transform());
AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
root_pass->damage_rect = root_pass->output_rect;
@@ -1411,10 +1395,9 @@ TEST_F(GLRendererTest, ScissorAndViewportWithinNonreshapableSurface) {
gfx::Rect quad_rect = gfx::Rect(20, 20, 20, 20);
RenderPassId root_pass_id(1, 0);
- TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
- root_pass_id,
- viewport_rect,
- gfx::Transform());
+ RenderPass* root_pass =
+ AddRenderPass(&render_passes_in_draw_order_, root_pass_id, viewport_rect,
+ gfx::Transform());
AddClippedQuad(root_pass, quad_rect, SK_ColorGREEN);
renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
@@ -1452,7 +1435,7 @@ TEST_F(GLRendererTest, DrawFramePreservesFramebuffer) {
gfx::Rect quad_rect = gfx::Rect(20, 20, 20, 20);
RenderPassId root_pass_id(1, 0);
- TestRenderPass* root_pass =
+ RenderPass* root_pass =
AddRenderPass(&render_passes_in_draw_order_, root_pass_id, viewport_rect,
gfx::Transform());
AddClippedQuad(root_pass, quad_rect, SK_ColorGREEN);
@@ -1477,10 +1460,10 @@ TEST_F(GLRendererShaderTest, DrawRenderPassQuadShaderPermutations) {
gfx::Rect child_rect(50, 50);
RenderPassId child_pass_id(2, 0);
- TestRenderPass* child_pass;
+ RenderPass* child_pass;
RenderPassId root_pass_id(1, 0);
- TestRenderPass* root_pass;
+ RenderPass* root_pass;
ResourceId mask = resource_provider_->CreateResource(
gfx::Size(20, 12), GL_CLAMP_TO_EDGE,
@@ -1744,11 +1727,11 @@ TEST_F(GLRendererShaderTest, DrawRenderPassQuadShaderPermutations) {
TEST_F(GLRendererShaderTest, DrawRenderPassQuadSkipsAAForClippingTransform) {
gfx::Rect child_rect(50, 50);
RenderPassId child_pass_id(2, 0);
- TestRenderPass* child_pass;
+ RenderPass* child_pass;
gfx::Rect viewport_rect(1, 1);
RenderPassId root_pass_id(1, 0);
- TestRenderPass* root_pass;
+ RenderPass* root_pass;
gfx::Transform transform_preventing_aa;
transform_preventing_aa.ApplyPerspectiveDepth(40.0);
@@ -1758,7 +1741,8 @@ TEST_F(GLRendererShaderTest, DrawRenderPassQuadSkipsAAForClippingTransform) {
// Verify that the test transform and test rect actually do cause the clipped
// flag to trigger. Otherwise we are not testing the intended scenario.
bool clipped = false;
- MathUtil::MapQuad(transform_preventing_aa, gfx::QuadF(child_rect), &clipped);
+ MathUtil::MapQuad(transform_preventing_aa, gfx::QuadF(gfx::RectF(child_rect)),
+ &clipped);
ASSERT_TRUE(clipped);
child_pass = AddRenderPass(&render_passes_in_draw_order_,
@@ -1793,7 +1777,7 @@ TEST_F(GLRendererShaderTest, DrawRenderPassQuadSkipsAAForClippingTransform) {
TEST_F(GLRendererShaderTest, DrawSolidColorShader) {
gfx::Rect viewport_rect(1, 1);
RenderPassId root_pass_id(1, 0);
- TestRenderPass* root_pass;
+ RenderPass* root_pass;
gfx::Transform pixel_aligned_transform_causing_aa;
pixel_aligned_transform_causing_aa.Translate(25.5f, 25.5f);
@@ -1871,10 +1855,9 @@ class MockOutputSurfaceTest : public GLRendererTest {
void DrawFrame(float device_scale_factor,
const gfx::Rect& device_viewport_rect) {
RenderPassId render_pass_id(1, 0);
- TestRenderPass* render_pass = AddRenderPass(&render_passes_in_draw_order_,
- render_pass_id,
- device_viewport_rect,
- gfx::Transform());
+ RenderPass* render_pass =
+ AddRenderPass(&render_passes_in_draw_order_, render_pass_id,
+ device_viewport_rect, gfx::Transform());
AddQuad(render_pass, device_viewport_rect, SK_ColorGREEN);
EXPECT_CALL(output_surface_, EnsureBackbuffer()).WillRepeatedly(Return());
@@ -2024,9 +2007,10 @@ class TestOverlayProcessor : public OverlayProcessor {
public:
Strategy() {}
~Strategy() override {}
- MOCK_METHOD2(Attempt,
+ MOCK_METHOD3(Attempt,
bool(RenderPassList* render_passes_in_draw_order,
- OverlayCandidateList* candidates));
+ OverlayCandidateList* candidates,
+ float device_scale_factor));
};
explicit TestOverlayProcessor(OutputSurface* surface)
@@ -2073,7 +2057,7 @@ TEST_F(GLRendererTest, DontOverlayWithCopyRequests) {
renderer.SetOverlayProcessor(processor);
gfx::Rect viewport_rect(1, 1);
- TestRenderPass* root_pass =
+ RenderPass* root_pass =
AddRenderPass(&render_passes_in_draw_order_, RenderPassId(1, 0),
viewport_rect, gfx::Transform());
root_pass->has_transparent_background = false;
@@ -2106,7 +2090,7 @@ TEST_F(GLRendererTest, DontOverlayWithCopyRequests) {
// added a fake strategy, so checking for Attempt calls checks if there was
// any attempt to overlay, which there shouldn't be. We can't use the quad
// list because the render pass is cleaned up by DrawFrame.
- EXPECT_CALL(*processor->strategy_, Attempt(_, _)).Times(0);
+ EXPECT_CALL(*processor->strategy_, Attempt(_, _, _)).Times(0);
renderer.DrawFrame(&render_passes_in_draw_order_, 1.f, viewport_rect,
viewport_rect, false);
Mock::VerifyAndClearExpectations(processor->strategy_);
@@ -2123,7 +2107,7 @@ TEST_F(GLRendererTest, DontOverlayWithCopyRequests) {
gfx::PointF(1, 1), SK_ColorTRANSPARENT, vertex_opacity,
flipped, nearest_neighbor);
- EXPECT_CALL(*processor->strategy_, Attempt(_, _)).Times(1);
+ EXPECT_CALL(*processor->strategy_, Attempt(_, _, _)).Times(1);
renderer.DrawFrame(&render_passes_in_draw_order_, 1.f, viewport_rect,
viewport_rect, false);
}
@@ -2132,8 +2116,15 @@ class SingleOverlayOnTopProcessor : public OverlayProcessor {
public:
class SingleOverlayValidator : public OverlayCandidateValidator {
public:
+ void GetStrategies(OverlayProcessor::StrategyList* strategies) override {
+ strategies->push_back(scoped_ptr<OverlayProcessor::Strategy>(
+ new OverlayStrategyCommon(this, new OverlayStrategySingleOnTop)));
+ strategies->push_back(scoped_ptr<OverlayProcessor::Strategy>(
+ new OverlayStrategyCommon(this, new OverlayStrategyUnderlay)));
+ }
+
void CheckOverlaySupport(OverlayCandidateList* surfaces) override {
- ASSERT_EQ(2U, surfaces->size());
+ ASSERT_EQ(1U, surfaces->size());
OverlayCandidate& candidate = surfaces->back();
candidate.overlay_handled = true;
}
@@ -2143,8 +2134,8 @@ class SingleOverlayOnTopProcessor : public OverlayProcessor {
: OverlayProcessor(surface) {}
void Initialize() override {
- strategies_.push_back(
- scoped_ptr<Strategy>(new OverlayStrategySingleOnTop(&validator_)));
+ strategies_.push_back(scoped_ptr<Strategy>(new OverlayStrategyCommon(
+ &validator_, new OverlayStrategySingleOnTop)));
}
SingleOverlayValidator validator_;
@@ -2199,12 +2190,12 @@ TEST_F(GLRendererTest, OverlaySyncPointsAreProcessed) {
renderer.SetOverlayProcessor(processor);
gfx::Rect viewport_rect(1, 1);
- TestRenderPass* root_pass =
+ RenderPass* root_pass =
AddRenderPass(&render_passes_in_draw_order_, RenderPassId(1, 0),
viewport_rect, gfx::Transform());
root_pass->has_transparent_background = false;
- unsigned sync_point = TestRenderPass::kSyncPointForMailboxTextureQuad;
+ unsigned sync_point = 29;
TextureMailbox mailbox =
TextureMailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point);
scoped_ptr<SingleReleaseCallbackImpl> release_callback =
@@ -2231,9 +2222,7 @@ TEST_F(GLRendererTest, OverlaySyncPointsAreProcessed) {
// Verify that overlay_quad actually gets turned into an overlay, and even
// though it's not drawn, that its sync point is waited on.
- EXPECT_CALL(*context,
- waitSyncPoint(TestRenderPass::kSyncPointForMailboxTextureQuad))
- .Times(1);
+ EXPECT_CALL(*context, waitSyncPoint(sync_point)).Times(1);
EXPECT_CALL(overlay_scheduler,
Schedule(1, gfx::OVERLAY_TRANSFORM_NONE, _, viewport_rect,
BoundingRect(uv_top_left, uv_bottom_right))).Times(1);
diff --git a/chromium/cc/output/latency_info_swap_promise.cc b/chromium/cc/output/latency_info_swap_promise.cc
index 5e08470fb07..3b267454076 100644
--- a/chromium/cc/output/latency_info_swap_promise.cc
+++ b/chromium/cc/output/latency_info_swap_promise.cc
@@ -34,7 +34,7 @@ LatencyInfoSwapPromise::~LatencyInfoSwapPromise() {
}
void LatencyInfoSwapPromise::DidSwap(CompositorFrameMetadata* metadata) {
- DCHECK(!latency_.terminated);
+ DCHECK(!latency_.terminated());
metadata->latency_info.push_back(latency_);
}
@@ -47,14 +47,16 @@ void LatencyInfoSwapPromise::DidNotSwap(DidNotSwapReason reason) {
}
int64 LatencyInfoSwapPromise::TraceId() const {
- return latency_.trace_id;
+ return latency_.trace_id();
}
// Trace the original LatencyInfo of a LatencyInfoSwapPromise
void LatencyInfoSwapPromise::OnCommit() {
- TRACE_EVENT_FLOW_STEP0("input,benchmark", "LatencyInfo.Flow",
+ TRACE_EVENT_WITH_FLOW1("input,benchmark",
+ "LatencyInfo.Flow",
TRACE_ID_DONT_MANGLE(TraceId()),
- "HanldeInputEventMainCommit");
+ TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
+ "step", "HandleInputEventMainCommit");
}
} // namespace cc
diff --git a/chromium/cc/output/output_surface.cc b/chromium/cc/output/output_surface.cc
index a597a87d845..38b13463c1b 100644
--- a/chromium/cc/output/output_surface.cc
+++ b/chromium/cc/output/output_surface.cc
@@ -14,13 +14,107 @@
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/context_support.h"
#include "gpu/command_buffer/client/gles2_interface.h"
+#include "third_party/skia/include/core/SkTraceMemoryDump.h"
#include "third_party/skia/include/gpu/GrContext.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
+#include "ui/gl/trace_util.h"
+class SkDiscardableMemory;
namespace cc {
+namespace {
+
+// Constants used by SkiaGpuTraceMemoryDump to identify different memory types.
+const char* kGLTextureBackingType = "gl_texture";
+const char* kGLBufferBackingType = "gl_buffer";
+const char* kGLRenderbufferBackingType = "gl_renderbuffer";
+
+// Derives from SkTraceMemoryDump and implements graphics specific memory
+// backing functionality.
+class SkiaGpuTraceMemoryDump : public SkTraceMemoryDump {
+ public:
+ // This should never outlive the provided ProcessMemoryDump, as it should
+ // always be scoped to a single OnMemoryDump funciton call.
+ explicit SkiaGpuTraceMemoryDump(base::trace_event::ProcessMemoryDump* pmd,
+ uint64_t share_group_tracing_guid)
+ : pmd_(pmd), share_group_tracing_guid_(share_group_tracing_guid) {}
+
+ // Overridden from SkTraceMemoryDump:
+ void dumpNumericValue(const char* dump_name,
+ const char* value_name,
+ const char* units,
+ uint64_t value) override {
+ auto dump = GetOrCreateAllocatorDump(dump_name);
+ dump->AddScalar(value_name, units, value);
+ }
+
+ void setMemoryBacking(const char* dump_name,
+ const char* backing_type,
+ const char* backing_object_id) override {
+ const uint64 tracing_process_id =
+ base::trace_event::MemoryDumpManager::GetInstance()
+ ->GetTracingProcessId();
+
+ // For uniformity, skia provides this value as a string. Convert back to a
+ // uint32_t.
+ uint32_t gl_id =
+ std::strtoul(backing_object_id, nullptr /* str_end */, 10 /* base */);
+
+ // Populated in if statements below.
+ base::trace_event::MemoryAllocatorDumpGuid guid;
+
+ if (strcmp(backing_type, kGLTextureBackingType) == 0) {
+ guid = gfx::GetGLTextureClientGUIDForTracing(share_group_tracing_guid_,
+ gl_id);
+ } else if (strcmp(backing_type, kGLBufferBackingType) == 0) {
+ guid = gfx::GetGLBufferGUIDForTracing(tracing_process_id, gl_id);
+ } else if (strcmp(backing_type, kGLRenderbufferBackingType) == 0) {
+ guid = gfx::GetGLRenderbufferGUIDForTracing(tracing_process_id, gl_id);
+ }
+
+ if (!guid.empty()) {
+ pmd_->CreateSharedGlobalAllocatorDump(guid);
+
+ auto* dump = GetOrCreateAllocatorDump(dump_name);
+
+ const int kImportance = 2;
+ pmd_->AddOwnershipEdge(dump->guid(), guid, kImportance);
+ }
+ }
+
+ void setDiscardableMemoryBacking(
+ const char* dump_name,
+ const SkDiscardableMemory& discardable_memory_object) override {
+ // We don't use this class for dumping discardable memory.
+ NOTREACHED();
+ }
+
+ LevelOfDetail getRequestedDetails() const override {
+ // TODO(ssid): Use MemoryDumpArgs to create light dumps when requested
+ // (crbug.com/499731).
+ return kObjectsBreakdowns_LevelOfDetail;
+ }
+
+ private:
+ // Helper to create allocator dumps.
+ base::trace_event::MemoryAllocatorDump* GetOrCreateAllocatorDump(
+ const char* dump_name) {
+ auto dump = pmd_->GetAllocatorDump(dump_name);
+ if (!dump)
+ dump = pmd_->CreateAllocatorDump(dump_name);
+ return dump;
+ }
+
+ base::trace_event::ProcessMemoryDump* pmd_;
+ uint64_t share_group_tracing_guid_;
+
+ DISALLOW_COPY_AND_ASSIGN(SkiaGpuTraceMemoryDump);
+};
+
+} // namespace
+
OutputSurface::OutputSurface(
const scoped_refptr<ContextProvider>& context_provider,
const scoped_refptr<ContextProvider>& worker_context_provider,
@@ -32,6 +126,7 @@ OutputSurface::OutputSurface(
device_scale_factor_(-1),
external_stencil_test_enabled_(false),
weak_ptr_factory_(this) {
+ client_thread_checker_.DetachFromThread();
}
OutputSurface::OutputSurface(
@@ -101,16 +196,8 @@ void OutputSurface::SetExternalDrawConstraints(
}
OutputSurface::~OutputSurface() {
- if (context_provider_.get()) {
- context_provider_->SetLostContextCallback(
- ContextProvider::LostContextCallback());
- context_provider_->SetMemoryPolicyChangedCallback(
- ContextProvider::MemoryPolicyChangedCallback());
- }
- if (worker_context_provider_.get()) {
- worker_context_provider_->SetLostContextCallback(
- ContextProvider::LostContextCallback());
- }
+ if (client_)
+ DetachFromClientInternal();
}
bool OutputSurface::HasExternalStencilTest() const {
@@ -118,7 +205,9 @@ bool OutputSurface::HasExternalStencilTest() const {
}
bool OutputSurface::BindToClient(OutputSurfaceClient* client) {
+ DCHECK(client_thread_checker_.CalledOnValidThread());
DCHECK(client);
+ DCHECK(!client_);
client_ = client;
bool success = true;
@@ -132,24 +221,27 @@ bool OutputSurface::BindToClient(OutputSurfaceClient* client) {
}
}
- if (success && worker_context_provider_.get()) {
- success = worker_context_provider_->BindToCurrentThread();
- if (success) {
- worker_context_provider_->SetupLock();
- // The destructor resets the context lost callback, so base::Unretained
- // is safe, as long as the worker threads stop using the context before
- // the output surface is destroyed.
- worker_context_provider_->SetLostContextCallback(base::Bind(
- &OutputSurface::DidLoseOutputSurface, base::Unretained(this)));
- }
- }
-
if (!success)
client_ = NULL;
+ // In certain cases, ThreadTaskRunnerHandle isn't set (Android Webview).
+ // Don't register a dump provider in these cases.
+ // TODO(ericrk): Get this working in Android Webview. crbug.com/517156
+ if (client_ && base::ThreadTaskRunnerHandle::IsSet()) {
+ // Now that we are on the context thread, register a dump provider with this
+ // thread's task runner. This will overwrite any previous dump provider
+ // registered.
+ base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
+ this, base::ThreadTaskRunnerHandle::Get());
+ }
+
return success;
}
+void OutputSurface::DetachFromClient() {
+ DetachFromClientInternal();
+}
+
void OutputSurface::EnsureBackbuffer() {
if (software_device_)
software_device_->EnsureBackbuffer();
@@ -176,10 +268,6 @@ void OutputSurface::Reshape(const gfx::Size& size, float scale_factor) {
software_device_->Resize(size, scale_factor);
}
-gfx::Size OutputSurface::SurfaceSize() const {
- return surface_size_;
-}
-
void OutputSurface::BindFramebuffer() {
DCHECK(context_provider_.get());
context_provider_->ContextGL()->BindFramebuffer(GL_FRAMEBUFFER, 0);
@@ -211,17 +299,21 @@ OverlayCandidateValidator* OutputSurface::GetOverlayCandidateValidator() const {
return nullptr;
}
+bool OutputSurface::IsDisplayedAsOverlayPlane() const {
+ return false;
+}
+
+unsigned OutputSurface::GetOverlayTextureId() const {
+ return 0;
+}
+
void OutputSurface::SetWorkerContextShouldAggressivelyFreeResources(
bool aggressively_free_resources) {
TRACE_EVENT1("cc",
"OutputSurface::SetWorkerContextShouldAggressivelyFreeResources",
"aggressively_free_resources", aggressively_free_resources);
if (auto* context_provider = worker_context_provider()) {
- // The context lock must be held while accessing the worker context.
- base::AutoLock context_lock(*context_provider->GetLock());
-
- // Allow context to bind to current thread.
- context_provider->DetachFromThread();
+ ContextProvider::ScopedContextLock scoped_context(context_provider);
if (aggressively_free_resources) {
context_provider->DeleteCachedResources();
@@ -231,9 +323,6 @@ void OutputSurface::SetWorkerContextShouldAggressivelyFreeResources(
context_support->SetAggressivelyFreeResources(
aggressively_free_resources);
}
-
- // Allow context to bind to other threads.
- context_provider->DetachFromThread();
}
}
@@ -241,4 +330,47 @@ bool OutputSurface::SurfaceIsSuspendForRecycle() const {
return false;
}
+bool OutputSurface::OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
+ base::trace_event::ProcessMemoryDump* pmd) {
+ if (auto* context_provider = this->context_provider()) {
+ // No need to lock, main context provider is not shared.
+ if (auto* gr_context = context_provider->GrContext()) {
+ SkiaGpuTraceMemoryDump trace_memory_dump(
+ pmd, context_provider->ContextSupport()->ShareGroupTracingGUID());
+ gr_context->dumpMemoryStatistics(&trace_memory_dump);
+ }
+ }
+ if (auto* context_provider = worker_context_provider()) {
+ ContextProvider::ScopedContextLock scoped_context(context_provider);
+
+ if (auto* gr_context = context_provider->GrContext()) {
+ SkiaGpuTraceMemoryDump trace_memory_dump(
+ pmd, context_provider->ContextSupport()->ShareGroupTracingGUID());
+ gr_context->dumpMemoryStatistics(&trace_memory_dump);
+ }
+ }
+
+ return true;
+}
+
+void OutputSurface::DetachFromClientInternal() {
+ DCHECK(client_thread_checker_.CalledOnValidThread());
+ DCHECK(client_);
+
+ // Unregister any dump provider. Safe to call (no-op) if we have not yet
+ // registered.
+ base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
+ this);
+
+ if (context_provider_.get()) {
+ context_provider_->SetLostContextCallback(
+ ContextProvider::LostContextCallback());
+ context_provider_->SetMemoryPolicyChangedCallback(
+ ContextProvider::MemoryPolicyChangedCallback());
+ }
+ context_provider_ = nullptr;
+ client_ = nullptr;
+ weak_ptr_factory_.InvalidateWeakPtrs();
+}
+
} // namespace cc
diff --git a/chromium/cc/output/output_surface.h b/chromium/cc/output/output_surface.h
index 423dc6317c3..bb6a59e7ecd 100644
--- a/chromium/cc/output/output_surface.h
+++ b/chromium/cc/output/output_surface.h
@@ -11,6 +11,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
+#include "base/threading/thread_checker.h"
#include "cc/base/cc_export.h"
#include "cc/output/context_provider.h"
#include "cc/output/overlay_candidate_validator.h"
@@ -18,7 +19,9 @@
namespace base { class SingleThreadTaskRunner; }
-namespace ui { struct LatencyInfo; }
+namespace ui {
+class LatencyInfo;
+}
namespace gfx {
class Rect;
@@ -40,7 +43,7 @@ class OutputSurfaceClient;
// From here on, it will only be used on the compositor thread.
// 3. If the 3D context is lost, then the compositor will delete the output
// surface (on the compositor thread) and go back to step 1.
-class CC_EXPORT OutputSurface {
+class CC_EXPORT OutputSurface : public base::trace_event::MemoryDumpProvider {
public:
enum {
DEFAULT_MAX_FRAMES_PENDING = 2
@@ -59,7 +62,7 @@ class CC_EXPORT OutputSurface {
OutputSurface(const scoped_refptr<ContextProvider>& context_provider,
scoped_ptr<SoftwareOutputDevice> software_device);
- virtual ~OutputSurface();
+ ~OutputSurface() override;
struct Capabilities {
Capabilities()
@@ -110,15 +113,20 @@ class CC_EXPORT OutputSurface {
// Called by the compositor on the compositor thread. This is a place where
// thread-specific data for the output surface can be initialized, since from
- // this point on the output surface will only be used on the compositor
- // thread.
+ // this point to when DetachFromClient() is called the output surface will
+ // only be used on the compositor thread.
virtual bool BindToClient(OutputSurfaceClient* client);
+ // Called by the compositor on the compositor thread. This is a place where
+ // thread-specific data for the output surface can be uninitialized.
+ virtual void DetachFromClient();
+
virtual void EnsureBackbuffer();
virtual void DiscardBackbuffer();
virtual void Reshape(const gfx::Size& size, float scale_factor);
- virtual gfx::Size SurfaceSize() const;
+ gfx::Size SurfaceSize() const { return surface_size_; }
+ float device_scale_factor() const { return device_scale_factor_; }
// If supported, this causes a ReclaimResources for all resources that are
// currently in use.
@@ -143,6 +151,12 @@ class CC_EXPORT OutputSurface {
// Get the class capable of informing cc of hardware overlay capability.
virtual OverlayCandidateValidator* GetOverlayCandidateValidator() const;
+ // Returns true if a main image overlay plane should be scheduled.
+ virtual bool IsDisplayedAsOverlayPlane() const;
+
+ // Get the texture for the main image's overlay.
+ virtual unsigned GetOverlayTextureId() const;
+
void DidLoseOutputSurface();
void SetMemoryPolicy(const ManagedMemoryPolicy& policy);
@@ -159,6 +173,10 @@ class CC_EXPORT OutputSurface {
// If this returns true, then the surface will not attempt to draw.
virtual bool SurfaceIsSuspendForRecycle() const;
+ // base::trace_event::MemoryDumpProvider implementation.
+ bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
+ base::trace_event::ProcessMemoryDump* pmd) override;
+
protected:
OutputSurfaceClient* client_;
@@ -170,6 +188,7 @@ class CC_EXPORT OutputSurface {
scoped_ptr<SoftwareOutputDevice> software_device_;
gfx::Size surface_size_;
float device_scale_factor_;
+ base::ThreadChecker client_thread_checker_;
void CommitVSyncParameters(base::TimeTicks timebase,
base::TimeDelta interval);
@@ -184,6 +203,7 @@ class CC_EXPORT OutputSurface {
const gfx::Rect& viewport_rect_for_tile_priority,
const gfx::Transform& transform_for_tile_priority,
bool resourceless_software_draw);
+ void DetachFromClientInternal();
private:
bool external_stencil_test_enabled_;
diff --git a/chromium/cc/output/overlay_candidate.cc b/chromium/cc/output/overlay_candidate.cc
index 7a825707d1d..5ecdc32ed36 100644
--- a/chromium/cc/output/overlay_candidate.cc
+++ b/chromium/cc/output/overlay_candidate.cc
@@ -8,6 +8,10 @@
#include <limits>
#include "base/logging.h"
#include "cc/base/math_util.h"
+#include "cc/quads/io_surface_draw_quad.h"
+#include "cc/quads/solid_color_draw_quad.h"
+#include "cc/quads/stream_video_draw_quad.h"
+#include "cc/quads/texture_draw_quad.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/vector3d_f.h"
@@ -32,22 +36,8 @@ Axis VectorToAxis(const gfx::Vector3dF& vec) {
return NONE;
}
-} // namespace
-
-OverlayCandidate::OverlayCandidate()
- : transform(gfx::OVERLAY_TRANSFORM_NONE),
- format(RGBA_8888),
- uv_rect(0.f, 0.f, 1.f, 1.f),
- resource_id(0),
- plane_z_order(0),
- overlay_handled(false) {}
-
-OverlayCandidate::~OverlayCandidate() {}
-
-// static
-gfx::OverlayTransform OverlayCandidate::GetOverlayTransform(
- const gfx::Transform& quad_transform,
- bool y_flipped) {
+gfx::OverlayTransform GetOverlayTransform(const gfx::Transform& quad_transform,
+ bool y_flipped) {
if (!quad_transform.Preserves2dAxisAlignment()) {
return gfx::OVERLAY_TRANSFORM_INVALID;
}
@@ -77,10 +67,10 @@ gfx::OverlayTransform OverlayCandidate::GetOverlayTransform(
return gfx::OVERLAY_TRANSFORM_INVALID;
}
-// static
-gfx::OverlayTransform OverlayCandidate::ModifyTransform(
- gfx::OverlayTransform in,
- gfx::OverlayTransform delta) {
+// Apply transform |delta| to |in| and return the resulting transform,
+// or OVERLAY_TRANSFORM_INVALID.
+gfx::OverlayTransform ComposeTransforms(gfx::OverlayTransform delta,
+ gfx::OverlayTransform in) {
// There are 8 different possible transforms. We can characterize these
// by looking at where the origin moves and the direction the horizontal goes.
// (TL=top-left, BR=bottom-right, H=horizontal, V=vertical).
@@ -173,15 +163,130 @@ gfx::OverlayTransform OverlayCandidate::ModifyTransform(
}
}
+} // namespace
+
+OverlayCandidate::OverlayCandidate()
+ : transform(gfx::OVERLAY_TRANSFORM_NONE),
+ format(RGBA_8888),
+ uv_rect(0.f, 0.f, 1.f, 1.f),
+ is_clipped(false),
+ use_output_surface_for_resource(false),
+ resource_id(0),
+ plane_z_order(0),
+ overlay_handled(false) {}
+
+OverlayCandidate::~OverlayCandidate() {}
+
+// static
+bool OverlayCandidate::FromDrawQuad(const DrawQuad* quad,
+ OverlayCandidate* candidate) {
+ if (quad->needs_blending || quad->shared_quad_state->opacity != 1.f ||
+ quad->shared_quad_state->blend_mode != SkXfermode::kSrcOver_Mode)
+ return false;
+
+ auto& transform = quad->shared_quad_state->quad_to_target_transform;
+ candidate->display_rect = gfx::RectF(quad->rect);
+ transform.TransformRect(&candidate->display_rect);
+ candidate->quad_rect_in_target_space =
+ MathUtil::MapEnclosingClippedRect(transform, quad->rect);
+
+ candidate->format = RGBA_8888;
+ candidate->clip_rect = quad->shared_quad_state->clip_rect;
+ candidate->is_clipped = quad->shared_quad_state->is_clipped;
+
+ switch (quad->material) {
+ case DrawQuad::TEXTURE_CONTENT:
+ return FromTextureQuad(TextureDrawQuad::MaterialCast(quad), candidate);
+ case DrawQuad::STREAM_VIDEO_CONTENT:
+ return FromStreamVideoQuad(StreamVideoDrawQuad::MaterialCast(quad),
+ candidate);
+ case DrawQuad::IO_SURFACE_CONTENT:
+ return FromIOSurfaceQuad(IOSurfaceDrawQuad::MaterialCast(quad),
+ candidate);
+ default:
+ break;
+ }
+
+ return false;
+}
+
+// static
+bool OverlayCandidate::FromTextureQuad(const TextureDrawQuad* quad,
+ OverlayCandidate* candidate) {
+ if (!quad->allow_overlay())
+ return false;
+ gfx::OverlayTransform overlay_transform = GetOverlayTransform(
+ quad->shared_quad_state->quad_to_target_transform, quad->y_flipped);
+ if (quad->background_color != SK_ColorTRANSPARENT ||
+ quad->premultiplied_alpha ||
+ overlay_transform == gfx::OVERLAY_TRANSFORM_INVALID)
+ return false;
+ candidate->resource_id = quad->resource_id();
+ candidate->resource_size_in_pixels = quad->resource_size_in_pixels();
+ candidate->transform = overlay_transform;
+ candidate->uv_rect = BoundingRect(quad->uv_top_left, quad->uv_bottom_right);
+ return true;
+}
+
+// static
+bool OverlayCandidate::FromStreamVideoQuad(const StreamVideoDrawQuad* quad,
+ OverlayCandidate* candidate) {
+ if (!quad->allow_overlay())
+ return false;
+ gfx::OverlayTransform overlay_transform = GetOverlayTransform(
+ quad->shared_quad_state->quad_to_target_transform, false);
+ if (overlay_transform == gfx::OVERLAY_TRANSFORM_INVALID)
+ return false;
+ if (!quad->matrix.IsScaleOrTranslation()) {
+ // We cannot handle anything other than scaling & translation for texture
+ // coordinates yet.
+ return false;
+ }
+ candidate->resource_id = quad->resource_id();
+ candidate->resource_size_in_pixels = quad->resource_size_in_pixels();
+ candidate->transform = overlay_transform;
+
+ gfx::Point3F uv0 = gfx::Point3F(0, 0, 0);
+ gfx::Point3F uv1 = gfx::Point3F(1, 1, 0);
+ quad->matrix.TransformPoint(&uv0);
+ quad->matrix.TransformPoint(&uv1);
+ gfx::Vector3dF delta = uv1 - uv0;
+ if (delta.x() < 0) {
+ candidate->transform = ComposeTransforms(
+ gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL, candidate->transform);
+ float x0 = uv0.x();
+ uv0.set_x(uv1.x());
+ uv1.set_x(x0);
+ delta.set_x(-delta.x());
+ }
+
+ if (delta.y() < 0) {
+ // In this situation, uv0y < uv1y. Since we overlay inverted, a request
+ // to invert the source texture means we can just output the texture
+ // normally and it will be correct.
+ candidate->uv_rect = gfx::RectF(uv0.x(), uv1.y(), delta.x(), -delta.y());
+ } else {
+ candidate->transform = ComposeTransforms(
+ gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL, candidate->transform);
+ candidate->uv_rect = gfx::RectF(uv0.x(), uv0.y(), delta.x(), delta.y());
+ }
+ return true;
+}
+
// static
-gfx::RectF OverlayCandidate::GetOverlayRect(
- const gfx::Transform& quad_transform,
- const gfx::Rect& rect) {
- DCHECK(quad_transform.Preserves2dAxisAlignment());
-
- gfx::RectF float_rect(rect);
- quad_transform.TransformRect(&float_rect);
- return float_rect;
+bool OverlayCandidate::FromIOSurfaceQuad(const IOSurfaceDrawQuad* quad,
+ OverlayCandidate* candidate) {
+ if (!quad->allow_overlay)
+ return false;
+ gfx::OverlayTransform overlay_transform = GetOverlayTransform(
+ quad->shared_quad_state->quad_to_target_transform, false);
+ if (overlay_transform != gfx::OVERLAY_TRANSFORM_NONE)
+ return false;
+ candidate->resource_id = quad->io_surface_resource_id();
+ candidate->resource_size_in_pixels = quad->io_surface_size;
+ candidate->transform = overlay_transform;
+ candidate->uv_rect = gfx::RectF(1.f, 1.f);
+ return true;
}
} // namespace cc
diff --git a/chromium/cc/output/overlay_candidate.h b/chromium/cc/output/overlay_candidate.h
index b3e7fb359f1..f54a7ddf113 100644
--- a/chromium/cc/output/overlay_candidate.h
+++ b/chromium/cc/output/overlay_candidate.h
@@ -10,23 +10,27 @@
#include "cc/base/cc_export.h"
#include "cc/resources/resource_format.h"
#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/rect_f.h"
+#include "ui/gfx/geometry/size.h"
#include "ui/gfx/overlay_transform.h"
#include "ui/gfx/transform.h"
+namespace gfx {
+class Rect;
+}
+
namespace cc {
+class DrawQuad;
+class IOSurfaceDrawQuad;
+class StreamVideoDrawQuad;
+class TextureDrawQuad;
+
class CC_EXPORT OverlayCandidate {
public:
- static gfx::OverlayTransform GetOverlayTransform(
- const gfx::Transform& quad_transform,
- bool y_flipped);
- // Apply transform |delta| to |in| and return the resulting transform,
- // or OVERLAY_TRANSFORM_INVALID.
- static gfx::OverlayTransform ModifyTransform(gfx::OverlayTransform in,
- gfx::OverlayTransform delta);
- static gfx::RectF GetOverlayRect(const gfx::Transform& quad_transform,
- const gfx::Rect& rect);
-
+ // Returns true and fills in |candidate| if |draw_quad| is of a known quad
+ // type and contains an overlayable resource.
+ static bool FromDrawQuad(const DrawQuad* quad, OverlayCandidate* candidate);
OverlayCandidate();
~OverlayCandidate();
@@ -41,6 +45,15 @@ class CC_EXPORT OverlayCandidate {
gfx::RectF display_rect;
// Crop within the buffer to be placed inside |display_rect|.
gfx::RectF uv_rect;
+ // Quad geometry rect after applying the quad_transform().
+ gfx::Rect quad_rect_in_target_space;
+ // Clip rect in the target content space after composition.
+ gfx::Rect clip_rect;
+ // If the quad is clipped after composition.
+ bool is_clipped;
+ // True if the texture for this overlay should be the same one used by the
+ // output surface's main overlay.
+ bool use_output_surface_for_resource;
// Texture resource to present in an overlay.
unsigned resource_id;
// Stacking order of the overlay plane relative to the main surface,
@@ -50,6 +63,14 @@ class CC_EXPORT OverlayCandidate {
// To be modified by the implementer if this candidate can go into
// an overlay.
bool overlay_handled;
+
+ private:
+ static bool FromTextureQuad(const TextureDrawQuad* quad,
+ OverlayCandidate* candidate);
+ static bool FromStreamVideoQuad(const StreamVideoDrawQuad* quad,
+ OverlayCandidate* candidate);
+ static bool FromIOSurfaceQuad(const IOSurfaceDrawQuad* quad,
+ OverlayCandidate* candidate);
};
typedef std::vector<OverlayCandidate> OverlayCandidateList;
diff --git a/chromium/cc/output/overlay_candidate_validator.h b/chromium/cc/output/overlay_candidate_validator.h
index 60647316f8b..8586b4de170 100644
--- a/chromium/cc/output/overlay_candidate_validator.h
+++ b/chromium/cc/output/overlay_candidate_validator.h
@@ -9,6 +9,7 @@
#include "cc/base/cc_export.h"
#include "cc/output/overlay_candidate.h"
+#include "cc/output/overlay_processor.h"
namespace cc {
@@ -16,6 +17,9 @@ namespace cc {
// configurations for a particular output device.
class CC_EXPORT OverlayCandidateValidator {
public:
+ // Populates a list of strategies that may work with this validator.
+ virtual void GetStrategies(OverlayProcessor::StrategyList* strategies) = 0;
+
// A list of possible overlay candidates is presented to this function.
// The expected result is that those candidates that can be in a separate
// plane are marked with |overlay_handled| set to true, otherwise they are
diff --git a/chromium/cc/output/overlay_processor.cc b/chromium/cc/output/overlay_processor.cc
index baae69dd10e..ab334ec9534 100644
--- a/chromium/cc/output/overlay_processor.cc
+++ b/chromium/cc/output/overlay_processor.cc
@@ -17,15 +17,10 @@ OverlayProcessor::OverlayProcessor(OutputSurface* surface) : surface_(surface) {
void OverlayProcessor::Initialize() {
DCHECK(surface_);
-
- OverlayCandidateValidator* candidates =
+ OverlayCandidateValidator* validator =
surface_->GetOverlayCandidateValidator();
- if (candidates) {
- strategies_.push_back(
- scoped_ptr<Strategy>(new OverlayStrategySingleOnTop(candidates)));
- strategies_.push_back(
- scoped_ptr<Strategy>(new OverlayStrategyUnderlay(candidates)));
- }
+ if (validator)
+ validator->GetStrategies(&strategies_);
}
OverlayProcessor::~OverlayProcessor() {}
@@ -35,8 +30,10 @@ void OverlayProcessor::ProcessForOverlays(
OverlayCandidateList* candidate_list) {
for (StrategyList::iterator it = strategies_.begin(); it != strategies_.end();
++it) {
- if ((*it)->Attempt(render_passes_in_draw_order, candidate_list))
+ if ((*it)->Attempt(render_passes_in_draw_order, candidate_list,
+ surface_->device_scale_factor())) {
return;
+ }
}
}
diff --git a/chromium/cc/output/overlay_processor.h b/chromium/cc/output/overlay_processor.h
index e37816c9565..feba0481b29 100644
--- a/chromium/cc/output/overlay_processor.h
+++ b/chromium/cc/output/overlay_processor.h
@@ -25,7 +25,8 @@ class CC_EXPORT OverlayProcessor {
// and adds any additional passes necessary to represent overlays to
// |render_passes_in_draw_order|.
virtual bool Attempt(RenderPassList* render_passes_in_draw_order,
- OverlayCandidateList* candidates) = 0;
+ OverlayCandidateList* candidates,
+ float device_scale_factor) = 0;
};
typedef ScopedPtrVector<Strategy> StrategyList;
diff --git a/chromium/cc/output/overlay_strategy_all_or_nothing.cc b/chromium/cc/output/overlay_strategy_all_or_nothing.cc
new file mode 100644
index 00000000000..bead0a707b6
--- /dev/null
+++ b/chromium/cc/output/overlay_strategy_all_or_nothing.cc
@@ -0,0 +1,44 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/output/overlay_strategy_all_or_nothing.h"
+
+#include "cc/output/overlay_candidate_validator.h"
+#include "cc/quads/draw_quad.h"
+
+namespace cc {
+
+OverlayStrategyAllOrNothing::OverlayStrategyAllOrNothing(
+ OverlayCandidateValidator* capability_checker)
+ : capability_checker_(capability_checker) {}
+
+OverlayStrategyAllOrNothing::~OverlayStrategyAllOrNothing() {}
+
+bool OverlayStrategyAllOrNothing::Attempt(RenderPassList* render_passes,
+ OverlayCandidateList* candidates,
+ float device_scale_factor) {
+ QuadList& quad_list = render_passes->back()->quad_list;
+ OverlayCandidateList new_candidates;
+ int next_z_order = -1;
+
+ for (const DrawQuad* quad : quad_list) {
+ OverlayCandidate candidate;
+ if (!OverlayCandidate::FromDrawQuad(quad, &candidate))
+ return false;
+ candidate.plane_z_order = next_z_order--;
+ new_candidates.push_back(candidate);
+ }
+
+ capability_checker_->CheckOverlaySupport(&new_candidates);
+ for (const OverlayCandidate& candidate : new_candidates) {
+ if (!candidate.overlay_handled)
+ return false;
+ }
+
+ quad_list.clear();
+ candidates->swap(new_candidates);
+ return true;
+}
+
+} // namespace cc
diff --git a/chromium/cc/output/overlay_strategy_all_or_nothing.h b/chromium/cc/output/overlay_strategy_all_or_nothing.h
new file mode 100644
index 00000000000..7986d0e2682
--- /dev/null
+++ b/chromium/cc/output/overlay_strategy_all_or_nothing.h
@@ -0,0 +1,35 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_OUTPUT_OVERLAY_STRATEGY_ALL_OR_NOTHING_H_
+#define CC_OUTPUT_OVERLAY_STRATEGY_ALL_OR_NOTHING_H_
+
+#include "cc/output/overlay_processor.h"
+
+namespace cc {
+
+class OverlayCandidateValidator;
+
+// This strategy attempts to promote all quads into overlays.
+// If any quad can't be promoted, it returns false and no quads are promoted.
+class CC_EXPORT OverlayStrategyAllOrNothing
+ : public OverlayProcessor::Strategy {
+ public:
+ explicit OverlayStrategyAllOrNothing(
+ OverlayCandidateValidator* capability_checker);
+ ~OverlayStrategyAllOrNothing() override;
+
+ bool Attempt(RenderPassList* render_passes,
+ OverlayCandidateList* candidate_list,
+ float device_scale_factor) override;
+
+ private:
+ OverlayCandidateValidator* capability_checker_; // Weak.
+
+ DISALLOW_COPY_AND_ASSIGN(OverlayStrategyAllOrNothing);
+};
+
+} // namespace cc
+
+#endif // CC_OUTPUT_OVERLAY_STRATEGY_ALL_OR_NOTHING_H_
diff --git a/chromium/cc/output/overlay_strategy_common.cc b/chromium/cc/output/overlay_strategy_common.cc
index 33b45942398..d142ba54155 100644
--- a/chromium/cc/output/overlay_strategy_common.cc
+++ b/chromium/cc/output/overlay_strategy_common.cc
@@ -4,57 +4,54 @@
#include "cc/output/overlay_strategy_common.h"
-#include <limits>
-
#include "cc/quads/solid_color_draw_quad.h"
-#include "cc/quads/stream_video_draw_quad.h"
-#include "cc/quads/texture_draw_quad.h"
-#include "cc/resources/resource_provider.h"
-#include "ui/gfx/geometry/point3_f.h"
-#include "ui/gfx/geometry/rect_conversions.h"
-#include "ui/gfx/transform.h"
namespace cc {
OverlayStrategyCommon::OverlayStrategyCommon(
- OverlayCandidateValidator* capability_checker)
- : capability_checker_(capability_checker) {
-}
+ OverlayCandidateValidator* capability_checker,
+ OverlayStrategyCommonDelegate* delegate)
+ : capability_checker_(capability_checker), delegate_(delegate) {}
OverlayStrategyCommon::~OverlayStrategyCommon() {
}
bool OverlayStrategyCommon::Attempt(RenderPassList* render_passes_in_draw_order,
- OverlayCandidateList* candidate_list) {
+ OverlayCandidateList* candidate_list,
+ float device_scale_factor) {
if (!capability_checker_)
return false;
RenderPass* root_render_pass = render_passes_in_draw_order->back();
DCHECK(root_render_pass);
+ bool created_overlay = false;
QuadList& quad_list = root_render_pass->quad_list;
- for (auto it = quad_list.begin(); it != quad_list.end(); ++it) {
+ for (auto it = quad_list.begin(); it != quad_list.end();) {
OverlayCandidate candidate;
- const DrawQuad* draw_quad = *it;
- if (IsOverlayQuad(draw_quad) &&
- GetCandidateQuadInfo(*draw_quad, &candidate) &&
- TryOverlay(capability_checker_, render_passes_in_draw_order,
- candidate_list, candidate, it))
- return true;
+ if (!OverlayCandidate::FromDrawQuad(*it, &candidate)) {
+ ++it;
+ continue;
+ }
+
+ OverlayResult result = delegate_->TryOverlay(
+ capability_checker_, render_passes_in_draw_order, candidate_list,
+ candidate, &it, device_scale_factor);
+ switch (result) {
+ case DID_NOT_CREATE_OVERLAY:
+ ++it;
+ break;
+ case CREATED_OVERLAY_STOP_LOOKING:
+ return true;
+ case CREATED_OVERLAY_KEEP_LOOKING:
+ created_overlay = true;
+ break;
+ }
}
- return false;
-}
-bool OverlayStrategyCommon::IsOverlayQuad(const DrawQuad* draw_quad) {
- switch (draw_quad->material) {
- case DrawQuad::TEXTURE_CONTENT:
- return TextureDrawQuad::MaterialCast(draw_quad)->allow_overlay();
- case DrawQuad::STREAM_VIDEO_CONTENT:
- return StreamVideoDrawQuad::MaterialCast(draw_quad)->allow_overlay();
- default:
- return false;
- }
+ return created_overlay;
}
+// static
bool OverlayStrategyCommon::IsInvisibleQuad(const DrawQuad* draw_quad) {
if (draw_quad->material == DrawQuad::SOLID_COLOR) {
const SolidColorDrawQuad* solid_quad =
@@ -68,87 +65,4 @@ bool OverlayStrategyCommon::IsInvisibleQuad(const DrawQuad* draw_quad) {
return false;
}
-bool OverlayStrategyCommon::GetTextureQuadInfo(const TextureDrawQuad& quad,
- OverlayCandidate* quad_info) {
- gfx::OverlayTransform overlay_transform =
- OverlayCandidate::GetOverlayTransform(
- quad.shared_quad_state->quad_to_target_transform, quad.y_flipped);
- if (quad.background_color != SK_ColorTRANSPARENT ||
- quad.premultiplied_alpha ||
- overlay_transform == gfx::OVERLAY_TRANSFORM_INVALID)
- return false;
- quad_info->resource_id = quad.resource_id();
- quad_info->resource_size_in_pixels = quad.resource_size_in_pixels();
- quad_info->transform = overlay_transform;
- quad_info->uv_rect = BoundingRect(quad.uv_top_left, quad.uv_bottom_right);
- return true;
-}
-
-bool OverlayStrategyCommon::GetVideoQuadInfo(const StreamVideoDrawQuad& quad,
- OverlayCandidate* quad_info) {
- gfx::OverlayTransform overlay_transform =
- OverlayCandidate::GetOverlayTransform(
- quad.shared_quad_state->quad_to_target_transform, false);
- if (overlay_transform == gfx::OVERLAY_TRANSFORM_INVALID)
- return false;
- if (!quad.matrix.IsScaleOrTranslation()) {
- // We cannot handle anything other than scaling & translation for texture
- // coordinates yet.
- return false;
- }
- quad_info->resource_id = quad.resource_id();
- quad_info->resource_size_in_pixels = quad.resource_size_in_pixels();
- quad_info->transform = overlay_transform;
-
- gfx::Point3F uv0 = gfx::Point3F(0, 0, 0);
- gfx::Point3F uv1 = gfx::Point3F(1, 1, 0);
- quad.matrix.TransformPoint(&uv0);
- quad.matrix.TransformPoint(&uv1);
- gfx::Vector3dF delta = uv1 - uv0;
- if (delta.x() < 0) {
- quad_info->transform = OverlayCandidate::ModifyTransform(
- quad_info->transform, gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL);
- float x0 = uv0.x();
- uv0.set_x(uv1.x());
- uv1.set_x(x0);
- delta.set_x(-delta.x());
- }
-
- if (delta.y() < 0) {
- // In this situation, uv0y < uv1y. Since we overlay inverted, a request
- // to invert the source texture means we can just output the texture
- // normally and it will be correct.
- quad_info->uv_rect = gfx::RectF(uv0.x(), uv1.y(), delta.x(), -delta.y());
- } else {
- quad_info->transform = OverlayCandidate::ModifyTransform(
- quad_info->transform, gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL);
- quad_info->uv_rect = gfx::RectF(uv0.x(), uv0.y(), delta.x(), delta.y());
- }
- return true;
-}
-
-bool OverlayStrategyCommon::GetCandidateQuadInfo(const DrawQuad& draw_quad,
- OverlayCandidate* quad_info) {
- // All quad checks.
- if (draw_quad.needs_blending || draw_quad.shared_quad_state->opacity != 1.f ||
- draw_quad.shared_quad_state->blend_mode != SkXfermode::kSrcOver_Mode)
- return false;
-
- if (draw_quad.material == DrawQuad::TEXTURE_CONTENT) {
- const TextureDrawQuad& quad = *TextureDrawQuad::MaterialCast(&draw_quad);
- if (!GetTextureQuadInfo(quad, quad_info))
- return false;
- } else if (draw_quad.material == DrawQuad::STREAM_VIDEO_CONTENT) {
- const StreamVideoDrawQuad& quad =
- *StreamVideoDrawQuad::MaterialCast(&draw_quad);
- if (!GetVideoQuadInfo(quad, quad_info))
- return false;
- }
-
- quad_info->format = RGBA_8888;
- quad_info->display_rect = OverlayCandidate::GetOverlayRect(
- draw_quad.shared_quad_state->quad_to_target_transform, draw_quad.rect);
- return true;
-}
-
} // namespace cc
diff --git a/chromium/cc/output/overlay_strategy_common.h b/chromium/cc/output/overlay_strategy_common.h
index 2b81b90ee40..59fc1f4e279 100644
--- a/chromium/cc/output/overlay_strategy_common.h
+++ b/chromium/cc/output/overlay_strategy_common.h
@@ -10,44 +10,52 @@
#include "cc/output/overlay_processor.h"
namespace cc {
+class IOSurfaceDrawQuad;
+class OverlayCandidate;
class OverlayCandidateValidator;
class StreamVideoDrawQuad;
class TextureDrawQuad;
-class OverlayCandidate;
+
+enum OverlayResult {
+ DID_NOT_CREATE_OVERLAY,
+ CREATED_OVERLAY_STOP_LOOKING,
+ CREATED_OVERLAY_KEEP_LOOKING,
+};
+
+class CC_EXPORT OverlayStrategyCommonDelegate {
+ public:
+ virtual ~OverlayStrategyCommonDelegate() {}
+
+ // Check if |candidate| can be promoted into an overlay. If so, add it to
+ // |candidate_list| and update the quads in |render_passes_in_draw_order|
+ // as necessary. When returning CREATED_OVERLAY_KEEP_LOOKING, |iter| is
+ // updated to point to the next quad to evaluate.
+ virtual OverlayResult TryOverlay(
+ OverlayCandidateValidator* capability_checker,
+ RenderPassList* render_passes_in_draw_order,
+ OverlayCandidateList* candidate_list,
+ const OverlayCandidate& candidate,
+ QuadList::Iterator* iter,
+ float device_scale_factor) = 0;
+};
class CC_EXPORT OverlayStrategyCommon : public OverlayProcessor::Strategy {
public:
- explicit OverlayStrategyCommon(OverlayCandidateValidator* capability_checker);
+ explicit OverlayStrategyCommon(OverlayCandidateValidator* capability_checker,
+ OverlayStrategyCommonDelegate* delegate);
~OverlayStrategyCommon() override;
bool Attempt(RenderPassList* render_passes_in_draw_order,
- OverlayCandidateList* candidate_list) override;
-
- protected:
- bool GetCandidateQuadInfo(const DrawQuad& draw_quad,
- OverlayCandidate* quad_info);
+ OverlayCandidateList* candidate_list,
+ float device_scale_factor) override;
// Returns true if |draw_quad| will not block quads underneath from becoming
// an overlay.
- bool IsInvisibleQuad(const DrawQuad* draw_quad);
-
- // Returns true if |draw_quad| is of a known quad type and contains an
- // overlayable resource.
- bool IsOverlayQuad(const DrawQuad* draw_quad);
-
- bool GetTextureQuadInfo(const TextureDrawQuad& quad,
- OverlayCandidate* quad_info);
- bool GetVideoQuadInfo(const StreamVideoDrawQuad& quad,
- OverlayCandidate* quad_info);
-
- virtual bool TryOverlay(OverlayCandidateValidator* capability_checker,
- RenderPassList* render_passes_in_draw_order,
- OverlayCandidateList* candidate_list,
- const OverlayCandidate& candidate,
- QuadList::Iterator iter) = 0;
+ static bool IsInvisibleQuad(const DrawQuad* draw_quad);
private:
OverlayCandidateValidator* capability_checker_;
+ scoped_ptr<OverlayStrategyCommonDelegate> delegate_;
DISALLOW_COPY_AND_ASSIGN(OverlayStrategyCommon);
};
diff --git a/chromium/cc/output/overlay_strategy_sandwich.cc b/chromium/cc/output/overlay_strategy_sandwich.cc
new file mode 100644
index 00000000000..63032a76e55
--- /dev/null
+++ b/chromium/cc/output/overlay_strategy_sandwich.cc
@@ -0,0 +1,163 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/output/overlay_strategy_sandwich.h"
+
+#include "cc/base/math_util.h"
+#include "cc/base/region.h"
+#include "cc/output/overlay_candidate_validator.h"
+#include "cc/quads/draw_quad.h"
+#include "cc/quads/solid_color_draw_quad.h"
+
+namespace cc {
+
+namespace {
+
+void ClipDisplayAndUVRects(gfx::Rect* display_rect,
+ gfx::RectF* uv_rect,
+ const gfx::Rect& clip_rect) {
+ gfx::Rect display_cropped_rect =
+ gfx::IntersectRects(*display_rect, clip_rect);
+
+ gfx::RectF uv_cropped_rect = gfx::RectF(display_cropped_rect);
+ uv_cropped_rect -= gfx::Vector2dF(display_rect->x(), display_rect->y());
+ uv_cropped_rect.Scale(uv_rect->width() / display_rect->width(),
+ uv_rect->height() / display_rect->height());
+ uv_cropped_rect += gfx::Vector2dF(uv_rect->x(), uv_rect->y());
+
+ *display_rect = display_cropped_rect;
+ *uv_rect = uv_cropped_rect;
+}
+
+} // namespace
+
+OverlayStrategySandwich::~OverlayStrategySandwich() {}
+
+OverlayResult OverlayStrategySandwich::TryOverlay(
+ OverlayCandidateValidator* capability_checker,
+ RenderPassList* render_passes_in_draw_order,
+ OverlayCandidateList* candidate_list,
+ const OverlayCandidate& candidate,
+ QuadList::Iterator* candidate_iter_in_quad_list,
+ float device_scale_factor) {
+ RenderPass* root_render_pass = render_passes_in_draw_order->back();
+ QuadList& quad_list = root_render_pass->quad_list;
+ gfx::Rect pixel_bounds = root_render_pass->output_rect;
+
+ const DrawQuad* candidate_quad = **candidate_iter_in_quad_list;
+ const gfx::Transform& candidate_transform =
+ candidate_quad->shared_quad_state->quad_to_target_transform;
+ gfx::Transform candidate_inverse_transform;
+ if (!candidate_transform.GetInverse(&candidate_inverse_transform))
+ return DID_NOT_CREATE_OVERLAY;
+
+ // Compute the candidate's rect in display space (pixels on the screen).
+ gfx::Rect candidate_pixel_rect = candidate.quad_rect_in_target_space;
+ gfx::RectF candidate_uv_rect = candidate.uv_rect;
+ if (candidate.is_clipped &&
+ !candidate.clip_rect.Contains(candidate_pixel_rect)) {
+ ClipDisplayAndUVRects(&candidate_pixel_rect, &candidate_uv_rect,
+ candidate.clip_rect);
+ }
+
+ // Don't allow overlapping overlays for now.
+ for (const OverlayCandidate& other_candidate : *candidate_list) {
+ if (other_candidate.display_rect.Intersects(candidate.display_rect) &&
+ other_candidate.plane_z_order == 1) {
+ return DID_NOT_CREATE_OVERLAY;
+ }
+ }
+
+ // Iterate through the quads in front of |candidate|, and compute the region
+ // of |candidate| that is covered.
+ Region pixel_covered_region;
+ for (auto overlap_iter = quad_list.cbegin();
+ overlap_iter != *candidate_iter_in_quad_list; ++overlap_iter) {
+ if (OverlayStrategyCommon::IsInvisibleQuad(*overlap_iter))
+ continue;
+ // Compute the quad's bounds in display space.
+ gfx::Rect pixel_covered_rect = MathUtil::MapEnclosingClippedRect(
+ overlap_iter->shared_quad_state->quad_to_target_transform,
+ overlap_iter->rect);
+
+ // Include the intersection of that quad with the candidate's quad in the
+ // covered region.
+ pixel_covered_rect.Intersect(candidate_pixel_rect);
+ pixel_covered_region.Union(pixel_covered_rect);
+ }
+
+ // Add the candidate's overlay.
+ DCHECK(candidate.resource_id);
+ OverlayCandidateList new_candidate_list = *candidate_list;
+ new_candidate_list.push_back(candidate);
+ OverlayCandidate& new_candidate = new_candidate_list.back();
+ new_candidate.plane_z_order = 1;
+ new_candidate.display_rect = gfx::RectF(candidate_pixel_rect);
+ new_candidate.quad_rect_in_target_space = candidate_pixel_rect;
+ new_candidate.uv_rect = candidate_uv_rect;
+
+ // Add an overlay of the primary surface for any part of the candidate's
+ // quad that was covered.
+ std::vector<gfx::Rect> pixel_covered_rects;
+ for (Region::Iterator it(pixel_covered_region); it.has_rect(); it.next())
+ pixel_covered_rects.push_back(it.rect());
+ for (const gfx::Rect& pixel_covered_rect : pixel_covered_rects) {
+ OverlayCandidate main_image_on_top;
+ main_image_on_top.display_rect = gfx::RectF(pixel_covered_rect);
+ main_image_on_top.uv_rect = gfx::RectF(pixel_covered_rect);
+ main_image_on_top.uv_rect.Scale(1.f / pixel_bounds.width(),
+ 1.f / pixel_bounds.height());
+ main_image_on_top.plane_z_order = 2;
+ main_image_on_top.transform = gfx::OVERLAY_TRANSFORM_NONE;
+ main_image_on_top.use_output_surface_for_resource = true;
+ new_candidate_list.push_back(main_image_on_top);
+ }
+
+ // Check for support.
+ capability_checker->CheckOverlaySupport(&new_candidate_list);
+ for (const OverlayCandidate& candidate : new_candidate_list) {
+ if (!candidate.overlay_handled)
+ return DID_NOT_CREATE_OVERLAY;
+ }
+
+ // Remove the quad for the overlay quad. Replace it with a transparent quad
+ // if we're putting a new overlay on top.
+ if (pixel_covered_rects.empty()) {
+ *candidate_iter_in_quad_list =
+ quad_list.EraseAndInvalidateAllPointers(*candidate_iter_in_quad_list);
+ } else {
+ // Cache the information from the candidate quad that we'll need to
+ // construct the solid color quads.
+ const SharedQuadState* candidate_shared_quad_state =
+ candidate_quad->shared_quad_state;
+ const gfx::Rect candidate_rect = candidate_quad->rect;
+
+ // Reserve space in the quad list for the transparent quads.
+ quad_list.ReplaceExistingElement<SolidColorDrawQuad>(
+ *candidate_iter_in_quad_list);
+ *candidate_iter_in_quad_list =
+ quad_list.InsertBeforeAndInvalidateAllPointers<SolidColorDrawQuad>(
+ *candidate_iter_in_quad_list, pixel_covered_rects.size() - 1);
+
+ // Cover the region with transparent quads.
+ for (const gfx::Rect& pixel_covered_rect : pixel_covered_rects) {
+ gfx::Rect quad_space_covered_rect = MathUtil::MapEnclosingClippedRect(
+ candidate_inverse_transform, pixel_covered_rect);
+ quad_space_covered_rect.Intersect(candidate_rect);
+
+ SolidColorDrawQuad* transparent_quad =
+ static_cast<SolidColorDrawQuad*>(**candidate_iter_in_quad_list);
+ transparent_quad->SetAll(candidate_shared_quad_state,
+ quad_space_covered_rect, quad_space_covered_rect,
+ quad_space_covered_rect, false,
+ SK_ColorTRANSPARENT, true);
+ ++(*candidate_iter_in_quad_list);
+ }
+ }
+
+ candidate_list->swap(new_candidate_list);
+ return CREATED_OVERLAY_KEEP_LOOKING;
+}
+
+} // namespace cc
diff --git a/chromium/cc/output/overlay_strategy_sandwich.h b/chromium/cc/output/overlay_strategy_sandwich.h
new file mode 100644
index 00000000000..a1bd9d1bb24
--- /dev/null
+++ b/chromium/cc/output/overlay_strategy_sandwich.h
@@ -0,0 +1,34 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_OUTPUT_OVERLAY_STRATEGY_SANDWICH_H_
+#define CC_OUTPUT_OVERLAY_STRATEGY_SANDWICH_H_
+
+#include "cc/output/overlay_strategy_common.h"
+
+namespace cc {
+
+// The sandwich strategy looks for a video quad without regard to quads above
+// it. The video is "overlaid" on top of the scene, and then the non-empty
+// parts of the scene are "overlaid" on top of the video. This is only valid
+// for overlay contents that are fully opaque.
+class CC_EXPORT OverlayStrategySandwich : public OverlayStrategyCommonDelegate {
+ public:
+ OverlayStrategySandwich() {}
+ ~OverlayStrategySandwich() override;
+
+ OverlayResult TryOverlay(OverlayCandidateValidator* capability_checker,
+ RenderPassList* render_passes_in_draw_order,
+ OverlayCandidateList* candidate_list,
+ const OverlayCandidate& candidate,
+ QuadList::Iterator* candidate_iterator,
+ float device_scale_factor) override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(OverlayStrategySandwich);
+};
+
+} // namespace cc
+
+#endif // CC_OUTPUT_OVERLAY_STRATEGY_SANDWICH_H_
diff --git a/chromium/cc/output/overlay_strategy_single_on_top.cc b/chromium/cc/output/overlay_strategy_single_on_top.cc
index fd47e0f3b72..6b63045c015 100644
--- a/chromium/cc/output/overlay_strategy_single_on_top.cc
+++ b/chromium/cc/output/overlay_strategy_single_on_top.cc
@@ -6,59 +6,50 @@
#include <limits>
+#include "cc/base/math_util.h"
#include "cc/output/overlay_candidate_validator.h"
#include "cc/quads/draw_quad.h"
namespace cc {
-OverlayStrategySingleOnTop::OverlayStrategySingleOnTop(
- OverlayCandidateValidator* capability_checker)
- : OverlayStrategyCommon(capability_checker) {
-}
+OverlayStrategySingleOnTop::~OverlayStrategySingleOnTop() {}
-bool OverlayStrategySingleOnTop::TryOverlay(
+OverlayResult OverlayStrategySingleOnTop::TryOverlay(
OverlayCandidateValidator* capability_checker,
-
RenderPassList* render_passes_in_draw_order,
OverlayCandidateList* candidate_list,
const OverlayCandidate& candidate,
- QuadList::Iterator candidate_iterator) {
+ QuadList::Iterator* candidate_iterator,
+ float device_scale_factor) {
RenderPass* root_render_pass = render_passes_in_draw_order->back();
QuadList& quad_list = root_render_pass->quad_list;
- const DrawQuad* draw_quad = *candidate_iterator;
- gfx::RectF rect = draw_quad->rect;
- draw_quad->shared_quad_state->quad_to_target_transform.TransformRect(&rect);
-
// Check that no prior quads overlap it.
for (auto overlap_iter = quad_list.cbegin();
- overlap_iter != candidate_iterator; ++overlap_iter) {
- gfx::RectF overlap_rect = overlap_iter->rect;
- overlap_iter->shared_quad_state->quad_to_target_transform.TransformRect(
- &overlap_rect);
- if (rect.Intersects(overlap_rect) && !IsInvisibleQuad(*overlap_iter))
- return false;
+ overlap_iter != *candidate_iterator; ++overlap_iter) {
+ gfx::RectF overlap_rect = MathUtil::MapClippedRect(
+ overlap_iter->shared_quad_state->quad_to_target_transform,
+ gfx::RectF(overlap_iter->rect));
+ if (candidate.display_rect.Intersects(overlap_rect) &&
+ !OverlayStrategyCommon::IsInvisibleQuad(*overlap_iter))
+ return DID_NOT_CREATE_OVERLAY;
}
- // Add our primary surface.
- OverlayCandidateList candidates;
- OverlayCandidate main_image;
- main_image.display_rect = root_render_pass->output_rect;
- candidates.push_back(main_image);
-
// Add the overlay.
- candidates.push_back(candidate);
- candidates.back().plane_z_order = 1;
+ OverlayCandidateList new_candidate_list = *candidate_list;
+ new_candidate_list.push_back(candidate);
+ new_candidate_list.back().plane_z_order = 1;
// Check for support.
- capability_checker->CheckOverlaySupport(&candidates);
+ capability_checker->CheckOverlaySupport(&new_candidate_list);
// If the candidate can be handled by an overlay, create a pass for it.
- if (candidates[1].overlay_handled) {
- quad_list.EraseAndInvalidateAllPointers(candidate_iterator);
- candidate_list->swap(candidates);
- return true;
+ if (new_candidate_list.back().overlay_handled) {
+ quad_list.EraseAndInvalidateAllPointers(*candidate_iterator);
+ candidate_list->swap(new_candidate_list);
+ return CREATED_OVERLAY_STOP_LOOKING;
}
- return false;
+
+ return DID_NOT_CREATE_OVERLAY;
}
} // namespace cc
diff --git a/chromium/cc/output/overlay_strategy_single_on_top.h b/chromium/cc/output/overlay_strategy_single_on_top.h
index 2b9cf4d04fd..17c763d8896 100644
--- a/chromium/cc/output/overlay_strategy_single_on_top.h
+++ b/chromium/cc/output/overlay_strategy_single_on_top.h
@@ -17,15 +17,18 @@ namespace cc {
class StreamVideoDrawQuad;
class TextureDrawQuad;
-class CC_EXPORT OverlayStrategySingleOnTop : public OverlayStrategyCommon {
+class CC_EXPORT OverlayStrategySingleOnTop
+ : public OverlayStrategyCommonDelegate {
public:
- explicit OverlayStrategySingleOnTop(
- OverlayCandidateValidator* capability_checker);
- bool TryOverlay(OverlayCandidateValidator* capability_checker,
- RenderPassList* render_passes_in_draw_order,
- OverlayCandidateList* candidate_list,
- const OverlayCandidate& candidate,
- QuadList::Iterator candidate_iterator) override;
+ OverlayStrategySingleOnTop() {}
+ ~OverlayStrategySingleOnTop() override;
+
+ OverlayResult TryOverlay(OverlayCandidateValidator* capability_checker,
+ RenderPassList* render_passes_in_draw_order,
+ OverlayCandidateList* candidate_list,
+ const OverlayCandidate& candidate,
+ QuadList::Iterator* candidate_iterator,
+ float device_scale_factor) override;
private:
DISALLOW_COPY_AND_ASSIGN(OverlayStrategySingleOnTop);
diff --git a/chromium/cc/output/overlay_strategy_underlay.cc b/chromium/cc/output/overlay_strategy_underlay.cc
index dd2b90f4814..88213695762 100644
--- a/chromium/cc/output/overlay_strategy_underlay.cc
+++ b/chromium/cc/output/overlay_strategy_underlay.cc
@@ -10,49 +10,42 @@
namespace cc {
-OverlayStrategyUnderlay::OverlayStrategyUnderlay(
- OverlayCandidateValidator* capability_checker)
- : OverlayStrategyCommon(capability_checker) {
-}
+OverlayStrategyUnderlay::~OverlayStrategyUnderlay() {}
-bool OverlayStrategyUnderlay::TryOverlay(
+OverlayResult OverlayStrategyUnderlay::TryOverlay(
OverlayCandidateValidator* capability_checker,
-
RenderPassList* render_passes_in_draw_order,
OverlayCandidateList* candidate_list,
const OverlayCandidate& candidate,
- QuadList::Iterator candidate_iterator) {
+ QuadList::Iterator* candidate_iterator,
+ float device_scale_factor) {
RenderPass* root_render_pass = render_passes_in_draw_order->back();
QuadList& quad_list = root_render_pass->quad_list;
- // Add our primary surface.
- OverlayCandidateList candidates;
- OverlayCandidate main_image;
- main_image.display_rect = root_render_pass->output_rect;
- candidates.push_back(main_image);
-
// Add the overlay.
- candidates.push_back(candidate);
- candidates.back().plane_z_order = -1;
+ OverlayCandidateList new_candidate_list = *candidate_list;
+ new_candidate_list.push_back(candidate);
+ new_candidate_list.back().plane_z_order = -1;
// Check for support.
- capability_checker->CheckOverlaySupport(&candidates);
+ capability_checker->CheckOverlaySupport(&new_candidate_list);
// If the candidate can be handled by an overlay, create a pass for it. We
// need to switch out the video quad with a black transparent one.
- if (candidates[1].overlay_handled) {
+ if (new_candidate_list.back().overlay_handled) {
const SharedQuadState* shared_quad_state =
- candidate_iterator->shared_quad_state;
- gfx::Rect rect = candidate_iterator->visible_rect;
+ (*candidate_iterator)->shared_quad_state;
+ gfx::Rect rect = (*candidate_iterator)->visible_rect;
SolidColorDrawQuad* replacement =
quad_list.ReplaceExistingElement<SolidColorDrawQuad>(
- candidate_iterator);
+ *candidate_iterator);
replacement->SetAll(shared_quad_state, rect, rect, rect, false,
SK_ColorTRANSPARENT, true);
- candidate_list->swap(candidates);
- return true;
+ candidate_list->swap(new_candidate_list);
+ return CREATED_OVERLAY_STOP_LOOKING;
}
- return false;
+
+ return DID_NOT_CREATE_OVERLAY;
}
} // namespace cc
diff --git a/chromium/cc/output/overlay_strategy_underlay.h b/chromium/cc/output/overlay_strategy_underlay.h
index fd55bef4319..20c210697f5 100644
--- a/chromium/cc/output/overlay_strategy_underlay.h
+++ b/chromium/cc/output/overlay_strategy_underlay.h
@@ -16,15 +16,17 @@ class TextureDrawQuad;
// for the video quad. The overlay content can then be blended in by the
// hardware under the the scene. This is only valid for overlay contents that
// are fully opaque.
-class CC_EXPORT OverlayStrategyUnderlay : public OverlayStrategyCommon {
+class CC_EXPORT OverlayStrategyUnderlay : public OverlayStrategyCommonDelegate {
public:
- explicit OverlayStrategyUnderlay(
- OverlayCandidateValidator* capability_checker);
- bool TryOverlay(OverlayCandidateValidator* capability_checker,
- RenderPassList* render_passes_in_draw_order,
- OverlayCandidateList* candidate_list,
- const OverlayCandidate& candidate,
- QuadList::Iterator candidate_iterator) override;
+ OverlayStrategyUnderlay() {}
+ ~OverlayStrategyUnderlay() override;
+
+ OverlayResult TryOverlay(OverlayCandidateValidator* capability_checker,
+ RenderPassList* render_passes_in_draw_order,
+ OverlayCandidateList* candidate_list,
+ const OverlayCandidate& candidate,
+ QuadList::Iterator* candidate_iterator,
+ float device_scale_factor) override;
private:
DISALLOW_COPY_AND_ASSIGN(OverlayStrategyUnderlay);
diff --git a/chromium/cc/output/overlay_unittest.cc b/chromium/cc/output/overlay_unittest.cc
index 6ac9b1c64c8..155707bc6a1 100644
--- a/chromium/cc/output/overlay_unittest.cc
+++ b/chromium/cc/output/overlay_unittest.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "cc/base/region.h"
#include "cc/base/scoped_ptr_vector.h"
#include "cc/output/compositor_frame_metadata.h"
#include "cc/output/gl_renderer.h"
@@ -9,10 +10,12 @@
#include "cc/output/output_surface_client.h"
#include "cc/output/overlay_candidate_validator.h"
#include "cc/output/overlay_processor.h"
+#include "cc/output/overlay_strategy_all_or_nothing.h"
+#include "cc/output/overlay_strategy_sandwich.h"
#include "cc/output/overlay_strategy_single_on_top.h"
#include "cc/output/overlay_strategy_underlay.h"
-#include "cc/quads/checkerboard_draw_quad.h"
#include "cc/quads/render_pass.h"
+#include "cc/quads/solid_color_draw_quad.h"
#include "cc/quads/stream_video_draw_quad.h"
#include "cc/quads/texture_draw_quad.h"
#include "cc/resources/resource_provider.h"
@@ -24,6 +27,7 @@
#include "cc/test/test_shared_bitmap_manager.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/geometry/rect_conversions.h"
using testing::_;
using testing::Mock;
@@ -31,9 +35,11 @@ using testing::Mock;
namespace cc {
namespace {
+const gfx::Size kDisplaySize(256, 256);
const gfx::Rect kOverlayRect(0, 0, 128, 128);
const gfx::Rect kOverlayTopLeftRect(0, 0, 64, 64);
const gfx::Rect kOverlayBottomRightRect(64, 64, 64, 64);
+const gfx::Rect kOverlayClipRect(0, 0, 128, 128);
const gfx::PointF kUVTopLeft(0.1f, 0.2f);
const gfx::PointF kUVBottomRight(1.0f, 1.0f);
const gfx::Transform kNormalTransform =
@@ -54,42 +60,76 @@ void MailboxReleased(unsigned sync_point,
class SingleOverlayValidator : public OverlayCandidateValidator {
public:
- void CheckOverlaySupport(OverlayCandidateList* surfaces) override;
+ void GetStrategies(OverlayProcessor::StrategyList* strategies) override {
+ strategies->push_back(make_scoped_ptr(
+ new OverlayStrategyCommon(this, new OverlayStrategySingleOnTop)));
+ strategies->push_back(make_scoped_ptr(
+ new OverlayStrategyCommon(this, new OverlayStrategyUnderlay)));
+ }
+ void CheckOverlaySupport(OverlayCandidateList* surfaces) override {
+ // We may have 1 or 2 surfaces depending on whether this ran through the
+ // full renderer and picked up the output surface, or not.
+ ASSERT_LE(1U, surfaces->size());
+ ASSERT_GE(2U, surfaces->size());
+
+ OverlayCandidate& candidate = surfaces->back();
+ EXPECT_TRUE(!candidate.use_output_surface_for_resource);
+ if (candidate.display_rect.width() == 64) {
+ EXPECT_EQ(gfx::RectF(kOverlayBottomRightRect), candidate.display_rect);
+ } else {
+ EXPECT_NEAR(kOverlayRect.x(), candidate.display_rect.x(), 0.01f);
+ EXPECT_NEAR(kOverlayRect.y(), candidate.display_rect.y(), 0.01f);
+ EXPECT_NEAR(kOverlayRect.width(), candidate.display_rect.width(), 0.01f);
+ EXPECT_NEAR(kOverlayRect.height(), candidate.display_rect.height(),
+ 0.01f);
+ }
+ EXPECT_FLOAT_RECT_EQ(BoundingRect(kUVTopLeft, kUVBottomRight),
+ candidate.uv_rect);
+ if (!candidate.clip_rect.IsEmpty()) {
+ EXPECT_EQ(true, candidate.is_clipped);
+ EXPECT_EQ(kOverlayClipRect, candidate.clip_rect);
+ }
+ candidate.overlay_handled = true;
+ }
};
-void SingleOverlayValidator::CheckOverlaySupport(
- OverlayCandidateList* surfaces) {
- ASSERT_EQ(2U, surfaces->size());
-
- OverlayCandidate& candidate = surfaces->back();
- if (candidate.display_rect.width() == 64) {
- EXPECT_EQ(kOverlayBottomRightRect, candidate.display_rect);
- } else {
- EXPECT_NEAR(kOverlayRect.x(), candidate.display_rect.x(), 0.01f);
- EXPECT_NEAR(kOverlayRect.y(), candidate.display_rect.y(), 0.01f);
- EXPECT_NEAR(kOverlayRect.width(), candidate.display_rect.width(), 0.01f);
- EXPECT_NEAR(kOverlayRect.height(), candidate.display_rect.height(), 0.01f);
+class SingleOnTopOverlayValidator : public SingleOverlayValidator {
+ public:
+ void GetStrategies(OverlayProcessor::StrategyList* strategies) override {
+ strategies->push_back(make_scoped_ptr(
+ new OverlayStrategyCommon(this, new OverlayStrategySingleOnTop)));
}
- EXPECT_EQ(BoundingRect(kUVTopLeft, kUVBottomRight).ToString(),
- candidate.uv_rect.ToString());
- candidate.overlay_handled = true;
-}
+};
-template <typename OverlayStrategyType>
-class SingleOverlayProcessor : public OverlayProcessor {
+class UnderlayOverlayValidator : public SingleOverlayValidator {
public:
- explicit SingleOverlayProcessor(OutputSurface* surface)
- : OverlayProcessor(surface) {
- EXPECT_EQ(surface, surface_);
+ void GetStrategies(OverlayProcessor::StrategyList* strategies) override {
+ strategies->push_back(make_scoped_ptr(
+ new OverlayStrategyCommon(this, new OverlayStrategyUnderlay)));
}
+};
- // Virtual to allow testing different strategies.
- void Initialize() override {
- OverlayCandidateValidator* candidates =
- surface_->GetOverlayCandidateValidator();
- ASSERT_TRUE(candidates != NULL);
- strategies_.push_back(
- scoped_ptr<Strategy>(new OverlayStrategyType(candidates)));
+class SandwichOverlayValidator : public OverlayCandidateValidator {
+ public:
+ void GetStrategies(OverlayProcessor::StrategyList* strategies) override {
+ strategies->push_back(make_scoped_ptr(
+ new OverlayStrategyCommon(this, new OverlayStrategySandwich)));
+ }
+ void CheckOverlaySupport(OverlayCandidateList* surfaces) override {
+ for (OverlayCandidate& candidate : *surfaces)
+ candidate.overlay_handled = true;
+ }
+};
+
+class AllOrNothingOverlayValidator : public OverlayCandidateValidator {
+ public:
+ void GetStrategies(OverlayProcessor::StrategyList* strategies) override {
+ strategies->push_back(
+ make_scoped_ptr(new OverlayStrategyAllOrNothing(this)));
+ }
+ void CheckOverlaySupport(OverlayCandidateList* surfaces) override {
+ for (OverlayCandidate& candidate : *surfaces)
+ candidate.overlay_handled = true;
}
};
@@ -110,21 +150,38 @@ size_t DefaultOverlayProcessor::GetStrategyCount() {
class OverlayOutputSurface : public OutputSurface {
public:
explicit OverlayOutputSurface(scoped_refptr<ContextProvider> context_provider)
- : OutputSurface(context_provider) {}
+ : OutputSurface(context_provider) {
+ surface_size_ = kDisplaySize;
+ device_scale_factor_ = 1;
+ is_displayed_as_overlay_plane_ = true;
+ }
+
+ void SetScaleFactor(float scale_factor) {
+ device_scale_factor_ = scale_factor;
+ }
// OutputSurface implementation
void SwapBuffers(CompositorFrame* frame) override;
- void InitWithSingleOverlayValidator() {
- overlay_candidate_validator_.reset(new SingleOverlayValidator);
+ void SetOverlayCandidateValidator(OverlayCandidateValidator* validator) {
+ overlay_candidate_validator_.reset(validator);
}
OverlayCandidateValidator* GetOverlayCandidateValidator() const override {
return overlay_candidate_validator_.get();
}
+ bool IsDisplayedAsOverlayPlane() const override {
+ return is_displayed_as_overlay_plane_;
+ }
+ unsigned GetOverlayTextureId() const override { return 10000; }
+ void set_is_displayed_as_overlay_plane(bool value) {
+ is_displayed_as_overlay_plane_ = value;
+ }
+
private:
scoped_ptr<OverlayCandidateValidator> overlay_candidate_validator_;
+ bool is_displayed_as_overlay_plane_;
};
void OverlayOutputSurface::SwapBuffers(CompositorFrame* frame) {
@@ -238,20 +295,20 @@ StreamVideoDrawQuad* CreateFullscreenCandidateVideoQuad(
render_pass, kOverlayRect, transform);
}
-void CreateCheckeredQuadAt(ResourceProvider* resource_provider,
- const SharedQuadState* shared_quad_state,
- RenderPass* render_pass,
- const gfx::Rect& rect) {
- CheckerboardDrawQuad* checkerboard_quad =
- render_pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
- checkerboard_quad->SetNew(shared_quad_state, rect, rect, SkColor(), 1.f);
+void CreateOpaqueQuadAt(ResourceProvider* resource_provider,
+ const SharedQuadState* shared_quad_state,
+ RenderPass* render_pass,
+ const gfx::Rect& rect) {
+ SolidColorDrawQuad* color_quad =
+ render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
+ color_quad->SetNew(shared_quad_state, rect, rect, SK_ColorBLACK, false);
}
-void CreateFullscreenCheckeredQuad(ResourceProvider* resource_provider,
- const SharedQuadState* shared_quad_state,
- RenderPass* render_pass) {
- CreateCheckeredQuadAt(
- resource_provider, shared_quad_state, render_pass, kOverlayRect);
+void CreateFullscreenOpaqueQuad(ResourceProvider* resource_provider,
+ const SharedQuadState* shared_quad_state,
+ RenderPass* render_pass) {
+ CreateOpaqueQuadAt(resource_provider, shared_quad_state, render_pass,
+ kOverlayRect);
}
static void CompareRenderPassLists(const RenderPassList& expected_list,
@@ -284,12 +341,43 @@ static void CompareRenderPassLists(const RenderPassList& expected_list,
}
}
+template <typename OverlayCandidateValidatorType>
+class OverlayTest : public testing::Test {
+ protected:
+ void SetUp() override {
+ provider_ = TestContextProvider::Create();
+ output_surface_.reset(new OverlayOutputSurface(provider_));
+ EXPECT_TRUE(output_surface_->BindToClient(&client_));
+ output_surface_->SetOverlayCandidateValidator(
+ new OverlayCandidateValidatorType);
+
+ shared_bitmap_manager_.reset(new TestSharedBitmapManager());
+ resource_provider_ = FakeResourceProvider::Create(
+ output_surface_.get(), shared_bitmap_manager_.get());
+
+ overlay_processor_.reset(new OverlayProcessor(output_surface_.get()));
+ overlay_processor_->Initialize();
+ }
+
+ scoped_refptr<TestContextProvider> provider_;
+ scoped_ptr<OverlayOutputSurface> output_surface_;
+ FakeOutputSurfaceClient client_;
+ scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
+ scoped_ptr<ResourceProvider> resource_provider_;
+ scoped_ptr<OverlayProcessor> overlay_processor_;
+};
+
+typedef OverlayTest<SingleOnTopOverlayValidator> SingleOverlayOnTopTest;
+typedef OverlayTest<UnderlayOverlayValidator> UnderlayTest;
+typedef OverlayTest<SandwichOverlayValidator> SandwichTest;
+typedef OverlayTest<AllOrNothingOverlayValidator> AllOrNothingOverlayTest;
+
TEST(OverlayTest, NoOverlaysByDefault) {
scoped_refptr<TestContextProvider> provider = TestContextProvider::Create();
OverlayOutputSurface output_surface(provider);
EXPECT_EQ(NULL, output_surface.GetOverlayCandidateValidator());
- output_surface.InitWithSingleOverlayValidator();
+ output_surface.SetOverlayCandidateValidator(new SingleOverlayValidator);
EXPECT_TRUE(output_surface.GetOverlayCandidateValidator() != NULL);
}
@@ -298,8 +386,7 @@ TEST(OverlayTest, OverlaysProcessorHasStrategy) {
OverlayOutputSurface output_surface(provider);
FakeOutputSurfaceClient client;
EXPECT_TRUE(output_surface.BindToClient(&client));
- output_surface.InitWithSingleOverlayValidator();
- EXPECT_TRUE(output_surface.GetOverlayCandidateValidator() != NULL);
+ output_surface.SetOverlayCandidateValidator(new SingleOverlayValidator);
scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
new TestSharedBitmapManager());
@@ -312,35 +399,246 @@ TEST(OverlayTest, OverlaysProcessorHasStrategy) {
EXPECT_GE(2U, overlay_processor->GetStrategyCount());
}
-template <typename OverlayStrategyType>
-class OverlayTest : public testing::Test {
- protected:
- void SetUp() override {
- provider_ = TestContextProvider::Create();
- output_surface_.reset(new OverlayOutputSurface(provider_));
- EXPECT_TRUE(output_surface_->BindToClient(&client_));
- output_surface_->InitWithSingleOverlayValidator();
- EXPECT_TRUE(output_surface_->GetOverlayCandidateValidator() != NULL);
+TEST_F(SandwichTest, SuccessfulSingleOverlay) {
+ scoped_ptr<RenderPass> pass = CreateRenderPass();
+ TextureDrawQuad* original_quad = CreateFullscreenCandidateQuad(
+ resource_provider_.get(), pass->shared_quad_state_list.back(),
+ pass.get());
+ unsigned original_resource_id = original_quad->resource_id();
- shared_bitmap_manager_.reset(new TestSharedBitmapManager());
- resource_provider_ = FakeResourceProvider::Create(
- output_surface_.get(), shared_bitmap_manager_.get());
+ // Add something behind it.
+ CreateFullscreenOpaqueQuad(resource_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get());
+ CreateFullscreenOpaqueQuad(resource_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get());
- overlay_processor_.reset(
- new SingleOverlayProcessor<OverlayStrategyType>(output_surface_.get()));
- overlay_processor_->Initialize();
+ RenderPassList pass_list;
+ pass_list.push_back(pass.Pass());
+
+ // Check for potential candidates.
+ OverlayCandidateList candidate_list;
+ overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
+
+ ASSERT_EQ(1U, pass_list.size());
+ ASSERT_EQ(1U, candidate_list.size());
+
+ RenderPass* main_pass = pass_list.back();
+ // Check that the quad is gone.
+ EXPECT_EQ(2U, main_pass->quad_list.size());
+ const QuadList& quad_list = main_pass->quad_list;
+ for (QuadList::ConstBackToFrontIterator it = quad_list.BackToFrontBegin();
+ it != quad_list.BackToFrontEnd(); ++it) {
+ EXPECT_NE(DrawQuad::TEXTURE_CONTENT, it->material);
}
- scoped_refptr<TestContextProvider> provider_;
- scoped_ptr<OverlayOutputSurface> output_surface_;
- FakeOutputSurfaceClient client_;
- scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
- scoped_ptr<ResourceProvider> resource_provider_;
- scoped_ptr<SingleOverlayProcessor<OverlayStrategyType>> overlay_processor_;
-};
+ // Check that the right resource id got extracted.
+ EXPECT_EQ(original_resource_id, candidate_list.back().resource_id);
+}
-typedef OverlayTest<OverlayStrategySingleOnTop> SingleOverlayOnTopTest;
-typedef OverlayTest<OverlayStrategyUnderlay> UnderlayTest;
+TEST_F(SandwichTest, CroppedSingleOverlay) {
+ scoped_ptr<RenderPass> pass = CreateRenderPass();
+ pass->shared_quad_state_list.back()->is_clipped = true;
+ pass->shared_quad_state_list.back()->clip_rect = gfx::Rect(0, 32, 64, 64);
+
+ TextureDrawQuad* original_quad = CreateFullscreenCandidateQuad(
+ resource_provider_.get(), pass->shared_quad_state_list.back(),
+ pass.get());
+ original_quad->uv_top_left = gfx::PointF(0, 0);
+ original_quad->uv_bottom_right = gfx::PointF(1, 1);
+ unsigned candidate_id = original_quad->resource_id();
+
+ // Add something behind it.
+ CreateFullscreenOpaqueQuad(resource_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get());
+ CreateFullscreenOpaqueQuad(resource_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get());
+
+ RenderPassList pass_list;
+ pass_list.push_back(pass.Pass());
+
+ // Check for potential candidates.
+ OverlayCandidateList candidate_list;
+ overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
+
+ // Ensure that the display and uv rects have cropping applied to them.
+ ASSERT_EQ(1U, pass_list.size());
+ ASSERT_EQ(1U, candidate_list.size());
+ EXPECT_EQ(candidate_id, candidate_list[0].resource_id);
+ EXPECT_EQ(gfx::RectF(0.f, 32.f, 64.f, 64.f), candidate_list[0].display_rect);
+ EXPECT_EQ(gfx::RectF(0.f, 0.25f, 0.5f, 0.5f), candidate_list[0].uv_rect);
+}
+
+TEST_F(SandwichTest, SuccessfulTwoOverlays) {
+ scoped_ptr<RenderPass> pass = CreateRenderPass();
+
+ // Add two non-overlapping candidates.
+ CreateCandidateQuadAt(resource_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get(),
+ kOverlayTopLeftRect);
+ CreateCandidateQuadAt(resource_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get(),
+ kOverlayBottomRightRect);
+
+ // Add something behind it.
+ CreateFullscreenOpaqueQuad(resource_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get());
+
+ RenderPassList pass_list;
+ pass_list.push_back(pass.Pass());
+ OverlayCandidateList candidate_list;
+ overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
+
+ // Both candidates should become overlays.
+ EXPECT_EQ(1u, pass_list.size());
+ EXPECT_EQ(2u, candidate_list.size());
+ EXPECT_EQ(gfx::RectF(kOverlayTopLeftRect), candidate_list[0].display_rect);
+ EXPECT_EQ(gfx::RectF(kOverlayBottomRightRect),
+ candidate_list[1].display_rect);
+
+ // The overlay quads should be gone.
+ const QuadList& quad_list = pass_list.back()->quad_list;
+ EXPECT_EQ(1u, quad_list.size());
+ EXPECT_EQ(DrawQuad::SOLID_COLOR, quad_list.front()->material);
+}
+
+TEST_F(SandwichTest, OverlappingOverlays) {
+ scoped_ptr<RenderPass> pass = CreateRenderPass();
+
+ // Add two overlapping candidates.
+ CreateCandidateQuadAt(resource_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get(),
+ kOverlayTopLeftRect);
+ CreateCandidateQuadAt(resource_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get(),
+ kOverlayRect);
+
+ // Add something behind it.
+ CreateFullscreenOpaqueQuad(resource_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get());
+
+ RenderPassList pass_list;
+ pass_list.push_back(pass.Pass());
+ OverlayCandidateList candidate_list;
+ overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
+
+ // Only one of the candidates should become an overlay.
+ EXPECT_EQ(1u, pass_list.size());
+ EXPECT_EQ(1u, candidate_list.size());
+ EXPECT_EQ(gfx::RectF(kOverlayTopLeftRect), candidate_list[0].display_rect);
+
+ // One of the overlay quads should be gone.
+ const QuadList& quad_list = pass_list.back()->quad_list;
+ EXPECT_EQ(2u, quad_list.size());
+ EXPECT_EQ(DrawQuad::TEXTURE_CONTENT, quad_list.front()->material);
+ EXPECT_EQ(DrawQuad::SOLID_COLOR, quad_list.back()->material);
+}
+
+TEST_F(SandwichTest, SuccessfulSandwichOverlay) {
+ scoped_ptr<RenderPass> pass = CreateRenderPass();
+
+ CreateOpaqueQuadAt(resource_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get(),
+ gfx::Rect(16, 16, 32, 32));
+ unsigned candidate_id =
+ CreateCandidateQuadAt(resource_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get(),
+ gfx::Rect(32, 32, 32, 32))
+ ->resource_id();
+ CreateOpaqueQuadAt(resource_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get(),
+ gfx::Rect(kDisplaySize));
+
+ RenderPassList pass_list;
+ pass_list.push_back(pass.Pass());
+
+ // Check for potential candidates.
+ OverlayCandidateList candidate_list;
+ overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
+
+ ASSERT_EQ(1U, pass_list.size());
+ ASSERT_EQ(2U, candidate_list.size());
+
+ RenderPass* main_pass = pass_list.back();
+ // Check that the quad is gone.
+ EXPECT_EQ(3U, main_pass->quad_list.size());
+ const QuadList& quad_list = main_pass->quad_list;
+ for (QuadList::ConstBackToFrontIterator it = quad_list.BackToFrontBegin();
+ it != quad_list.BackToFrontEnd(); ++it) {
+ EXPECT_NE(DrawQuad::TEXTURE_CONTENT, it->material);
+ }
+
+ EXPECT_EQ(candidate_id, candidate_list[0].resource_id);
+ EXPECT_EQ(gfx::RectF(32.f, 32.f, 32.f, 32.f), candidate_list[0].display_rect);
+ EXPECT_TRUE(candidate_list[1].use_output_surface_for_resource);
+ EXPECT_EQ(gfx::RectF(32.f, 32.f, 16.f, 16.f), candidate_list[1].display_rect);
+ EXPECT_EQ(gfx::RectF(32.f / 256.f, 32.f / 256.f, 16.f / 256.f, 16.f / 256.f),
+ candidate_list[1].uv_rect);
+}
+
+TEST_F(SandwichTest, MultiQuadOverlay) {
+ scoped_ptr<RenderPass> pass = CreateRenderPass();
+
+ // Put two non-intersecting quads on top.
+ const gfx::Rect rect1(gfx::Rect(0, 0, 32, 32));
+ const gfx::Rect rect2(gfx::Rect(32, 32, 32, 32));
+ Region covered_region;
+ covered_region.Union(rect1);
+ covered_region.Union(rect2);
+ CreateOpaqueQuadAt(resource_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get(), rect1);
+ CreateOpaqueQuadAt(resource_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get(), rect2);
+
+ // Then a candidate that we'll turn into an overlay.
+ unsigned candidate_id =
+ CreateCandidateQuadAt(resource_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get(),
+ gfx::Rect(0, 0, 64, 64))
+ ->resource_id();
+
+ // Then some opaque background.
+ CreateOpaqueQuadAt(resource_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get(),
+ gfx::Rect(kDisplaySize));
+
+ RenderPassList pass_list;
+ pass_list.push_back(pass.Pass());
+
+ // Run the overlay strategy on that input.
+ RenderPass* main_pass = pass_list.back();
+ OverlayCandidateList candidate_list;
+ EXPECT_EQ(4U, main_pass->quad_list.size());
+ overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
+ ASSERT_EQ(1U, pass_list.size());
+ ASSERT_EQ(3U, candidate_list.size());
+
+ // Check that the candidate quad is gone and that we now have two transparent
+ // quads for the same region that was covered on the overlay.
+ EXPECT_EQ(5U, main_pass->quad_list.size());
+ const QuadList& quad_list = main_pass->quad_list;
+ Region transparent_quad_region;
+ for (QuadList::ConstBackToFrontIterator it = quad_list.BackToFrontBegin();
+ it != quad_list.BackToFrontEnd(); ++it) {
+ EXPECT_NE(DrawQuad::TEXTURE_CONTENT, it->material);
+ if (it->material == DrawQuad::SOLID_COLOR) {
+ const SolidColorDrawQuad* solid_color_quad =
+ SolidColorDrawQuad::MaterialCast(*it);
+ if (solid_color_quad->color == SK_ColorTRANSPARENT)
+ transparent_quad_region.Union(solid_color_quad->rect);
+ }
+ }
+ DCHECK(covered_region == transparent_quad_region);
+
+ // Check that overlays cover the same region that the quads covered.
+ EXPECT_EQ(candidate_id, candidate_list[0].resource_id);
+ EXPECT_EQ(gfx::RectF(64.f, 64.f), candidate_list[0].display_rect);
+ EXPECT_TRUE(candidate_list[1].use_output_surface_for_resource);
+ EXPECT_TRUE(candidate_list[2].use_output_surface_for_resource);
+ Region overlay_region;
+ overlay_region.Union(gfx::ToEnclosingRect(candidate_list[1].display_rect));
+ overlay_region.Union(gfx::ToEnclosingRect(candidate_list[2].display_rect));
+ DCHECK(covered_region == overlay_region);
+}
TEST_F(SingleOverlayOnTopTest, SuccessfullOverlay) {
scoped_ptr<RenderPass> pass = CreateRenderPass();
@@ -351,12 +649,10 @@ TEST_F(SingleOverlayOnTopTest, SuccessfullOverlay) {
unsigned original_resource_id = original_quad->resource_id();
// Add something behind it.
- CreateFullscreenCheckeredQuad(resource_provider_.get(),
- pass->shared_quad_state_list.back(),
- pass.get());
- CreateFullscreenCheckeredQuad(resource_provider_.get(),
- pass->shared_quad_state_list.back(),
- pass.get());
+ CreateFullscreenOpaqueQuad(resource_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get());
+ CreateFullscreenOpaqueQuad(resource_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get());
RenderPassList pass_list;
pass_list.push_back(pass.Pass());
@@ -366,7 +662,7 @@ TEST_F(SingleOverlayOnTopTest, SuccessfullOverlay) {
overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
ASSERT_EQ(1U, pass_list.size());
- ASSERT_EQ(2U, candidate_list.size());
+ ASSERT_EQ(1U, candidate_list.size());
RenderPass* main_pass = pass_list.back();
// Check that the quad is gone.
@@ -384,12 +680,10 @@ TEST_F(SingleOverlayOnTopTest, SuccessfullOverlay) {
TEST_F(SingleOverlayOnTopTest, NoCandidates) {
scoped_ptr<RenderPass> pass = CreateRenderPass();
- CreateFullscreenCheckeredQuad(resource_provider_.get(),
- pass->shared_quad_state_list.back(),
- pass.get());
- CreateFullscreenCheckeredQuad(resource_provider_.get(),
- pass->shared_quad_state_list.back(),
- pass.get());
+ CreateFullscreenOpaqueQuad(resource_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get());
+ CreateFullscreenOpaqueQuad(resource_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get());
RenderPassList pass_list;
pass_list.push_back(pass.Pass());
@@ -406,12 +700,10 @@ TEST_F(SingleOverlayOnTopTest, NoCandidates) {
TEST_F(SingleOverlayOnTopTest, OccludedCandidates) {
scoped_ptr<RenderPass> pass = CreateRenderPass();
- CreateFullscreenCheckeredQuad(resource_provider_.get(),
- pass->shared_quad_state_list.back(),
- pass.get());
- CreateFullscreenCheckeredQuad(resource_provider_.get(),
- pass->shared_quad_state_list.back(),
- pass.get());
+ CreateFullscreenOpaqueQuad(resource_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get());
+ CreateFullscreenOpaqueQuad(resource_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get());
CreateFullscreenCandidateQuad(resource_provider_.get(),
pass->shared_quad_state_list.back(),
@@ -441,12 +733,10 @@ TEST_F(SingleOverlayOnTopTest, MultipleRenderPasses) {
pass.get());
// Add something behind it.
- CreateFullscreenCheckeredQuad(resource_provider_.get(),
- pass->shared_quad_state_list.back(),
- pass.get());
- CreateFullscreenCheckeredQuad(resource_provider_.get(),
- pass->shared_quad_state_list.back(),
- pass.get());
+ CreateFullscreenOpaqueQuad(resource_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get());
+ CreateFullscreenOpaqueQuad(resource_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get());
pass_list.push_back(pass.Pass());
@@ -456,7 +746,7 @@ TEST_F(SingleOverlayOnTopTest, MultipleRenderPasses) {
// Check for potential candidates.
OverlayCandidateList candidate_list;
overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
- EXPECT_EQ(2U, candidate_list.size());
+ EXPECT_EQ(1U, candidate_list.size());
// This should be the same.
ASSERT_EQ(2U, pass_list.size());
@@ -556,6 +846,22 @@ TEST_F(SingleOverlayOnTopTest, RejectNonAxisAlignedTransform) {
EXPECT_EQ(0U, candidate_list.size());
}
+TEST_F(SingleOverlayOnTopTest, AllowClipped) {
+ scoped_ptr<RenderPass> pass = CreateRenderPass();
+ CreateFullscreenCandidateQuad(resource_provider_.get(),
+ pass->shared_quad_state_list.back(),
+ pass.get());
+ pass->shared_quad_state_list.back()->is_clipped = true;
+ pass->shared_quad_state_list.back()->clip_rect = kOverlayClipRect;
+
+ RenderPassList pass_list;
+ pass_list.push_back(pass.Pass());
+ OverlayCandidateList candidate_list;
+ overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
+ ASSERT_EQ(1U, pass_list.size());
+ EXPECT_EQ(1U, candidate_list.size());
+}
+
TEST_F(SingleOverlayOnTopTest, AllowVerticalFlip) {
gfx::Rect rect = kOverlayRect;
rect.set_width(rect.width() / 2);
@@ -571,7 +877,7 @@ TEST_F(SingleOverlayOnTopTest, AllowVerticalFlip) {
OverlayCandidateList candidate_list;
overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
ASSERT_EQ(1U, pass_list.size());
- ASSERT_EQ(2U, candidate_list.size());
+ ASSERT_EQ(1U, candidate_list.size());
EXPECT_EQ(gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL,
candidate_list.back().transform);
}
@@ -591,7 +897,7 @@ TEST_F(SingleOverlayOnTopTest, AllowHorizontalFlip) {
OverlayCandidateList candidate_list;
overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
ASSERT_EQ(1U, pass_list.size());
- ASSERT_EQ(2U, candidate_list.size());
+ ASSERT_EQ(1U, candidate_list.size());
EXPECT_EQ(gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL,
candidate_list.back().transform);
}
@@ -610,7 +916,7 @@ TEST_F(SingleOverlayOnTopTest, AllowPositiveScaleTransform) {
OverlayCandidateList candidate_list;
overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
ASSERT_EQ(1U, pass_list.size());
- EXPECT_EQ(2U, candidate_list.size());
+ EXPECT_EQ(1U, candidate_list.size());
}
TEST_F(SingleOverlayOnTopTest, Allow90DegreeRotation) {
@@ -627,7 +933,7 @@ TEST_F(SingleOverlayOnTopTest, Allow90DegreeRotation) {
OverlayCandidateList candidate_list;
overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
ASSERT_EQ(1U, pass_list.size());
- ASSERT_EQ(2U, candidate_list.size());
+ ASSERT_EQ(1U, candidate_list.size());
EXPECT_EQ(gfx::OVERLAY_TRANSFORM_ROTATE_90, candidate_list.back().transform);
}
@@ -645,7 +951,7 @@ TEST_F(SingleOverlayOnTopTest, Allow180DegreeRotation) {
OverlayCandidateList candidate_list;
overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
ASSERT_EQ(1U, pass_list.size());
- ASSERT_EQ(2U, candidate_list.size());
+ ASSERT_EQ(1U, candidate_list.size());
EXPECT_EQ(gfx::OVERLAY_TRANSFORM_ROTATE_180, candidate_list.back().transform);
}
@@ -663,16 +969,15 @@ TEST_F(SingleOverlayOnTopTest, Allow270DegreeRotation) {
OverlayCandidateList candidate_list;
overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
ASSERT_EQ(1U, pass_list.size());
- ASSERT_EQ(2U, candidate_list.size());
+ ASSERT_EQ(1U, candidate_list.size());
EXPECT_EQ(gfx::OVERLAY_TRANSFORM_ROTATE_270, candidate_list.back().transform);
}
TEST_F(SingleOverlayOnTopTest, AllowNotTopIfNotOccluded) {
scoped_ptr<RenderPass> pass = CreateRenderPass();
- CreateCheckeredQuadAt(resource_provider_.get(),
- pass->shared_quad_state_list.back(),
- pass.get(),
- kOverlayTopLeftRect);
+ CreateOpaqueQuadAt(resource_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get(),
+ kOverlayTopLeftRect);
CreateCandidateQuadAt(resource_provider_.get(),
pass->shared_quad_state_list.back(),
pass.get(),
@@ -687,7 +992,7 @@ TEST_F(SingleOverlayOnTopTest, AllowNotTopIfNotOccluded) {
OverlayCandidateList candidate_list;
overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
EXPECT_EQ(1U, pass_list.size());
- EXPECT_EQ(2U, candidate_list.size());
+ EXPECT_EQ(1U, candidate_list.size());
}
TEST_F(SingleOverlayOnTopTest, AllowTransparentOnTop) {
@@ -710,7 +1015,7 @@ TEST_F(SingleOverlayOnTopTest, AllowTransparentOnTop) {
OverlayCandidateList candidate_list;
overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
EXPECT_EQ(1U, pass_list.size());
- EXPECT_EQ(2U, candidate_list.size());
+ EXPECT_EQ(1U, candidate_list.size());
}
TEST_F(SingleOverlayOnTopTest, AllowTransparentColorOnTop) {
@@ -731,7 +1036,7 @@ TEST_F(SingleOverlayOnTopTest, AllowTransparentColorOnTop) {
OverlayCandidateList candidate_list;
overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
EXPECT_EQ(1U, pass_list.size());
- EXPECT_EQ(2U, candidate_list.size());
+ EXPECT_EQ(1U, candidate_list.size());
}
TEST_F(SingleOverlayOnTopTest, RejectOpaqueColorOnTop) {
@@ -803,7 +1108,7 @@ TEST_F(SingleOverlayOnTopTest, AllowVideoXMirrorTransform) {
OverlayCandidateList candidate_list;
overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
ASSERT_EQ(1U, pass_list.size());
- EXPECT_EQ(2U, candidate_list.size());
+ EXPECT_EQ(1U, candidate_list.size());
}
TEST_F(SingleOverlayOnTopTest, AllowVideoBothMirrorTransform) {
@@ -817,7 +1122,7 @@ TEST_F(SingleOverlayOnTopTest, AllowVideoBothMirrorTransform) {
OverlayCandidateList candidate_list;
overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
ASSERT_EQ(1U, pass_list.size());
- EXPECT_EQ(2U, candidate_list.size());
+ EXPECT_EQ(1U, candidate_list.size());
}
TEST_F(SingleOverlayOnTopTest, AllowVideoNormalTransform) {
@@ -831,7 +1136,7 @@ TEST_F(SingleOverlayOnTopTest, AllowVideoNormalTransform) {
OverlayCandidateList candidate_list;
overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
ASSERT_EQ(1U, pass_list.size());
- EXPECT_EQ(2U, candidate_list.size());
+ EXPECT_EQ(1U, candidate_list.size());
}
TEST_F(SingleOverlayOnTopTest, AllowVideoYMirrorTransform) {
@@ -845,14 +1150,13 @@ TEST_F(SingleOverlayOnTopTest, AllowVideoYMirrorTransform) {
OverlayCandidateList candidate_list;
overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
ASSERT_EQ(1U, pass_list.size());
- EXPECT_EQ(2U, candidate_list.size());
+ EXPECT_EQ(1U, candidate_list.size());
}
TEST_F(UnderlayTest, OverlayLayerUnderMainLayer) {
scoped_ptr<RenderPass> pass = CreateRenderPass();
- CreateFullscreenCheckeredQuad(resource_provider_.get(),
- pass->shared_quad_state_list.back(),
- pass.get());
+ CreateFullscreenOpaqueQuad(resource_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get());
CreateCandidateQuadAt(resource_provider_.get(),
pass->shared_quad_state_list.back(), pass.get(),
kOverlayBottomRightRect);
@@ -863,9 +1167,8 @@ TEST_F(UnderlayTest, OverlayLayerUnderMainLayer) {
OverlayCandidateList candidate_list;
overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
EXPECT_EQ(1U, pass_list.size());
- ASSERT_EQ(2U, candidate_list.size());
- EXPECT_EQ(0, candidate_list[0].plane_z_order);
- EXPECT_EQ(-1, candidate_list[1].plane_z_order);
+ ASSERT_EQ(1U, candidate_list.size());
+ EXPECT_EQ(-1, candidate_list[0].plane_z_order);
EXPECT_EQ(2U, pass_list[0]->quad_list.size());
// The overlay quad should have changed to a SOLID_COLOR quad.
EXPECT_EQ(pass_list[0]->quad_list.back()->material, DrawQuad::SOLID_COLOR);
@@ -877,9 +1180,8 @@ TEST_F(UnderlayTest, AllowOnTop) {
pass->shared_quad_state_list.back(),
pass.get());
pass->CreateAndAppendSharedQuadState()->opacity = 0.5f;
- CreateFullscreenCheckeredQuad(resource_provider_.get(),
- pass->shared_quad_state_list.back(),
- pass.get());
+ CreateFullscreenOpaqueQuad(resource_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get());
RenderPassList pass_list;
pass_list.push_back(pass.Pass());
@@ -887,13 +1189,63 @@ TEST_F(UnderlayTest, AllowOnTop) {
OverlayCandidateList candidate_list;
overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
EXPECT_EQ(1U, pass_list.size());
- ASSERT_EQ(2U, candidate_list.size());
- EXPECT_EQ(0, candidate_list[0].plane_z_order);
- EXPECT_EQ(-1, candidate_list[1].plane_z_order);
+ ASSERT_EQ(1U, candidate_list.size());
+ EXPECT_EQ(-1, candidate_list[0].plane_z_order);
// The overlay quad should have changed to a SOLID_COLOR quad.
EXPECT_EQ(pass_list[0]->quad_list.front()->material, DrawQuad::SOLID_COLOR);
}
+TEST_F(AllOrNothingOverlayTest, SuccessfulOverlappingOverlays) {
+ scoped_ptr<RenderPass> pass = CreateRenderPass();
+
+ // Add two overlapping candidates.
+ CreateCandidateQuadAt(resource_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get(),
+ kOverlayTopLeftRect);
+ CreateCandidateQuadAt(resource_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get(),
+ kOverlayRect);
+
+ RenderPassList pass_list;
+ pass_list.push_back(pass.Pass());
+ OverlayCandidateList candidates;
+ overlay_processor_->ProcessForOverlays(&pass_list, &candidates);
+
+ // Both quads should become overlays.
+ EXPECT_EQ(2u, candidates.size());
+ EXPECT_EQ(-1, candidates[0].plane_z_order);
+ EXPECT_EQ(-2, candidates[1].plane_z_order);
+ EXPECT_EQ(gfx::RectF(kOverlayTopLeftRect), candidates[0].display_rect);
+ EXPECT_EQ(gfx::RectF(kOverlayRect), candidates[1].display_rect);
+
+ // All quads should be gone.
+ EXPECT_TRUE(pass_list.back()->quad_list.empty());
+}
+
+TEST_F(AllOrNothingOverlayTest, RejectQuadWithTransform) {
+ scoped_ptr<RenderPass> pass = CreateRenderPass();
+
+ CreateCandidateQuadAt(resource_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get(),
+ kOverlayTopLeftRect);
+
+ // Add a rotated quad that can't be promoted into overlay.
+ SharedQuadState* shared_state = pass->CreateAndAppendSharedQuadState();
+ shared_state->opacity = 1.f;
+ shared_state->quad_to_target_transform.Rotate(90);
+ CreateSolidColorQuadAt(shared_state, SK_ColorBLACK, pass.get(),
+ kOverlayBottomRightRect);
+
+ RenderPassList pass_list;
+ pass_list.push_back(pass.Pass());
+ OverlayCandidateList candidates;
+ overlay_processor_->ProcessForOverlays(&pass_list, &candidates);
+
+ // No quads should become overlays.
+ EXPECT_EQ(0u, candidates.size());
+ EXPECT_EQ(2u, pass_list.back()->quad_list.size());
+}
+
class OverlayInfoRendererGL : public GLRenderer {
public:
OverlayInfoRendererGL(RendererClient* client,
@@ -966,7 +1318,7 @@ class GLRendererWithOverlaysTest : public testing::Test {
void Init(bool use_validator) {
if (use_validator)
- output_surface_->InitWithSingleOverlayValidator();
+ output_surface_->SetOverlayCandidateValidator(new SingleOverlayValidator);
renderer_ =
make_scoped_ptr(new OverlayInfoRendererGL(&renderer_client_,
@@ -999,12 +1351,10 @@ TEST_F(GLRendererWithOverlaysTest, OverlayQuadNotDrawn) {
pass->shared_quad_state_list.back(),
pass.get());
- CreateFullscreenCheckeredQuad(resource_provider_.get(),
- pass->shared_quad_state_list.back(),
- pass.get());
- CreateFullscreenCheckeredQuad(resource_provider_.get(),
- pass->shared_quad_state_list.back(),
- pass.get());
+ CreateFullscreenOpaqueQuad(resource_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get());
+ CreateFullscreenOpaqueQuad(resource_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get());
RenderPassList pass_list;
pass_list.push_back(pass.Pass());
@@ -1013,11 +1363,13 @@ TEST_F(GLRendererWithOverlaysTest, OverlayQuadNotDrawn) {
// so only draw 2 quads.
EXPECT_CALL(*renderer_, DoDrawQuad(_, _, _)).Times(2);
EXPECT_CALL(scheduler_,
- Schedule(1,
- gfx::OVERLAY_TRANSFORM_NONE,
- _,
- kOverlayRect,
- BoundingRect(kUVTopLeft, kUVBottomRight))).Times(1);
+ Schedule(0, gfx::OVERLAY_TRANSFORM_NONE, _,
+ gfx::Rect(kDisplaySize), gfx::RectF(0, 0, 1, 1)))
+ .Times(1);
+ EXPECT_CALL(scheduler_,
+ Schedule(1, gfx::OVERLAY_TRANSFORM_NONE, _, kOverlayRect,
+ BoundingRect(kUVTopLeft, kUVBottomRight)))
+ .Times(1);
renderer_->DrawFrame(&pass_list, 1.f, viewport_rect, viewport_rect, false);
SwapBuffers();
@@ -1034,12 +1386,10 @@ TEST_F(GLRendererWithOverlaysTest, OccludedQuadInUnderlay) {
scoped_ptr<RenderPass> pass = CreateRenderPass();
- CreateFullscreenCheckeredQuad(resource_provider_.get(),
- pass->shared_quad_state_list.back(),
- pass.get());
- CreateFullscreenCheckeredQuad(resource_provider_.get(),
- pass->shared_quad_state_list.back(),
- pass.get());
+ CreateFullscreenOpaqueQuad(resource_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get());
+ CreateFullscreenOpaqueQuad(resource_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get());
CreateFullscreenCandidateQuad(resource_provider_.get(),
pass->shared_quad_state_list.back(),
@@ -1052,8 +1402,13 @@ TEST_F(GLRendererWithOverlaysTest, OccludedQuadInUnderlay) {
// Expect to be replaced with transparent hole quad and placed in underlay.
EXPECT_CALL(*renderer_, DoDrawQuad(_, _, _)).Times(3);
EXPECT_CALL(scheduler_,
+ Schedule(0, gfx::OVERLAY_TRANSFORM_NONE, _,
+ gfx::Rect(kDisplaySize), gfx::RectF(0, 0, 1, 1)))
+ .Times(1);
+ EXPECT_CALL(scheduler_,
Schedule(-1, gfx::OVERLAY_TRANSFORM_NONE, _, kOverlayRect,
- BoundingRect(kUVTopLeft, kUVBottomRight))).Times(1);
+ BoundingRect(kUVTopLeft, kUVBottomRight)))
+ .Times(1);
renderer_->DrawFrame(&pass_list, 1.f, viewport_rect, viewport_rect, false);
SwapBuffers();
@@ -1074,23 +1429,20 @@ TEST_F(GLRendererWithOverlaysTest, NoValidatorNoOverlay) {
pass->shared_quad_state_list.back(),
pass.get());
- CreateFullscreenCheckeredQuad(resource_provider_.get(),
- pass->shared_quad_state_list.back(),
- pass.get());
- CreateFullscreenCheckeredQuad(resource_provider_.get(),
- pass->shared_quad_state_list.back(),
- pass.get());
+ CreateFullscreenOpaqueQuad(resource_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get());
+ CreateFullscreenOpaqueQuad(resource_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get());
RenderPassList pass_list;
pass_list.push_back(pass.Pass());
- // Should see no overlays.
+ // Should not see the primary surface's overlay.
+ output_surface_->set_is_displayed_as_overlay_plane(false);
EXPECT_CALL(*renderer_, DoDrawQuad(_, _, _)).Times(3);
EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(0);
renderer_->DrawFrame(&pass_list, 1.f, viewport_rect, viewport_rect, false);
-
SwapBuffers();
-
Mock::VerifyAndClearExpectations(renderer_.get());
Mock::VerifyAndClearExpectations(&scheduler_);
}
@@ -1110,6 +1462,7 @@ TEST_F(GLRendererWithOverlaysTest, ResourcesExportedAndReturned) {
DirectRenderer::DrawingFrame frame1;
frame1.render_passes_in_draw_order = &pass_list;
frame1.overlay_list.resize(2);
+ frame1.overlay_list.front().use_output_surface_for_resource = true;
OverlayCandidate& overlay1 = frame1.overlay_list.back();
overlay1.resource_id = resource1;
overlay1.plane_z_order = 1;
@@ -1117,19 +1470,21 @@ TEST_F(GLRendererWithOverlaysTest, ResourcesExportedAndReturned) {
DirectRenderer::DrawingFrame frame2;
frame2.render_passes_in_draw_order = &pass_list;
frame2.overlay_list.resize(2);
+ frame2.overlay_list.front().use_output_surface_for_resource = true;
OverlayCandidate& overlay2 = frame2.overlay_list.back();
overlay2.resource_id = resource2;
overlay2.plane_z_order = 1;
- EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(1);
+ EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(2);
renderer_->BeginDrawingFrame(&frame1);
+ printf("About to finish, %d %d\n", resource1, resource2);
renderer_->FinishDrawingFrame(&frame1);
EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
EXPECT_FALSE(resource_provider_->InUseByConsumer(resource2));
SwapBuffers();
Mock::VerifyAndClearExpectations(&scheduler_);
- EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(1);
+ EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(2);
renderer_->BeginDrawingFrame(&frame2);
renderer_->FinishDrawingFrame(&frame2);
EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
@@ -1138,7 +1493,7 @@ TEST_F(GLRendererWithOverlaysTest, ResourcesExportedAndReturned) {
EXPECT_FALSE(resource_provider_->InUseByConsumer(resource1));
Mock::VerifyAndClearExpectations(&scheduler_);
- EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(1);
+ EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(2);
renderer_->BeginDrawingFrame(&frame1);
renderer_->FinishDrawingFrame(&frame1);
EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
@@ -1162,14 +1517,14 @@ TEST_F(GLRendererWithOverlaysTest, ResourcesExportedAndReturned) {
// Use the same buffer twice.
renderer_->set_expect_overlays(true);
- EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(1);
+ EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(2);
renderer_->BeginDrawingFrame(&frame1);
renderer_->FinishDrawingFrame(&frame1);
EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
SwapBuffers();
Mock::VerifyAndClearExpectations(&scheduler_);
- EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(1);
+ EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(2);
renderer_->BeginDrawingFrame(&frame1);
renderer_->FinishDrawingFrame(&frame1);
EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
@@ -1187,5 +1542,125 @@ TEST_F(GLRendererWithOverlaysTest, ResourcesExportedAndReturned) {
Mock::VerifyAndClearExpectations(&scheduler_);
}
+TEST_F(GLRendererWithOverlaysTest, ResourcesExportedAndReturnedWithDelay) {
+ bool use_validator = true;
+ settings_.delay_releasing_overlay_resources = true;
+ Init(use_validator);
+ renderer_->set_expect_overlays(true);
+
+ ResourceId resource1 = CreateResource(resource_provider_.get());
+ ResourceId resource2 = CreateResource(resource_provider_.get());
+ ResourceId resource3 = CreateResource(resource_provider_.get());
+
+ scoped_ptr<RenderPass> pass = CreateRenderPass();
+ RenderPassList pass_list;
+ pass_list.push_back(pass.Pass());
+
+ DirectRenderer::DrawingFrame frame1;
+ frame1.render_passes_in_draw_order = &pass_list;
+ frame1.overlay_list.resize(2);
+ frame1.overlay_list.front().use_output_surface_for_resource = true;
+ OverlayCandidate& overlay1 = frame1.overlay_list.back();
+ overlay1.resource_id = resource1;
+ overlay1.plane_z_order = 1;
+
+ DirectRenderer::DrawingFrame frame2;
+ frame2.render_passes_in_draw_order = &pass_list;
+ frame2.overlay_list.resize(2);
+ frame2.overlay_list.front().use_output_surface_for_resource = true;
+ OverlayCandidate& overlay2 = frame2.overlay_list.back();
+ overlay2.resource_id = resource2;
+ overlay2.plane_z_order = 1;
+
+ DirectRenderer::DrawingFrame frame3;
+ frame3.render_passes_in_draw_order = &pass_list;
+ frame3.overlay_list.resize(2);
+ frame3.overlay_list.front().use_output_surface_for_resource = true;
+ OverlayCandidate& overlay3 = frame3.overlay_list.back();
+ overlay3.resource_id = resource3;
+ overlay3.plane_z_order = 1;
+
+ EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(2);
+ renderer_->BeginDrawingFrame(&frame1);
+ renderer_->FinishDrawingFrame(&frame1);
+ EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
+ EXPECT_FALSE(resource_provider_->InUseByConsumer(resource2));
+ SwapBuffers();
+ Mock::VerifyAndClearExpectations(&scheduler_);
+
+ EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(2);
+ renderer_->BeginDrawingFrame(&frame2);
+ renderer_->FinishDrawingFrame(&frame2);
+ EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
+ EXPECT_TRUE(resource_provider_->InUseByConsumer(resource2));
+ SwapBuffers();
+ EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
+ EXPECT_TRUE(resource_provider_->InUseByConsumer(resource2));
+ Mock::VerifyAndClearExpectations(&scheduler_);
+
+ EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(2);
+ renderer_->BeginDrawingFrame(&frame3);
+ renderer_->FinishDrawingFrame(&frame3);
+ EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
+ EXPECT_TRUE(resource_provider_->InUseByConsumer(resource2));
+ EXPECT_TRUE(resource_provider_->InUseByConsumer(resource3));
+ SwapBuffers();
+ EXPECT_FALSE(resource_provider_->InUseByConsumer(resource1));
+ EXPECT_TRUE(resource_provider_->InUseByConsumer(resource2));
+ EXPECT_TRUE(resource_provider_->InUseByConsumer(resource3));
+ Mock::VerifyAndClearExpectations(&scheduler_);
+
+ // No overlays, release the resource.
+ EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(0);
+ DirectRenderer::DrawingFrame frame_no_overlays;
+ frame_no_overlays.render_passes_in_draw_order = &pass_list;
+ renderer_->set_expect_overlays(false);
+ renderer_->BeginDrawingFrame(&frame_no_overlays);
+ renderer_->FinishDrawingFrame(&frame_no_overlays);
+ EXPECT_FALSE(resource_provider_->InUseByConsumer(resource1));
+ EXPECT_TRUE(resource_provider_->InUseByConsumer(resource2));
+ EXPECT_TRUE(resource_provider_->InUseByConsumer(resource3));
+ SwapBuffers();
+ EXPECT_FALSE(resource_provider_->InUseByConsumer(resource1));
+ EXPECT_FALSE(resource_provider_->InUseByConsumer(resource2));
+ EXPECT_TRUE(resource_provider_->InUseByConsumer(resource3));
+ Mock::VerifyAndClearExpectations(&scheduler_);
+
+ // Use the same buffer twice.
+ renderer_->set_expect_overlays(true);
+ EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(2);
+ renderer_->BeginDrawingFrame(&frame1);
+ renderer_->FinishDrawingFrame(&frame1);
+ EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
+ SwapBuffers();
+ Mock::VerifyAndClearExpectations(&scheduler_);
+
+ EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(2);
+ renderer_->BeginDrawingFrame(&frame1);
+ renderer_->FinishDrawingFrame(&frame1);
+ EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
+ SwapBuffers();
+ EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
+ Mock::VerifyAndClearExpectations(&scheduler_);
+
+ EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(0);
+ renderer_->set_expect_overlays(false);
+ renderer_->BeginDrawingFrame(&frame_no_overlays);
+ renderer_->FinishDrawingFrame(&frame_no_overlays);
+ EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
+ SwapBuffers();
+ EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
+ Mock::VerifyAndClearExpectations(&scheduler_);
+
+ EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(0);
+ renderer_->set_expect_overlays(false);
+ renderer_->BeginDrawingFrame(&frame_no_overlays);
+ renderer_->FinishDrawingFrame(&frame_no_overlays);
+ EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
+ SwapBuffers();
+ EXPECT_FALSE(resource_provider_->InUseByConsumer(resource1));
+ Mock::VerifyAndClearExpectations(&scheduler_);
+}
+
} // namespace
} // namespace cc
diff --git a/chromium/cc/output/renderer.h b/chromium/cc/output/renderer.h
index 8143e2a0410..96406a23fb2 100644
--- a/chromium/cc/output/renderer.h
+++ b/chromium/cc/output/renderer.h
@@ -73,8 +73,6 @@ class CC_EXPORT Renderer {
// Waits for rendering to finish.
virtual void Finish() = 0;
- virtual void DoNoOp() {}
-
// Puts backbuffer onscreen.
virtual void SwapBuffers(const CompositorFrameMetadata& metadata) = 0;
virtual void ReceiveSwapBuffersAck(const CompositorFrameAck& ack) {}
diff --git a/chromium/cc/output/renderer_pixeltest.cc b/chromium/cc/output/renderer_pixeltest.cc
index 8472ff50613..76fb2c3811d 100644
--- a/chromium/cc/output/renderer_pixeltest.cc
+++ b/chromium/cc/output/renderer_pixeltest.cc
@@ -8,13 +8,15 @@
#include "cc/quads/picture_draw_quad.h"
#include "cc/quads/texture_draw_quad.h"
#include "cc/resources/video_resource_updater.h"
-#include "cc/test/fake_picture_pile_impl.h"
+#include "cc/test/fake_display_list_raster_source.h"
+#include "cc/test/fake_display_list_recording_source.h"
#include "cc/test/pixel_test.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "media/base/video_frame.h"
#include "third_party/skia/include/core/SkColorPriv.h"
#include "third_party/skia/include/core/SkImageFilter.h"
#include "third_party/skia/include/core/SkMatrix.h"
+#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/effects/SkColorFilterImageFilter.h"
#include "third_party/skia/include/effects/SkColorMatrixFilter.h"
#include "ui/gfx/geometry/rect_conversions.h"
@@ -190,12 +192,12 @@ void CreateTestYUVVideoDrawQuad_FromVideoFrame(
const gfx::Rect& rect,
const gfx::Rect& visible_rect,
ResourceProvider* resource_provider) {
- const bool with_alpha = (video_frame->format() == media::VideoFrame::YV12A);
+ const bool with_alpha = (video_frame->format() == media::PIXEL_FORMAT_YV12A);
YUVVideoDrawQuad::ColorSpace color_space = YUVVideoDrawQuad::REC_601;
int video_frame_color_space;
if (video_frame->metadata()->GetInteger(
media::VideoFrameMetadata::COLOR_SPACE, &video_frame_color_space) &&
- video_frame_color_space == media::VideoFrame::COLOR_SPACE_JPEG) {
+ video_frame_color_space == media::COLOR_SPACE_JPEG) {
color_space = YUVVideoDrawQuad::JPEG;
}
@@ -269,7 +271,7 @@ void CreateTestYUVVideoDrawQuad_FromVideoFrame(
void CreateTestYUVVideoDrawQuad_Striped(
const SharedQuadState* shared_state,
- media::VideoFrame::Format format,
+ media::VideoPixelFormat format,
bool is_transparent,
const gfx::RectF& tex_coord_rect,
RenderPass* render_pass,
@@ -316,8 +318,8 @@ void CreateTestYUVVideoDrawQuad_Striped(
// by 2 because YUV is a block format.
void CreateTestYUVVideoDrawQuad_TwoColor(
const SharedQuadState* shared_state,
- media::VideoFrame::Format format,
- media::VideoFrame::ColorSpace color_space,
+ media::VideoPixelFormat format,
+ media::ColorSpace color_space,
bool is_transparent,
const gfx::RectF& tex_coord_rect,
const gfx::Size& background_size,
@@ -380,8 +382,8 @@ void CreateTestYUVVideoDrawQuad_TwoColor(
void CreateTestYUVVideoDrawQuad_Solid(
const SharedQuadState* shared_state,
- media::VideoFrame::Format format,
- media::VideoFrame::ColorSpace color_space,
+ media::VideoPixelFormat format,
+ media::ColorSpace color_space,
bool is_transparent,
const gfx::RectF& tex_coord_rect,
uint8 y,
@@ -749,11 +751,11 @@ TYPED_TEST(IntersectingQuadPixelTest, TexturedQuads) {
TYPED_TEST(IntersectingQuadSoftwareTest, PictureQuads) {
this->SetupQuadStateAndRenderPass();
- gfx::RectF outer_rect(this->quad_rect_);
- gfx::RectF inner_rect(this->quad_rect_.x() + (this->quad_rect_.width() / 4),
- this->quad_rect_.y() + (this->quad_rect_.height() / 4),
- this->quad_rect_.width() / 2,
- this->quad_rect_.height() / 2);
+ gfx::Rect outer_rect(this->quad_rect_);
+ gfx::Rect inner_rect(this->quad_rect_.x() + (this->quad_rect_.width() / 4),
+ this->quad_rect_.y() + (this->quad_rect_.height() / 4),
+ this->quad_rect_.width() / 2,
+ this->quad_rect_.height() / 2);
SkPaint black_paint;
black_paint.setColor(SK_ColorBLACK);
@@ -762,37 +764,40 @@ TYPED_TEST(IntersectingQuadSoftwareTest, PictureQuads) {
SkPaint green_paint;
green_paint.setColor(SK_ColorGREEN);
- scoped_ptr<FakePicturePile> blue_recording =
- FakePicturePile::CreateFilledPile(gfx::Size(1000, 1000),
- this->quad_rect_.size());
+ scoped_ptr<FakeDisplayListRecordingSource> blue_recording =
+ FakeDisplayListRecordingSource::CreateFilledRecordingSource(
+ this->quad_rect_.size());
blue_recording->add_draw_rect_with_paint(outer_rect, black_paint);
blue_recording->add_draw_rect_with_paint(inner_rect, blue_paint);
blue_recording->Rerecord();
- scoped_refptr<FakePicturePileImpl> blue_pile =
- FakePicturePileImpl::CreateFromPile(blue_recording.get(), nullptr);
+ scoped_refptr<FakeDisplayListRasterSource> blue_raster_source =
+ FakeDisplayListRasterSource::CreateFromRecordingSource(
+ blue_recording.get(), false);
PictureDrawQuad* blue_quad =
this->render_pass_->template CreateAndAppendDrawQuad<PictureDrawQuad>();
blue_quad->SetNew(this->front_quad_state_, this->quad_rect_, gfx::Rect(),
- this->quad_rect_, this->quad_rect_, this->quad_rect_.size(),
- false, RGBA_8888, this->quad_rect_, 1.f, blue_pile);
+ this->quad_rect_, gfx::RectF(this->quad_rect_),
+ this->quad_rect_.size(), false, RGBA_8888, this->quad_rect_,
+ 1.f, blue_raster_source);
- scoped_ptr<FakePicturePile> green_recording =
- FakePicturePile::CreateFilledPile(this->quad_rect_.size(),
- this->quad_rect_.size());
+ scoped_ptr<FakeDisplayListRecordingSource> green_recording =
+ FakeDisplayListRecordingSource::CreateFilledRecordingSource(
+ this->quad_rect_.size());
green_recording->add_draw_rect_with_paint(outer_rect, green_paint);
green_recording->add_draw_rect_with_paint(inner_rect, black_paint);
green_recording->Rerecord();
- scoped_refptr<FakePicturePileImpl> green_pile =
- FakePicturePileImpl::CreateFromPile(green_recording.get(), nullptr);
+ scoped_refptr<FakeDisplayListRasterSource> green_raster_source =
+ FakeDisplayListRasterSource::CreateFromRecordingSource(
+ green_recording.get(), false);
PictureDrawQuad* green_quad =
this->render_pass_->template CreateAndAppendDrawQuad<PictureDrawQuad>();
green_quad->SetNew(this->back_quad_state_, this->quad_rect_, gfx::Rect(),
- this->quad_rect_, this->quad_rect_,
+ this->quad_rect_, gfx::RectF(this->quad_rect_),
this->quad_rect_.size(), false, RGBA_8888,
- this->quad_rect_, 1.f, green_pile);
+ this->quad_rect_, 1.f, green_raster_source);
SCOPED_TRACE("IntersectingPictureQuadsPass");
this->template AppendBackgroundAndRunTest<PictureDrawQuad>(
FuzzyPixelComparator(false, 2.f, 0.f, 256.f, 256, 0.f));
@@ -843,17 +848,15 @@ TYPED_TEST(IntersectingQuadGLPixelTest, YUVVideoQuads) {
(this->quad_rect_.height() / 2) & ~0xF);
CreateTestYUVVideoDrawQuad_TwoColor(
- this->front_quad_state_, media::VideoFrame::YV12,
- media::VideoFrame::COLOR_SPACE_JPEG, false,
- gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), this->quad_rect_.size(),
- this->quad_rect_, 0, 128, 128, inner_rect, 29, 255, 107,
- this->render_pass_.get(), this->video_resource_updater_.get(),
+ this->front_quad_state_, media::PIXEL_FORMAT_YV12,
+ media::COLOR_SPACE_JPEG, false, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f),
+ this->quad_rect_.size(), this->quad_rect_, 0, 128, 128, inner_rect, 29,
+ 255, 107, this->render_pass_.get(), this->video_resource_updater_.get(),
this->resource_provider_.get());
CreateTestYUVVideoDrawQuad_TwoColor(
- this->back_quad_state_, media::VideoFrame::YV12,
- media::VideoFrame::COLOR_SPACE_JPEG, false,
- gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), this->quad_rect_.size(),
+ this->back_quad_state_, media::PIXEL_FORMAT_YV12, media::COLOR_SPACE_JPEG,
+ false, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), this->quad_rect_.size(),
this->quad_rect_, 149, 43, 21, inner_rect, 0, 128, 128,
this->render_pass_.get(), this->video_resource_updater2_.get(),
this->resource_provider_.get());
@@ -930,8 +933,8 @@ TEST_F(GLRendererPixelTest, NonPremultipliedTextureWithBackground) {
class VideoGLRendererPixelTest : public GLRendererPixelTest {
protected:
- void CreateEdgeBleedPass(media::VideoFrame::Format format,
- media::VideoFrame::ColorSpace color_space,
+ void CreateEdgeBleedPass(media::VideoPixelFormat format,
+ media::ColorSpace color_space,
RenderPassList* pass_list) {
gfx::Rect rect(200, 200);
@@ -985,7 +988,7 @@ TEST_F(VideoGLRendererPixelTest, SimpleYUVRect) {
SharedQuadState* shared_state =
CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
- CreateTestYUVVideoDrawQuad_Striped(shared_state, media::VideoFrame::YV12,
+ CreateTestYUVVideoDrawQuad_Striped(shared_state, media::PIXEL_FORMAT_YV12,
false, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f),
pass.get(), video_resource_updater_.get(),
rect, rect, resource_provider_.get());
@@ -1010,7 +1013,7 @@ TEST_F(VideoGLRendererPixelTest, ClippedYUVRect) {
SharedQuadState* shared_state =
CreateTestSharedQuadState(gfx::Transform(), viewport, pass.get());
- CreateTestYUVVideoDrawQuad_Striped(shared_state, media::VideoFrame::YV12,
+ CreateTestYUVVideoDrawQuad_Striped(shared_state, media::PIXEL_FORMAT_YV12,
false, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f),
pass.get(), video_resource_updater_.get(),
draw_rect, viewport,
@@ -1034,7 +1037,7 @@ TEST_F(VideoGLRendererPixelTest, OffsetYUVRect) {
// Intentionally sets frame format to I420 for testing coverage.
CreateTestYUVVideoDrawQuad_Striped(
- shared_state, media::VideoFrame::I420, false,
+ shared_state, media::PIXEL_FORMAT_I420, false,
gfx::RectF(0.125f, 0.25f, 0.75f, 0.5f), pass.get(),
video_resource_updater_.get(), rect, rect, resource_provider_.get());
@@ -1058,9 +1061,8 @@ TEST_F(VideoGLRendererPixelTest, SimpleYUVRectBlack) {
// In MPEG color range YUV values of (15,128,128) should produce black.
CreateTestYUVVideoDrawQuad_Solid(
- shared_state, media::VideoFrame::YV12,
- media::VideoFrame::COLOR_SPACE_UNSPECIFIED, false,
- gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), 15, 128, 128, pass.get(),
+ shared_state, media::PIXEL_FORMAT_YV12, media::COLOR_SPACE_UNSPECIFIED,
+ false, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), 15, 128, 128, pass.get(),
video_resource_updater_.get(), rect, rect, resource_provider_.get());
RenderPassList pass_list;
@@ -1084,8 +1086,7 @@ TEST_F(VideoGLRendererPixelTest, SimpleYUVJRect) {
// YUV of (149,43,21) should be green (0,255,0) in RGB.
CreateTestYUVVideoDrawQuad_Solid(
- shared_state, media::VideoFrame::YV12,
- media::VideoFrame::COLOR_SPACE_JPEG, false,
+ shared_state, media::PIXEL_FORMAT_YV12, media::COLOR_SPACE_JPEG, false,
gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), 149, 43, 21, pass.get(),
video_resource_updater_.get(), rect, rect, resource_provider_.get());
@@ -1101,8 +1102,8 @@ TEST_F(VideoGLRendererPixelTest, SimpleYUVJRect) {
// tex coord rect is only a partial subrectangle of the coded contents.
TEST_F(VideoGLRendererPixelTest, YUVEdgeBleed) {
RenderPassList pass_list;
- CreateEdgeBleedPass(media::VideoFrame::YV12,
- media::VideoFrame::COLOR_SPACE_JPEG, &pass_list);
+ CreateEdgeBleedPass(media::PIXEL_FORMAT_YV12, media::COLOR_SPACE_JPEG,
+ &pass_list);
EXPECT_TRUE(this->RunPixelTest(&pass_list,
base::FilePath(FILE_PATH_LITERAL("green.png")),
FuzzyPixelOffByOneComparator(true)));
@@ -1110,8 +1111,8 @@ TEST_F(VideoGLRendererPixelTest, YUVEdgeBleed) {
TEST_F(VideoGLRendererPixelTest, YUVAEdgeBleed) {
RenderPassList pass_list;
- CreateEdgeBleedPass(media::VideoFrame::YV12A,
- media::VideoFrame::COLOR_SPACE_UNSPECIFIED, &pass_list);
+ CreateEdgeBleedPass(media::PIXEL_FORMAT_YV12A, media::COLOR_SPACE_UNSPECIFIED,
+ &pass_list);
EXPECT_TRUE(this->RunPixelTest(&pass_list,
base::FilePath(FILE_PATH_LITERAL("green.png")),
FuzzyPixelOffByOneComparator(true)));
@@ -1128,8 +1129,7 @@ TEST_F(VideoGLRendererPixelTest, SimpleYUVJRectGrey) {
// Dark grey in JPEG color range (in MPEG, this is black).
CreateTestYUVVideoDrawQuad_Solid(
- shared_state, media::VideoFrame::YV12,
- media::VideoFrame::COLOR_SPACE_JPEG, false,
+ shared_state, media::PIXEL_FORMAT_YV12, media::COLOR_SPACE_JPEG, false,
gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), 15, 128, 128, pass.get(),
video_resource_updater_.get(), rect, rect, resource_provider_.get());
@@ -1151,7 +1151,7 @@ TEST_F(VideoGLRendererPixelTest, SimpleYUVARect) {
SharedQuadState* shared_state =
CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
- CreateTestYUVVideoDrawQuad_Striped(shared_state, media::VideoFrame::YV12A,
+ CreateTestYUVVideoDrawQuad_Striped(shared_state, media::PIXEL_FORMAT_YV12A,
false, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f),
pass.get(), video_resource_updater_.get(),
rect, rect, resource_provider_.get());
@@ -1178,7 +1178,7 @@ TEST_F(VideoGLRendererPixelTest, FullyTransparentYUVARect) {
SharedQuadState* shared_state =
CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
- CreateTestYUVVideoDrawQuad_Striped(shared_state, media::VideoFrame::YV12A,
+ CreateTestYUVVideoDrawQuad_Striped(shared_state, media::PIXEL_FORMAT_YV12A,
true, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f),
pass.get(), video_resource_updater_.get(),
rect, rect, resource_provider_.get());
@@ -2174,7 +2174,6 @@ TEST_F(GLRendererPixelTest, AntiAliasingPerspective) {
}
TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadIdentityScale) {
- gfx::Size pile_tile_size(1000, 1000);
gfx::Rect viewport(this->device_viewport_size_);
// TODO(enne): the renderer should figure this out on its own.
ResourceFormat texture_format = RGBA_8888;
@@ -2190,8 +2189,9 @@ TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadIdentityScale) {
gfx::Rect blue_rect(gfx::Size(100, 100));
gfx::Rect blue_clip_rect(gfx::Point(50, 50), gfx::Size(50, 50));
- scoped_ptr<FakePicturePile> blue_recording =
- FakePicturePile::CreateFilledPile(pile_tile_size, blue_rect.size());
+ scoped_ptr<FakeDisplayListRecordingSource> blue_recording =
+ FakeDisplayListRecordingSource::CreateFilledRecordingSource(
+ blue_rect.size());
SkPaint red_paint;
red_paint.setColor(SK_ColorRED);
blue_recording->add_draw_rect_with_paint(blue_rect, red_paint);
@@ -2200,17 +2200,18 @@ TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadIdentityScale) {
blue_recording->add_draw_rect_with_paint(blue_clip_rect, blue_paint);
blue_recording->Rerecord();
- scoped_refptr<FakePicturePileImpl> blue_pile =
- FakePicturePileImpl::CreateFromPile(blue_recording.get(), nullptr);
+ scoped_refptr<FakeDisplayListRasterSource> blue_raster_source =
+ FakeDisplayListRasterSource::CreateFromRecordingSource(
+ blue_recording.get(), false);
- gfx::Transform blue_quad_to_target_transform;
gfx::Vector2d offset(viewport.bottom_right() - blue_rect.bottom_right());
+ gfx::Transform blue_quad_to_target_transform;
blue_quad_to_target_transform.Translate(offset.x(), offset.y());
- gfx::RectF blue_scissor_rect = blue_clip_rect;
- blue_quad_to_target_transform.TransformRect(&blue_scissor_rect);
- SharedQuadState* blue_shared_state = CreateTestSharedQuadStateClipped(
- blue_quad_to_target_transform, blue_rect,
- gfx::ToEnclosingRect(blue_scissor_rect), pass.get());
+ gfx::Rect blue_target_clip_rect = MathUtil::MapEnclosingClippedRect(
+ blue_quad_to_target_transform, blue_clip_rect);
+ SharedQuadState* blue_shared_state =
+ CreateTestSharedQuadStateClipped(blue_quad_to_target_transform, blue_rect,
+ blue_target_clip_rect, pass.get());
PictureDrawQuad* blue_quad = pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
@@ -2218,17 +2219,19 @@ TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadIdentityScale) {
viewport, // Intentionally bigger than clip.
gfx::Rect(), viewport, gfx::RectF(viewport),
viewport.size(), nearest_neighbor, texture_format, viewport,
- 1.f, blue_pile.get());
+ 1.f, blue_raster_source.Pass());
// One viewport-filling green quad.
- scoped_ptr<FakePicturePile> green_recording =
- FakePicturePile::CreateFilledPile(pile_tile_size, viewport.size());
+ scoped_ptr<FakeDisplayListRecordingSource> green_recording =
+ FakeDisplayListRecordingSource::CreateFilledRecordingSource(
+ viewport.size());
SkPaint green_paint;
green_paint.setColor(SK_ColorGREEN);
green_recording->add_draw_rect_with_paint(viewport, green_paint);
green_recording->Rerecord();
- scoped_refptr<FakePicturePileImpl> green_pile =
- FakePicturePileImpl::CreateFromPile(green_recording.get(), nullptr);
+ scoped_refptr<FakeDisplayListRasterSource> green_raster_source =
+ FakeDisplayListRasterSource::CreateFromRecordingSource(
+ green_recording.get(), false);
gfx::Transform green_quad_to_target_transform;
SharedQuadState* green_shared_state = CreateTestSharedQuadState(
@@ -2239,7 +2242,7 @@ TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadIdentityScale) {
green_quad->SetNew(green_shared_state, viewport, gfx::Rect(), viewport,
gfx::RectF(0.f, 0.f, 1.f, 1.f), viewport.size(),
nearest_neighbor, texture_format, viewport, 1.f,
- green_pile.get());
+ green_raster_source.Pass());
RenderPassList pass_list;
pass_list.push_back(pass.Pass());
@@ -2252,7 +2255,6 @@ TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadIdentityScale) {
// Not WithSkiaGPUBackend since that path currently requires tiles for opacity.
TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadOpacity) {
- gfx::Size pile_tile_size(1000, 1000);
gfx::Rect viewport(this->device_viewport_size_);
ResourceFormat texture_format = RGBA_8888;
bool nearest_neighbor = false;
@@ -2263,14 +2265,16 @@ TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadOpacity) {
CreateTestRenderPass(id, viewport, transform_to_root);
// One viewport-filling 0.5-opacity green quad.
- scoped_ptr<FakePicturePile> green_recording =
- FakePicturePile::CreateFilledPile(pile_tile_size, viewport.size());
+ scoped_ptr<FakeDisplayListRecordingSource> green_recording =
+ FakeDisplayListRecordingSource::CreateFilledRecordingSource(
+ viewport.size());
SkPaint green_paint;
green_paint.setColor(SK_ColorGREEN);
green_recording->add_draw_rect_with_paint(viewport, green_paint);
green_recording->Rerecord();
- scoped_refptr<FakePicturePileImpl> green_pile =
- FakePicturePileImpl::CreateFromPile(green_recording.get(), nullptr);
+ scoped_refptr<FakeDisplayListRasterSource> green_raster_source =
+ FakeDisplayListRasterSource::CreateFromRecordingSource(
+ green_recording.get(), false);
gfx::Transform green_quad_to_target_transform;
SharedQuadState* green_shared_state = CreateTestSharedQuadState(
@@ -2281,17 +2285,19 @@ TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadOpacity) {
pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
green_quad->SetNew(green_shared_state, viewport, gfx::Rect(), viewport,
gfx::RectF(0, 0, 1, 1), viewport.size(), nearest_neighbor,
- texture_format, viewport, 1.f, green_pile.get());
+ texture_format, viewport, 1.f, green_raster_source.get());
// One viewport-filling white quad.
- scoped_ptr<FakePicturePile> white_recording =
- FakePicturePile::CreateFilledPile(pile_tile_size, viewport.size());
+ scoped_ptr<FakeDisplayListRecordingSource> white_recording =
+ FakeDisplayListRecordingSource::CreateFilledRecordingSource(
+ viewport.size());
SkPaint white_paint;
white_paint.setColor(SK_ColorWHITE);
white_recording->add_draw_rect_with_paint(viewport, white_paint);
white_recording->Rerecord();
- scoped_refptr<FakePicturePileImpl> white_pile =
- FakePicturePileImpl::CreateFromPile(white_recording.get(), nullptr);
+ scoped_refptr<FakeDisplayListRasterSource> white_raster_source =
+ FakeDisplayListRasterSource::CreateFromRecordingSource(
+ white_recording.get(), false);
gfx::Transform white_quad_to_target_transform;
SharedQuadState* white_shared_state = CreateTestSharedQuadState(
@@ -2301,7 +2307,7 @@ TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadOpacity) {
pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
white_quad->SetNew(white_shared_state, viewport, gfx::Rect(), viewport,
gfx::RectF(0, 0, 1, 1), viewport.size(), nearest_neighbor,
- texture_format, viewport, 1.f, white_pile.get());
+ texture_format, viewport, 1.f, white_raster_source.Pass());
RenderPassList pass_list;
pass_list.push_back(pass.Pass());
@@ -2334,7 +2340,6 @@ TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadDisableImageFiltering) {
if (!IsSoftwareRenderer<TypeParam>())
return;
- gfx::Size pile_tile_size(1000, 1000);
gfx::Rect viewport(this->device_viewport_size_);
ResourceFormat texture_format = RGBA_8888;
bool nearest_neighbor = false;
@@ -2344,25 +2349,26 @@ TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadDisableImageFiltering) {
scoped_ptr<RenderPass> pass =
CreateTestRenderPass(id, viewport, transform_to_root);
- SkBitmap bitmap;
- bitmap.allocN32Pixels(2, 2);
- {
- SkAutoLockPixels lock(bitmap);
- SkCanvas canvas(bitmap);
- canvas.drawPoint(0, 0, SK_ColorGREEN);
- canvas.drawPoint(0, 1, SK_ColorBLUE);
- canvas.drawPoint(1, 0, SK_ColorBLUE);
- canvas.drawPoint(1, 1, SK_ColorGREEN);
- }
-
- scoped_ptr<FakePicturePile> recording =
- FakePicturePile::CreateFilledPile(pile_tile_size, viewport.size());
+ skia::RefPtr<SkSurface> surface =
+ skia::AdoptRef(SkSurface::NewRasterN32Premul(2, 2));
+ ASSERT_NE(surface, nullptr);
+ SkCanvas* canvas = surface->getCanvas();
+ canvas->drawPoint(0, 0, SK_ColorGREEN);
+ canvas->drawPoint(0, 1, SK_ColorBLUE);
+ canvas->drawPoint(1, 0, SK_ColorBLUE);
+ canvas->drawPoint(1, 1, SK_ColorGREEN);
+ skia::RefPtr<SkImage> image = skia::AdoptRef(surface->newImageSnapshot());
+
+ scoped_ptr<FakeDisplayListRecordingSource> recording =
+ FakeDisplayListRecordingSource::CreateFilledRecordingSource(
+ viewport.size());
SkPaint paint;
paint.setFilterQuality(kLow_SkFilterQuality);
- recording->add_draw_bitmap_with_paint(bitmap, gfx::Point(), paint);
+ recording->add_draw_image_with_paint(image.get(), gfx::Point(), paint);
recording->Rerecord();
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFromPile(recording.get(), nullptr);
+ scoped_refptr<FakeDisplayListRasterSource> raster_source =
+ FakeDisplayListRasterSource::CreateFromRecordingSource(recording.get(),
+ false);
gfx::Transform quad_to_target_transform;
SharedQuadState* shared_state =
@@ -2371,7 +2377,7 @@ TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadDisableImageFiltering) {
PictureDrawQuad* quad = pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
quad->SetNew(shared_state, viewport, gfx::Rect(), viewport,
gfx::RectF(0, 0, 2, 2), viewport.size(), nearest_neighbor,
- texture_format, viewport, 1.f, pile.get());
+ texture_format, viewport, 1.f, raster_source.Pass());
RenderPassList pass_list;
pass_list.push_back(pass.Pass());
@@ -2386,7 +2392,6 @@ TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadDisableImageFiltering) {
// This disables filtering by setting |nearest_neighbor| on the PictureDrawQuad.
TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadNearestNeighbor) {
- gfx::Size pile_tile_size(1000, 1000);
gfx::Rect viewport(this->device_viewport_size_);
ResourceFormat texture_format = RGBA_8888;
bool nearest_neighbor = true;
@@ -2396,25 +2401,26 @@ TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadNearestNeighbor) {
scoped_ptr<RenderPass> pass =
CreateTestRenderPass(id, viewport, transform_to_root);
- SkBitmap bitmap;
- bitmap.allocN32Pixels(2, 2);
- {
- SkAutoLockPixels lock(bitmap);
- SkCanvas canvas(bitmap);
- canvas.drawPoint(0, 0, SK_ColorGREEN);
- canvas.drawPoint(0, 1, SK_ColorBLUE);
- canvas.drawPoint(1, 0, SK_ColorBLUE);
- canvas.drawPoint(1, 1, SK_ColorGREEN);
- }
-
- scoped_ptr<FakePicturePile> recording =
- FakePicturePile::CreateFilledPile(pile_tile_size, viewport.size());
+ skia::RefPtr<SkSurface> surface =
+ skia::AdoptRef(SkSurface::NewRasterN32Premul(2, 2));
+ ASSERT_NE(surface, nullptr);
+ SkCanvas* canvas = surface->getCanvas();
+ canvas->drawPoint(0, 0, SK_ColorGREEN);
+ canvas->drawPoint(0, 1, SK_ColorBLUE);
+ canvas->drawPoint(1, 0, SK_ColorBLUE);
+ canvas->drawPoint(1, 1, SK_ColorGREEN);
+ skia::RefPtr<SkImage> image = skia::AdoptRef(surface->newImageSnapshot());
+
+ scoped_ptr<FakeDisplayListRecordingSource> recording =
+ FakeDisplayListRecordingSource::CreateFilledRecordingSource(
+ viewport.size());
SkPaint paint;
paint.setFilterQuality(kLow_SkFilterQuality);
- recording->add_draw_bitmap_with_paint(bitmap, gfx::Point(), paint);
+ recording->add_draw_image_with_paint(image.get(), gfx::Point(), paint);
recording->Rerecord();
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFromPile(recording.get(), nullptr);
+ scoped_refptr<FakeDisplayListRasterSource> raster_source =
+ FakeDisplayListRasterSource::CreateFromRecordingSource(recording.get(),
+ false);
gfx::Transform quad_to_target_transform;
SharedQuadState* shared_state =
@@ -2423,7 +2429,7 @@ TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadNearestNeighbor) {
PictureDrawQuad* quad = pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
quad->SetNew(shared_state, viewport, gfx::Rect(), viewport,
gfx::RectF(0, 0, 2, 2), viewport.size(), nearest_neighbor,
- texture_format, viewport, 1.f, pile.get());
+ texture_format, viewport, 1.f, raster_source.Pass());
RenderPassList pass_list;
pass_list.push_back(pass.Pass());
@@ -2473,7 +2479,7 @@ TYPED_TEST(RendererPixelTest, TileDrawQuadNearestNeighbor) {
TileDrawQuad* quad = pass->CreateAndAppendDrawQuad<TileDrawQuad>();
quad->SetNew(shared_state, viewport, gfx::Rect(), viewport, resource,
- gfx::Rect(tile_size), tile_size, swizzle_contents,
+ gfx::RectF(gfx::Rect(tile_size)), tile_size, swizzle_contents,
nearest_neighbor);
RenderPassList pass_list;
@@ -2592,7 +2598,6 @@ TYPED_TEST(SoftwareRendererPixelTest, TextureDrawQuadLinear) {
}
TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadNonIdentityScale) {
- gfx::Size pile_tile_size(1000, 1000);
gfx::Rect viewport(this->device_viewport_size_);
// TODO(enne): the renderer should figure this out on its own.
ResourceFormat texture_format = RGBA_8888;
@@ -2611,8 +2616,9 @@ TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadNonIdentityScale) {
gfx::Rect green_rect1(gfx::Point(80, 0), gfx::Size(20, 100));
gfx::Rect green_rect2(gfx::Point(0, 80), gfx::Size(100, 20));
- scoped_ptr<FakePicturePile> green_recording =
- FakePicturePile::CreateFilledPile(pile_tile_size, viewport.size());
+ scoped_ptr<FakeDisplayListRecordingSource> green_recording =
+ FakeDisplayListRecordingSource::CreateFilledRecordingSource(
+ viewport.size());
SkPaint red_paint;
red_paint.setColor(SK_ColorRED);
@@ -2622,8 +2628,9 @@ TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadNonIdentityScale) {
green_recording->add_draw_rect_with_paint(green_rect1, green_paint);
green_recording->add_draw_rect_with_paint(green_rect2, green_paint);
green_recording->Rerecord();
- scoped_refptr<FakePicturePileImpl> green_pile =
- FakePicturePileImpl::CreateFromPile(green_recording.get(), nullptr);
+ scoped_refptr<FakeDisplayListRasterSource> green_raster_source =
+ FakeDisplayListRasterSource::CreateFromRecordingSource(
+ green_recording.get(), false);
SharedQuadState* top_right_green_shared_quad_state =
CreateTestSharedQuadState(green_quad_to_target_transform, viewport,
@@ -2631,17 +2638,18 @@ TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadNonIdentityScale) {
PictureDrawQuad* green_quad1 =
pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
- green_quad1->SetNew(top_right_green_shared_quad_state, green_rect1,
- gfx::Rect(), green_rect1, gfx::RectF(green_rect1.size()),
- green_rect1.size(), nearest_neighbor, texture_format,
- green_rect1, 1.f, green_pile.get());
+ green_quad1->SetNew(
+ top_right_green_shared_quad_state, green_rect1, gfx::Rect(), green_rect1,
+ gfx::RectF(gfx::SizeF(green_rect1.size())), green_rect1.size(),
+ nearest_neighbor, texture_format, green_rect1, 1.f, green_raster_source);
PictureDrawQuad* green_quad2 =
pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
green_quad2->SetNew(top_right_green_shared_quad_state, green_rect2,
- gfx::Rect(), green_rect2, gfx::RectF(green_rect2.size()),
+ gfx::Rect(), green_rect2,
+ gfx::RectF(gfx::SizeF(green_rect2.size())),
green_rect2.size(), nearest_neighbor, texture_format,
- green_rect2, 1.f, green_pile.get());
+ green_rect2, 1.f, green_raster_source.Pass());
// Add a green clipped checkerboard in the bottom right to help test
// interleaving picture quad content and solid color content.
@@ -2676,8 +2684,9 @@ TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadNonIdentityScale) {
blue_layer_rect1.Inset(inset, inset, inset, inset);
blue_layer_rect2.Inset(inset, inset, inset, inset);
- scoped_ptr<FakePicturePile> recording =
- FakePicturePile::CreateFilledPile(pile_tile_size, layer_rect.size());
+ scoped_ptr<FakeDisplayListRecordingSource> recording =
+ FakeDisplayListRecordingSource::CreateFilledRecordingSource(
+ layer_rect.size());
Region outside(layer_rect);
outside.Subtract(gfx::ToEnclosingRect(union_layer_rect));
@@ -2687,11 +2696,12 @@ TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadNonIdentityScale) {
SkPaint blue_paint;
blue_paint.setColor(SK_ColorBLUE);
- recording->add_draw_rect_with_paint(blue_layer_rect1, blue_paint);
- recording->add_draw_rect_with_paint(blue_layer_rect2, blue_paint);
+ recording->add_draw_rectf_with_paint(blue_layer_rect1, blue_paint);
+ recording->add_draw_rectf_with_paint(blue_layer_rect2, blue_paint);
recording->Rerecord();
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFromPile(recording.get(), nullptr);
+ scoped_refptr<FakeDisplayListRasterSource> raster_source =
+ FakeDisplayListRasterSource::CreateFromRecordingSource(recording.get(),
+ false);
gfx::Rect content_rect(
gfx::ScaleToEnclosingRect(layer_rect, contents_scale));
@@ -2710,7 +2720,7 @@ TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadNonIdentityScale) {
blue_quad->SetNew(blue_shared_state, quad_content_rect, gfx::Rect(),
quad_content_rect, gfx::RectF(quad_content_rect),
content_union_rect.size(), nearest_neighbor, texture_format,
- content_union_rect, contents_scale, pile.get());
+ content_union_rect, contents_scale, raster_source.Pass());
// Fill left half of viewport with green.
gfx::Transform half_green_quad_to_target_transform;
@@ -2942,109 +2952,6 @@ TYPED_TEST(RendererPixelTest, WrapModeRepeat) {
FuzzyPixelOffByOneComparator(true)));
}
-TYPED_TEST(RendererPixelTest, Checkerboards) {
- gfx::Rect rect(this->device_viewport_size_);
-
- RenderPassId id(1, 1);
- scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
-
- SharedQuadState* shared_state =
- CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
-
- // The color's alpha value is not used.
- SkColor color1 = SK_ColorGREEN;
- color1 = SkColorSetA(color1, 0);
- SkColor color2 = SK_ColorBLUE;
- color2 = SkColorSetA(color2, 0);
-
- gfx::Rect content_rect(rect);
-
- gfx::Rect top_left(content_rect);
- gfx::Rect top_right(content_rect);
- gfx::Rect bottom_left(content_rect);
- gfx::Rect bottom_right(content_rect);
- // The format is Inset(left, top, right, bottom).
- top_left.Inset(0, 0, content_rect.width() / 2, content_rect.height() / 2);
- top_right.Inset(content_rect.width() / 2, 0, 0, content_rect.height() / 2);
- bottom_left.Inset(0, content_rect.height() / 2, content_rect.width() / 2, 0);
- bottom_right.Inset(content_rect.width() / 2, content_rect.height() / 2, 0, 0);
-
- // Appends checkerboard quads with a scale of 1.
- CheckerboardDrawQuad* quad =
- pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
- quad->SetNew(shared_state, top_left, top_left, color1, 1.f);
- quad = pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
- quad->SetNew(shared_state, top_right, top_right, color2, 1.f);
- quad = pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
- quad->SetNew(shared_state, bottom_left, bottom_left, color2, 1.f);
- quad = pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
- quad->SetNew(shared_state, bottom_right, bottom_right, color1, 1.f);
-
- RenderPassList pass_list;
- pass_list.push_back(pass.Pass());
-
- base::FilePath::StringType path =
- IsSoftwareRenderer<TypeParam>()
- ? FILE_PATH_LITERAL("four_blue_green_checkers.png")
- : FILE_PATH_LITERAL("checkers.png");
- EXPECT_TRUE(this->RunPixelTest(&pass_list, base::FilePath(path),
- ExactPixelComparator(true)));
-}
-
-TYPED_TEST(RendererPixelTest, CheckerboardsScaled) {
- gfx::Rect rect(this->device_viewport_size_);
-
- RenderPassId id(1, 1);
- scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
-
- gfx::Transform scale;
- scale.Scale(2.f, 2.f);
-
- SharedQuadState* shared_state =
- CreateTestSharedQuadState(scale, rect, pass.get());
-
- // The color's alpha value is not used.
- SkColor color1 = SK_ColorGREEN;
- color1 = SkColorSetA(color1, 0);
- SkColor color2 = SK_ColorBLUE;
- color2 = SkColorSetA(color2, 0);
-
- gfx::Rect content_rect(rect);
- content_rect.Inset(0, 0, rect.width() / 2, rect.height() / 2);
-
- gfx::Rect top_left(content_rect);
- gfx::Rect top_right(content_rect);
- gfx::Rect bottom_left(content_rect);
- gfx::Rect bottom_right(content_rect);
- // The format is Inset(left, top, right, bottom).
- top_left.Inset(0, 0, content_rect.width() / 2, content_rect.height() / 2);
- top_right.Inset(content_rect.width() / 2, 0, 0, content_rect.height() / 2);
- bottom_left.Inset(0, content_rect.height() / 2, content_rect.width() / 2, 0);
- bottom_right.Inset(content_rect.width() / 2, content_rect.height() / 2, 0, 0);
-
- // Appends checkerboard quads with a scale of 2, and a shared quad state
- // with a scale of 2. The checkers should be scaled by 2 * 2 = 4.
- CheckerboardDrawQuad* quad =
- pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
- quad->SetNew(shared_state, top_left, top_left, color1, 2.f);
- quad = pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
- quad->SetNew(shared_state, top_right, top_right, color2, 2.f);
- quad = pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
- quad->SetNew(shared_state, bottom_left, bottom_left, color2, 2.f);
- quad = pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
- quad->SetNew(shared_state, bottom_right, bottom_right, color1, 2.f);
-
- RenderPassList pass_list;
- pass_list.push_back(pass.Pass());
-
- base::FilePath::StringType path =
- IsSoftwareRenderer<TypeParam>()
- ? FILE_PATH_LITERAL("four_blue_green_checkers.png")
- : FILE_PATH_LITERAL("checkers_big.png");
- EXPECT_TRUE(this->RunPixelTest(&pass_list, base::FilePath(path),
- ExactPixelComparator(true)));
-}
-
#endif // !defined(OS_ANDROID)
} // namespace
diff --git a/chromium/cc/output/renderer_settings.cc b/chromium/cc/output/renderer_settings.cc
index 0c0a10d1e01..35415f19866 100644
--- a/chromium/cc/output/renderer_settings.cc
+++ b/chromium/cc/output/renderer_settings.cc
@@ -17,12 +17,12 @@ RendererSettings::RendererSettings()
partial_swap_enabled(false),
finish_rendering_on_resize(false),
should_clear_root_render_pass(true),
- disable_gpu_vsync(false),
+ disable_display_vsync(false),
+ delay_releasing_overlay_resources(false),
refresh_rate(60.0),
highp_threshold_min(0),
use_rgba_4444_textures(false),
- texture_id_allocation_chunk_size(64) {
-}
+ texture_id_allocation_chunk_size(64) {}
RendererSettings::~RendererSettings() {
}
diff --git a/chromium/cc/output/renderer_settings.h b/chromium/cc/output/renderer_settings.h
index 4757f8d5571..48aa13d0054 100644
--- a/chromium/cc/output/renderer_settings.h
+++ b/chromium/cc/output/renderer_settings.h
@@ -21,7 +21,8 @@ class CC_EXPORT RendererSettings {
bool partial_swap_enabled;
bool finish_rendering_on_resize;
bool should_clear_root_render_pass;
- bool disable_gpu_vsync;
+ bool disable_display_vsync;
+ bool delay_releasing_overlay_resources;
double refresh_rate;
int highp_threshold_min;
bool use_rgba_4444_textures;
diff --git a/chromium/cc/output/shader.cc b/chromium/cc/output/shader.cc
index 15ad7e05fa7..a4ee1bbfc6b 100644
--- a/chromium/cc/output/shader.cc
+++ b/chromium/cc/output/shader.cc
@@ -772,7 +772,7 @@ FragmentTexBlendMode::FragmentTexBlendMode()
}
std::string FragmentTexBlendMode::SetBlendModeFunctions(
- std::string shader_string) const {
+ const std::string& shader_string) const {
if (shader_string.find("ApplyBlendMode") == std::string::npos)
return shader_string;
@@ -2253,64 +2253,4 @@ std::string FragmentShaderColorAA::GetShaderBody() {
});
}
-FragmentShaderCheckerboard::FragmentShaderCheckerboard()
- : alpha_location_(-1),
- tex_transform_location_(-1),
- frequency_location_(-1) {
-}
-
-void FragmentShaderCheckerboard::Init(GLES2Interface* context,
- unsigned program,
- int* base_uniform_index) {
- static const char* uniforms[] = {
- "alpha", "texTransform", "frequency", "color",
- };
- int locations[arraysize(uniforms)];
-
- GetProgramUniformLocations(context,
- program,
- arraysize(uniforms),
- uniforms,
- locations,
- base_uniform_index);
- alpha_location_ = locations[0];
- tex_transform_location_ = locations[1];
- frequency_location_ = locations[2];
- color_location_ = locations[3];
-}
-
-std::string FragmentShaderCheckerboard::GetShaderString(
- TexCoordPrecision precision,
- SamplerType sampler) const {
- return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
-}
-
-std::string FragmentShaderCheckerboard::GetShaderHead() {
- return SHADER0([]() {
- precision mediump float;
- precision mediump int;
- varying vec2 v_texCoord;
- uniform float alpha;
- uniform float frequency;
- uniform vec4 texTransform;
- uniform vec4 color;
- });
-}
-
-std::string FragmentShaderCheckerboard::GetShaderBody() {
- // Shader based on Example 13-17 of "OpenGL ES 2.0 Programming Guide"
- // by Munshi, Ginsburg, Shreiner.
- return SHADER0([]() {
- void main() {
- vec4 color1 = vec4(1.0, 1.0, 1.0, 1.0);
- vec4 color2 = color;
- vec2 texCoord =
- clamp(v_texCoord, 0.0, 1.0) * texTransform.zw + texTransform.xy;
- vec2 coord = mod(floor(texCoord * frequency * 2.0), 2.0);
- float picker = abs(coord.x - coord.y); // NOLINT
- gl_FragColor = mix(color1, color2, picker) * alpha;
- }
- });
-}
-
} // namespace cc
diff --git a/chromium/cc/output/shader.h b/chromium/cc/output/shader.h
index d692a123cd7..448ff07a8b2 100644
--- a/chromium/cc/output/shader.h
+++ b/chromium/cc/output/shader.h
@@ -371,7 +371,7 @@ class FragmentTexBlendMode {
protected:
FragmentTexBlendMode();
- std::string SetBlendModeFunctions(std::string shader_string) const;
+ std::string SetBlendModeFunctions(const std::string& shader_string) const;
int backdrop_location_;
int original_backdrop_location_;
@@ -868,31 +868,6 @@ class FragmentShaderColorAA : public FragmentTexBlendMode {
DISALLOW_COPY_AND_ASSIGN(FragmentShaderColorAA);
};
-class FragmentShaderCheckerboard : public FragmentTexBlendMode {
- public:
- FragmentShaderCheckerboard();
- std::string GetShaderString(
- TexCoordPrecision precision, SamplerType sampler) const;
- static std::string GetShaderHead();
- static std::string GetShaderBody();
-
- void Init(gpu::gles2::GLES2Interface* context,
- unsigned program,
- int* base_uniform_index);
- int alpha_location() const { return alpha_location_; }
- int tex_transform_location() const { return tex_transform_location_; }
- int frequency_location() const { return frequency_location_; }
- int color_location() const { return color_location_; }
-
- private:
- int alpha_location_;
- int tex_transform_location_;
- int frequency_location_;
- int color_location_;
-
- DISALLOW_COPY_AND_ASSIGN(FragmentShaderCheckerboard);
-};
-
} // namespace cc
#endif // CC_OUTPUT_SHADER_H_
diff --git a/chromium/cc/output/software_frame_data.cc b/chromium/cc/output/software_frame_data.cc
deleted file mode 100644
index 7fc380e7b64..00000000000
--- a/chromium/cc/output/software_frame_data.cc
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cc/output/software_frame_data.h"
-
-namespace cc {
-
-SoftwareFrameData::SoftwareFrameData() : id(0) {}
-
-SoftwareFrameData::~SoftwareFrameData() {}
-
-} // namespace cc
diff --git a/chromium/cc/output/software_frame_data.h b/chromium/cc/output/software_frame_data.h
deleted file mode 100644
index 9cb74efa6e9..00000000000
--- a/chromium/cc/output/software_frame_data.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CC_OUTPUT_SOFTWARE_FRAME_DATA_H_
-#define CC_OUTPUT_SOFTWARE_FRAME_DATA_H_
-
-#include "cc/base/cc_export.h"
-#include "cc/resources/shared_bitmap.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/geometry/size.h"
-
-namespace cc {
-
-class CC_EXPORT SoftwareFrameData {
- public:
- SoftwareFrameData();
- ~SoftwareFrameData();
-
- unsigned id;
- gfx::Size size;
- gfx::Rect damage_rect;
- SharedBitmapId bitmap_id;
-};
-
-} // namespace cc
-
-#endif // CC_OUTPUT_SOFTWARE_FRAME_DATA_H_
diff --git a/chromium/cc/output/software_output_device.cc b/chromium/cc/output/software_output_device.cc
index 3692224679d..07129387ad0 100644
--- a/chromium/cc/output/software_output_device.cc
+++ b/chromium/cc/output/software_output_device.cc
@@ -5,7 +5,6 @@
#include "cc/output/software_output_device.h"
#include "base/logging.h"
-#include "cc/output/software_frame_data.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "ui/gfx/vsync_provider.h"
@@ -31,21 +30,11 @@ void SoftwareOutputDevice::Resize(const gfx::Size& viewport_pixel_size,
}
SkCanvas* SoftwareOutputDevice::BeginPaint(const gfx::Rect& damage_rect) {
- DCHECK(surface_);
damage_rect_ = damage_rect;
- return surface_->getCanvas();
+ return surface_ ? surface_->getCanvas() : nullptr;
}
-void SoftwareOutputDevice::EndPaint(SoftwareFrameData* frame_data) {
- DCHECK(frame_data);
- frame_data->id = 0;
- frame_data->size = viewport_pixel_size_;
- frame_data->damage_rect = damage_rect_;
-}
-
-void SoftwareOutputDevice::ReclaimSoftwareFrame(unsigned id) {
- NOTIMPLEMENTED();
-}
+void SoftwareOutputDevice::EndPaint() {}
gfx::VSyncProvider* SoftwareOutputDevice::GetVSyncProvider() {
return vsync_provider_.get();
diff --git a/chromium/cc/output/software_output_device.h b/chromium/cc/output/software_output_device.h
index 45ce83117c7..127c70a5fae 100644
--- a/chromium/cc/output/software_output_device.h
+++ b/chromium/cc/output/software_output_device.h
@@ -23,8 +23,6 @@ class VSyncProvider;
namespace cc {
-class SoftwareFrameData;
-
// This is a "tear-off" class providing software drawing support to
// OutputSurface, such as to a platform-provided window framebuffer.
class CC_EXPORT SoftwareOutputDevice {
@@ -46,7 +44,7 @@ class CC_EXPORT SoftwareOutputDevice {
// Called on FinishDrawingFrame. The compositor will no longer mutate the the
// SkCanvas instance returned by |BeginPaint| and should discard any reference
// that it holds to it.
- virtual void EndPaint(SoftwareFrameData* frame_data);
+ virtual void EndPaint();
// Discard the backing buffer in the surface provided by this instance.
virtual void DiscardBackbuffer() {}
@@ -54,12 +52,6 @@ class CC_EXPORT SoftwareOutputDevice {
// Ensures that there is a backing buffer available on this instance.
virtual void EnsureBackbuffer() {}
- // TODO(skaslev) Remove this after UberCompositor lands.
- // Called in response to receiving a SwapBuffersAck. At this point, software
- // frame identified by id can be reused or discarded as it is no longer being
- // displayed.
- virtual void ReclaimSoftwareFrame(unsigned id);
-
// VSyncProvider used to update the timer used to schedule draws with the
// hardware vsync. Return NULL if a provider doesn't exist.
virtual gfx::VSyncProvider* GetVSyncProvider();
diff --git a/chromium/cc/output/software_renderer.cc b/chromium/cc/output/software_renderer.cc
index a8110efb4dc..ea980a854f6 100644
--- a/chromium/cc/output/software_renderer.cc
+++ b/chromium/cc/output/software_renderer.cc
@@ -13,7 +13,6 @@
#include "cc/output/output_surface.h"
#include "cc/output/render_surface_filters.h"
#include "cc/output/software_output_device.h"
-#include "cc/quads/checkerboard_draw_quad.h"
#include "cc/quads/debug_border_draw_quad.h"
#include "cc/quads/picture_draw_quad.h"
#include "cc/quads/render_pass_draw_quad.h"
@@ -25,6 +24,7 @@
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkImageFilter.h"
#include "third_party/skia/include/core/SkMatrix.h"
+#include "third_party/skia/include/core/SkPath.h"
#include "third_party/skia/include/core/SkPoint.h"
#include "third_party/skia/include/core/SkShader.h"
#include "third_party/skia/include/effects/SkLayerRasterizer.h"
@@ -102,8 +102,7 @@ const RendererCapabilitiesImpl& SoftwareRenderer::Capabilities() const {
void SoftwareRenderer::BeginDrawingFrame(DrawingFrame* frame) {
TRACE_EVENT0("cc", "SoftwareRenderer::BeginDrawingFrame");
- root_canvas_ = output_device_->BeginPaint(
- gfx::ToEnclosingRect(frame->root_damage_rect));
+ root_canvas_ = output_device_->BeginPaint(frame->root_damage_rect);
}
void SoftwareRenderer::FinishDrawingFrame(DrawingFrame* frame) {
@@ -113,22 +112,16 @@ void SoftwareRenderer::FinishDrawingFrame(DrawingFrame* frame) {
current_canvas_ = NULL;
root_canvas_ = NULL;
- current_frame_data_.reset(new SoftwareFrameData);
- output_device_->EndPaint(current_frame_data_.get());
+ output_device_->EndPaint();
}
void SoftwareRenderer::SwapBuffers(const CompositorFrameMetadata& metadata) {
TRACE_EVENT0("cc,benchmark", "SoftwareRenderer::SwapBuffers");
CompositorFrame compositor_frame;
compositor_frame.metadata = metadata;
- compositor_frame.software_frame_data = current_frame_data_.Pass();
output_surface_->SwapBuffers(&compositor_frame);
}
-void SoftwareRenderer::ReceiveSwapBuffersAck(const CompositorFrameAck& ack) {
- output_device_->ReclaimSoftwareFrame(ack.last_software_frame_id);
-}
-
bool SoftwareRenderer::FlippedFramebuffer(const DrawingFrame* frame) const {
return false;
}
@@ -143,6 +136,8 @@ void SoftwareRenderer::EnsureScissorTestDisabled() {
// rendering, but the underlying effect we want is to clear any existing
// clipRect on the current SkCanvas. This is done by setting clipRect to
// the viewport's dimensions.
+ if (!current_canvas_)
+ return;
is_scissor_enabled_ = false;
SkISize size = current_canvas_->getDeviceSize();
SetClipRect(gfx::Rect(size.width(), size.height()));
@@ -182,6 +177,8 @@ void SoftwareRenderer::SetScissorTestRect(const gfx::Rect& scissor_rect) {
}
void SoftwareRenderer::SetClipRect(const gfx::Rect& rect) {
+ if (!current_canvas_)
+ return;
// Skia applies the current matrix to clip rects so we reset it temporary.
SkMatrix current_matrix = current_canvas_->getTotalMatrix();
current_canvas_->resetMatrix();
@@ -190,6 +187,8 @@ void SoftwareRenderer::SetClipRect(const gfx::Rect& rect) {
}
void SoftwareRenderer::ClearCanvas(SkColor color) {
+ if (!current_canvas_)
+ return;
// SkCanvas::clear doesn't respect the current clipping region
// so we SkCanvas::drawColor instead if scissoring is active.
if (is_scissor_enabled_)
@@ -244,6 +243,8 @@ bool SoftwareRenderer::IsSoftwareResource(ResourceId resource_id) const {
void SoftwareRenderer::DoDrawQuad(DrawingFrame* frame,
const DrawQuad* quad,
const gfx::QuadF* draw_region) {
+ if (!current_canvas_)
+ return;
if (draw_region) {
current_canvas_->save();
}
@@ -252,7 +253,7 @@ void SoftwareRenderer::DoDrawQuad(DrawingFrame* frame,
gfx::Transform quad_rect_matrix;
QuadRectTransform(&quad_rect_matrix,
quad->shared_quad_state->quad_to_target_transform,
- quad->rect);
+ gfx::RectF(quad->rect));
gfx::Transform contents_device_transform =
frame->window_matrix * frame->projection_matrix * quad_rect_matrix;
contents_device_transform.FlattenTo2d();
@@ -302,14 +303,6 @@ void SoftwareRenderer::DoDrawQuad(DrawingFrame* frame,
}
switch (quad->material) {
- case DrawQuad::CHECKERBOARD:
- // TODO(enne) For now since checkerboards shouldn't be part of a 3D
- // context, clipping regions aren't supported so we skip drawing them
- // if this becomes the case.
- if (!draw_region) {
- DrawCheckerboardQuad(frame, CheckerboardDrawQuad::MaterialCast(quad));
- }
- break;
case DrawQuad::DEBUG_BORDER:
DrawDebugBorderQuad(frame, DebugBorderDrawQuad::MaterialCast(quad));
break;
@@ -348,16 +341,6 @@ void SoftwareRenderer::DoDrawQuad(DrawingFrame* frame,
}
}
-void SoftwareRenderer::DrawCheckerboardQuad(const DrawingFrame* frame,
- const CheckerboardDrawQuad* quad) {
- gfx::RectF visible_quad_vertex_rect = MathUtil::ScaleRectProportional(
- QuadVertexRect(), quad->rect, quad->visible_rect);
- current_paint_.setColor(quad->color);
- current_paint_.setAlpha(quad->shared_quad_state->opacity);
- current_canvas_->drawRect(gfx::RectFToSkRect(visible_quad_vertex_rect),
- current_paint_);
-}
-
void SoftwareRenderer::DrawDebugBorderQuad(const DrawingFrame* frame,
const DebugBorderDrawQuad* quad) {
// We need to apply the matrix manually to have pixel-sized stroke width.
@@ -412,7 +395,7 @@ void SoftwareRenderer::DrawPictureQuad(const DrawingFrame* frame,
void SoftwareRenderer::DrawSolidColorQuad(const DrawingFrame* frame,
const SolidColorDrawQuad* quad) {
gfx::RectF visible_quad_vertex_rect = MathUtil::ScaleRectProportional(
- QuadVertexRect(), quad->rect, quad->visible_rect);
+ QuadVertexRect(), gfx::RectF(quad->rect), gfx::RectF(quad->visible_rect));
current_paint_.setColor(quad->color);
current_paint_.setAlpha(quad->shared_quad_state->opacity *
SkColorGetA(quad->color));
@@ -437,11 +420,11 @@ void SoftwareRenderer::DrawTextureQuad(const DrawingFrame* frame,
quad->uv_bottom_right),
bitmap->width(),
bitmap->height());
- gfx::RectF visible_uv_rect =
- MathUtil::ScaleRectProportional(uv_rect, quad->rect, quad->visible_rect);
+ gfx::RectF visible_uv_rect = MathUtil::ScaleRectProportional(
+ uv_rect, gfx::RectF(quad->rect), gfx::RectF(quad->visible_rect));
SkRect sk_uv_rect = gfx::RectFToSkRect(visible_uv_rect);
gfx::RectF visible_quad_vertex_rect = MathUtil::ScaleRectProportional(
- QuadVertexRect(), quad->rect, quad->visible_rect);
+ QuadVertexRect(), gfx::RectF(quad->rect), gfx::RectF(quad->visible_rect));
SkRect quad_rect = gfx::RectFToSkRect(visible_quad_vertex_rect);
if (quad->y_flipped)
@@ -472,10 +455,8 @@ void SoftwareRenderer::DrawTextureQuad(const DrawingFrame* frame,
paint.setShader(shader.get());
current_canvas_->drawRect(quad_rect, paint);
} else {
- current_canvas_->drawBitmapRectToRect(*bitmap,
- &sk_uv_rect,
- quad_rect,
- &current_paint_);
+ current_canvas_->drawBitmapRect(*bitmap, sk_uv_rect, quad_rect,
+ &current_paint_);
}
if (needs_layer)
@@ -496,18 +477,17 @@ void SoftwareRenderer::DrawTileQuad(const DrawingFrame* frame,
DCHECK_EQ(GL_CLAMP_TO_EDGE, lock.wrap_mode());
gfx::RectF visible_tex_coord_rect = MathUtil::ScaleRectProportional(
- quad->tex_coord_rect, quad->rect, quad->visible_rect);
+ quad->tex_coord_rect, gfx::RectF(quad->rect),
+ gfx::RectF(quad->visible_rect));
gfx::RectF visible_quad_vertex_rect = MathUtil::ScaleRectProportional(
- QuadVertexRect(), quad->rect, quad->visible_rect);
+ QuadVertexRect(), gfx::RectF(quad->rect), gfx::RectF(quad->visible_rect));
SkRect uv_rect = gfx::RectFToSkRect(visible_tex_coord_rect);
current_paint_.setFilterQuality(
quad->nearest_neighbor ? kNone_SkFilterQuality : kLow_SkFilterQuality);
- current_canvas_->drawBitmapRectToRect(
- *lock.sk_bitmap(),
- &uv_rect,
- gfx::RectFToSkRect(visible_quad_vertex_rect),
- &current_paint_);
+ current_canvas_->drawBitmapRect(*lock.sk_bitmap(), uv_rect,
+ gfx::RectFToSkRect(visible_quad_vertex_rect),
+ &current_paint_);
}
void SoftwareRenderer::DrawRenderPassQuad(const DrawingFrame* frame,
@@ -525,8 +505,9 @@ void SoftwareRenderer::DrawRenderPassQuad(const DrawingFrame* frame,
SkShader::TileMode content_tile_mode = WrapModeToTileMode(lock.wrap_mode());
SkRect dest_rect = gfx::RectFToSkRect(QuadVertexRect());
- SkRect dest_visible_rect = gfx::RectFToSkRect(MathUtil::ScaleRectProportional(
- QuadVertexRect(), quad->rect, quad->visible_rect));
+ SkRect dest_visible_rect = gfx::RectFToSkRect(
+ MathUtil::ScaleRectProportional(QuadVertexRect(), gfx::RectF(quad->rect),
+ gfx::RectF(quad->visible_rect)));
SkRect content_rect = SkRect::MakeWH(quad->rect.width(), quad->rect.height());
SkMatrix content_mat;
@@ -538,23 +519,10 @@ void SoftwareRenderer::DrawRenderPassQuad(const DrawingFrame* frame,
SkBitmap filter_bitmap;
if (!quad->filters.IsEmpty()) {
skia::RefPtr<SkImageFilter> filter = RenderSurfaceFilters::BuildImageFilter(
- quad->filters, content_texture->size());
+ quad->filters, gfx::SizeF(content_texture->size()));
// TODO(ajuma): Apply the filter in the same pass as the content where
// possible (e.g. when there's no origin offset). See crbug.com/308201.
- if (filter) {
- SkImageInfo info = SkImageInfo::MakeN32Premul(
- content_texture->size().width(), content_texture->size().height());
- if (filter_bitmap.tryAllocPixels(info)) {
- SkCanvas canvas(filter_bitmap);
- SkPaint paint;
- paint.setImageFilter(filter.get());
- canvas.clear(SK_ColorTRANSPARENT);
- canvas.translate(SkIntToScalar(-quad->rect.origin().x()),
- SkIntToScalar(-quad->rect.origin().y()));
- canvas.scale(quad->filters_scale.x(), quad->filters_scale.y());
- canvas.drawSprite(*content, 0, 0, &paint);
- }
- }
+ filter_bitmap = ApplyImageFilter(filter.get(), quad, content);
}
skia::RefPtr<SkShader> shader;
@@ -565,17 +533,20 @@ void SoftwareRenderer::DrawRenderPassQuad(const DrawingFrame* frame,
shader = skia::AdoptRef(SkShader::CreateBitmapShader(
filter_bitmap, content_tile_mode, content_tile_mode, &content_mat));
}
- current_paint_.setShader(shader.get());
+ scoped_ptr<ResourceProvider::ScopedReadLockSoftware> mask_lock;
if (quad->mask_resource_id()) {
- ResourceProvider::ScopedReadLockSoftware mask_lock(
- resource_provider_, quad->mask_resource_id());
- if (!lock.valid())
+ mask_lock = scoped_ptr<ResourceProvider::ScopedReadLockSoftware>(
+ new ResourceProvider::ScopedReadLockSoftware(resource_provider_,
+ quad->mask_resource_id()));
+
+ if (!mask_lock->valid())
return;
- SkShader::TileMode mask_tile_mode = WrapModeToTileMode(
- mask_lock.wrap_mode());
- const SkBitmap* mask = mask_lock.sk_bitmap();
+ SkShader::TileMode mask_tile_mode =
+ WrapModeToTileMode(mask_lock->wrap_mode());
+
+ const SkBitmap* mask = mask_lock->sk_bitmap();
// Scale normalized uv rect into absolute texel coordinates.
SkRect mask_rect =
@@ -600,11 +571,17 @@ void SoftwareRenderer::DrawRenderPassQuad(const DrawingFrame* frame,
skia::AdoptRef(builder.detachRasterizer());
current_paint_.setRasterizer(mask_rasterizer.get());
- current_canvas_->drawRect(dest_visible_rect, current_paint_);
- } else {
- // TODO(skaslev): Apply background filters
+ }
+
+ // If we have a background filter shader, render its results first.
+ skia::RefPtr<SkShader> background_filter_shader =
+ GetBackgroundFilterShader(frame, quad, content_tile_mode);
+ if (background_filter_shader) {
+ current_paint_.setShader(background_filter_shader.get());
current_canvas_->drawRect(dest_visible_rect, current_paint_);
}
+ current_paint_.setShader(shader.get());
+ current_canvas_->drawRect(dest_visible_rect, current_paint_);
}
void SoftwareRenderer::DrawUnsupportedQuad(const DrawingFrame* frame,
@@ -663,4 +640,107 @@ void SoftwareRenderer::DidChangeVisibility() {
DiscardBackbuffer();
}
+bool SoftwareRenderer::ShouldApplyBackgroundFilters(
+ const RenderPassDrawQuad* quad) const {
+ if (quad->background_filters.IsEmpty())
+ return false;
+
+ // TODO(hendrikw): Look into allowing background filters to see pixels from
+ // other render targets. See crbug.com/314867.
+
+ return true;
+}
+
+SkBitmap SoftwareRenderer::ApplyImageFilter(SkImageFilter* filter,
+ const RenderPassDrawQuad* quad,
+ const SkBitmap* to_filter) const {
+ if (!filter)
+ return SkBitmap();
+
+ SkBitmap filter_bitmap;
+ if (filter_bitmap.tryAllocPixels(SkImageInfo::MakeN32Premul(
+ to_filter->width(), to_filter->height()))) {
+ SkCanvas canvas(filter_bitmap);
+ SkPaint paint;
+ paint.setImageFilter(filter);
+ canvas.clear(SK_ColorTRANSPARENT);
+ canvas.translate(SkIntToScalar(-quad->rect.origin().x()),
+ SkIntToScalar(-quad->rect.origin().y()));
+ canvas.scale(quad->filters_scale.x(), quad->filters_scale.y());
+ canvas.drawSprite(*to_filter, 0, 0, &paint);
+ }
+ return filter_bitmap;
+}
+
+SkBitmap SoftwareRenderer::GetBackdropBitmap(
+ const gfx::Rect& bounding_rect) const {
+ SkBitmap bitmap;
+ bitmap.setInfo(SkImageInfo::MakeN32Premul(bounding_rect.width(),
+ bounding_rect.height()));
+ current_canvas_->readPixels(&bitmap, bounding_rect.x(), bounding_rect.y());
+ return bitmap;
+}
+
+gfx::Rect SoftwareRenderer::GetBackdropBoundingBoxForRenderPassQuad(
+ const DrawingFrame* frame,
+ const RenderPassDrawQuad* quad,
+ const gfx::Transform& contents_device_transform) const {
+ DCHECK(ShouldApplyBackgroundFilters(quad));
+ gfx::Rect backdrop_rect = gfx::ToEnclosingRect(
+ MathUtil::MapClippedRect(contents_device_transform, QuadVertexRect()));
+
+ int top, right, bottom, left;
+ quad->background_filters.GetOutsets(&top, &right, &bottom, &left);
+ backdrop_rect.Inset(-left, -top, -right, -bottom);
+
+ backdrop_rect.Intersect(MoveFromDrawToWindowSpace(
+ frame, frame->current_render_pass->output_rect));
+
+ return backdrop_rect;
+}
+
+skia::RefPtr<SkShader> SoftwareRenderer::GetBackgroundFilterShader(
+ const DrawingFrame* frame,
+ const RenderPassDrawQuad* quad,
+ SkShader::TileMode content_tile_mode) const {
+ if (!ShouldApplyBackgroundFilters(quad))
+ return skia::RefPtr<SkShader>();
+
+ gfx::Transform quad_rect_matrix;
+ QuadRectTransform(&quad_rect_matrix,
+ quad->shared_quad_state->quad_to_target_transform,
+ gfx::RectF(quad->rect));
+ gfx::Transform contents_device_transform =
+ frame->window_matrix * frame->projection_matrix * quad_rect_matrix;
+ contents_device_transform.FlattenTo2d();
+
+ gfx::Rect backdrop_rect = GetBackdropBoundingBoxForRenderPassQuad(
+ frame, quad, contents_device_transform);
+
+ // Figure out the transformations to move it back to pixel space.
+ gfx::Transform contents_device_transform_inverse;
+ if (!contents_device_transform.GetInverse(&contents_device_transform_inverse))
+ return skia::RefPtr<SkShader>();
+
+ SkMatrix filter_backdrop_transform =
+ contents_device_transform_inverse.matrix();
+ filter_backdrop_transform.preTranslate(backdrop_rect.x(), backdrop_rect.y());
+
+ // Draw what's behind, and apply the filter to it.
+ SkBitmap backdrop_bitmap = GetBackdropBitmap(backdrop_rect);
+
+ skia::RefPtr<SkImageFilter> filter = RenderSurfaceFilters::BuildImageFilter(
+ quad->background_filters,
+ gfx::SizeF(backdrop_bitmap.width(), backdrop_bitmap.height()));
+ SkBitmap filter_backdrop_bitmap =
+ ApplyImageFilter(filter.get(), quad, &backdrop_bitmap);
+
+ if (filter_backdrop_bitmap.empty())
+ return skia::RefPtr<SkShader>();
+
+ return skia::AdoptRef(SkShader::CreateBitmapShader(
+ filter_backdrop_bitmap, content_tile_mode, content_tile_mode,
+ &filter_backdrop_transform));
+}
+
} // namespace cc
diff --git a/chromium/cc/output/software_renderer.h b/chromium/cc/output/software_renderer.h
index c3090429635..339bf6fb64a 100644
--- a/chromium/cc/output/software_renderer.h
+++ b/chromium/cc/output/software_renderer.h
@@ -37,7 +37,6 @@ class CC_EXPORT SoftwareRenderer : public DirectRenderer {
const RendererCapabilitiesImpl& Capabilities() const override;
void Finish() override;
void SwapBuffers(const CompositorFrameMetadata& metadata) override;
- void ReceiveSwapBuffersAck(const CompositorFrameAck& ack) override;
void DiscardBackbuffer() override;
void EnsureBackbuffer() override;
@@ -92,6 +91,19 @@ class CC_EXPORT SoftwareRenderer : public DirectRenderer {
const TileDrawQuad* quad);
void DrawUnsupportedQuad(const DrawingFrame* frame,
const DrawQuad* quad);
+ bool ShouldApplyBackgroundFilters(const RenderPassDrawQuad* quad) const;
+ SkBitmap ApplyImageFilter(SkImageFilter* filter,
+ const RenderPassDrawQuad* quad,
+ const SkBitmap* to_filter) const;
+ gfx::Rect GetBackdropBoundingBoxForRenderPassQuad(
+ const DrawingFrame* frame,
+ const RenderPassDrawQuad* quad,
+ const gfx::Transform& contents_device_transform) const;
+ SkBitmap GetBackdropBitmap(const gfx::Rect& bounding_rect) const;
+ skia::RefPtr<SkShader> GetBackgroundFilterShader(
+ const DrawingFrame* frame,
+ const RenderPassDrawQuad* quad,
+ SkShader::TileMode content_tile_mode) const;
RendererCapabilitiesImpl capabilities_;
bool is_scissor_enabled_;
@@ -105,7 +117,6 @@ class CC_EXPORT SoftwareRenderer : public DirectRenderer {
scoped_ptr<ResourceProvider::ScopedWriteLockSoftware>
current_framebuffer_lock_;
skia::RefPtr<SkCanvas> current_framebuffer_canvas_;
- scoped_ptr<SoftwareFrameData> current_frame_data_;
DISALLOW_COPY_AND_ASSIGN(SoftwareRenderer);
};
diff --git a/chromium/cc/output/software_renderer_unittest.cc b/chromium/cc/output/software_renderer_unittest.cc
index a7ef1a20f7d..488cf344c63 100644
--- a/chromium/cc/output/software_renderer_unittest.cc
+++ b/chromium/cc/output/software_renderer_unittest.cc
@@ -18,7 +18,6 @@
#include "cc/test/fake_output_surface_client.h"
#include "cc/test/fake_resource_provider.h"
#include "cc/test/geometry_test_utils.h"
-#include "cc/test/render_pass_test_common.h"
#include "cc/test/render_pass_test_utils.h"
#include "cc/test/test_shared_bitmap_manager.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -100,7 +99,7 @@ TEST_F(SoftwareRendererTest, SolidColorQuad) {
InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
RenderPassId root_render_pass_id = RenderPassId(1, 1);
- scoped_ptr<TestRenderPass> root_render_pass = TestRenderPass::Create();
+ scoped_ptr<RenderPass> root_render_pass = RenderPass::Create();
root_render_pass->SetNew(
root_render_pass_id, outer_rect, outer_rect, gfx::Transform());
SharedQuadState* shared_quad_state =
@@ -173,7 +172,7 @@ TEST_F(SoftwareRendererTest, TileQuad) {
gfx::Rect root_rect = outer_rect;
RenderPassId root_render_pass_id = RenderPassId(1, 1);
- scoped_ptr<TestRenderPass> root_render_pass = TestRenderPass::Create();
+ scoped_ptr<RenderPass> root_render_pass = RenderPass::Create();
root_render_pass->SetNew(
root_render_pass_id, root_rect, root_rect, gfx::Transform());
SharedQuadState* shared_quad_state =
@@ -188,26 +187,14 @@ TEST_F(SoftwareRendererTest, TileQuad) {
0);
TileDrawQuad* inner_quad =
root_render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
- inner_quad->SetNew(shared_quad_state,
- inner_rect,
- inner_rect,
- inner_rect,
- resource_cyan,
- gfx::RectF(inner_size),
- inner_size,
- false,
- false);
+ inner_quad->SetNew(shared_quad_state, inner_rect, inner_rect, inner_rect,
+ resource_cyan, gfx::RectF(gfx::SizeF(inner_size)),
+ inner_size, false, false);
TileDrawQuad* outer_quad =
root_render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
- outer_quad->SetNew(shared_quad_state,
- outer_rect,
- outer_rect,
- outer_rect,
- resource_yellow,
- gfx::RectF(outer_size),
- outer_size,
- false,
- false);
+ outer_quad->SetNew(shared_quad_state, outer_rect, outer_rect, outer_rect,
+ resource_yellow, gfx::RectF(gfx::SizeF(outer_size)),
+ outer_size, false, false);
RenderPassList list;
list.push_back(root_render_pass.Pass());
@@ -252,7 +239,7 @@ TEST_F(SoftwareRendererTest, TileQuadVisibleRect) {
gfx::Rect root_rect(tile_size);
RenderPassId root_render_pass_id = RenderPassId(1, 1);
- scoped_ptr<TestRenderPass> root_render_pass = TestRenderPass::Create();
+ scoped_ptr<RenderPass> root_render_pass = RenderPass::Create();
root_render_pass->SetNew(
root_render_pass_id, root_rect, root_rect, gfx::Transform());
SharedQuadState* shared_quad_state =
@@ -267,15 +254,9 @@ TEST_F(SoftwareRendererTest, TileQuadVisibleRect) {
0);
TileDrawQuad* quad =
root_render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
- quad->SetNew(shared_quad_state,
- tile_rect,
- tile_rect,
- tile_rect,
- resource_cyan,
- gfx::RectF(tile_size),
- tile_size,
- false,
- false);
+ quad->SetNew(shared_quad_state, tile_rect, tile_rect, tile_rect,
+ resource_cyan, gfx::RectF(gfx::SizeF(tile_size)), tile_size,
+ false, false);
quad->visible_rect = visible_rect;
RenderPassList list;
@@ -319,7 +300,7 @@ TEST_F(SoftwareRendererTest, ShouldClearRootRenderPass) {
// Draw a fullscreen green quad in a first frame.
RenderPassId root_clear_pass_id(1, 0);
- TestRenderPass* root_clear_pass = AddRenderPass(
+ RenderPass* root_clear_pass = AddRenderPass(
&list, root_clear_pass_id, device_viewport_rect, gfx::Transform());
AddQuad(root_clear_pass, device_viewport_rect, SK_ColorGREEN);
@@ -342,7 +323,7 @@ TEST_F(SoftwareRendererTest, ShouldClearRootRenderPass) {
gfx::Rect smaller_rect(20, 20, 60, 60);
RenderPassId root_smaller_pass_id(2, 0);
- TestRenderPass* root_smaller_pass = AddRenderPass(
+ RenderPass* root_smaller_pass = AddRenderPass(
&list, root_smaller_pass_id, device_viewport_rect, gfx::Transform());
AddQuad(root_smaller_pass, smaller_rect, SK_ColorMAGENTA);
@@ -375,13 +356,13 @@ TEST_F(SoftwareRendererTest, RenderPassVisibleRect) {
// Pass drawn as inner quad is magenta.
gfx::Rect smaller_rect(20, 20, 60, 60);
RenderPassId smaller_pass_id(2, 1);
- TestRenderPass* smaller_pass =
+ RenderPass* smaller_pass =
AddRenderPass(&list, smaller_pass_id, smaller_rect, gfx::Transform());
AddQuad(smaller_pass, smaller_rect, SK_ColorMAGENTA);
// Root pass is green.
RenderPassId root_clear_pass_id(1, 0);
- TestRenderPass* root_clear_pass = AddRenderPass(
+ RenderPass* root_clear_pass = AddRenderPass(
&list, root_clear_pass_id, device_viewport_rect, gfx::Transform());
AddRenderPassQuad(root_clear_pass, smaller_pass);
AddQuad(root_clear_pass, device_viewport_rect, SK_ColorGREEN);
diff --git a/chromium/cc/playback/clip_display_item.cc b/chromium/cc/playback/clip_display_item.cc
index 5941502860b..e0901b88e07 100644
--- a/chromium/cc/playback/clip_display_item.cc
+++ b/chromium/cc/playback/clip_display_item.cc
@@ -48,6 +48,11 @@ void ClipDisplayItem::Raster(SkCanvas* canvas,
}
}
+void ClipDisplayItem::ProcessForBounds(
+ DisplayItemListBoundsCalculator* calculator) const {
+ calculator->AddStartingDisplayItem();
+}
+
void ClipDisplayItem::AsValueInto(base::trace_event::TracedValue* array) const {
std::string value = base::StringPrintf("ClipDisplayItem rect: [%s]",
clip_rect_.ToString().c_str());
@@ -88,6 +93,11 @@ void EndClipDisplayItem::Raster(SkCanvas* canvas,
canvas->restore();
}
+void EndClipDisplayItem::ProcessForBounds(
+ DisplayItemListBoundsCalculator* calculator) const {
+ calculator->AddEndingDisplayItem();
+}
+
void EndClipDisplayItem::AsValueInto(
base::trace_event::TracedValue* array) const {
array->AppendString("EndClipDisplayItem");
diff --git a/chromium/cc/playback/clip_display_item.h b/chromium/cc/playback/clip_display_item.h
index 83e0b6bf21a..2af0fa33e9d 100644
--- a/chromium/cc/playback/clip_display_item.h
+++ b/chromium/cc/playback/clip_display_item.h
@@ -29,6 +29,8 @@ class CC_EXPORT ClipDisplayItem : public DisplayItem {
const gfx::Rect& canvas_target_playback_rect,
SkPicture::AbortCallback* callback) const override;
void AsValueInto(base::trace_event::TracedValue* array) const override;
+ void ProcessForBounds(
+ DisplayItemListBoundsCalculator* calculator) const override;
private:
gfx::Rect clip_rect_;
@@ -44,6 +46,8 @@ class CC_EXPORT EndClipDisplayItem : public DisplayItem {
const gfx::Rect& canvas_target_playback_rect,
SkPicture::AbortCallback* callback) const override;
void AsValueInto(base::trace_event::TracedValue* array) const override;
+ void ProcessForBounds(
+ DisplayItemListBoundsCalculator* calculator) const override;
};
} // namespace cc
diff --git a/chromium/cc/playback/clip_path_display_item.cc b/chromium/cc/playback/clip_path_display_item.cc
index f7fd60626e5..9ac5bdea80a 100644
--- a/chromium/cc/playback/clip_path_display_item.cc
+++ b/chromium/cc/playback/clip_path_display_item.cc
@@ -36,6 +36,11 @@ void ClipPathDisplayItem::Raster(SkCanvas* canvas,
canvas->clipPath(clip_path_, clip_op_, antialias_);
}
+void ClipPathDisplayItem::ProcessForBounds(
+ DisplayItemListBoundsCalculator* calculator) const {
+ calculator->AddStartingDisplayItem();
+}
+
void ClipPathDisplayItem::AsValueInto(
base::trace_event::TracedValue* array) const {
array->AppendString(base::StringPrintf("ClipPathDisplayItem length: %d",
@@ -57,6 +62,11 @@ void EndClipPathDisplayItem::Raster(
canvas->restore();
}
+void EndClipPathDisplayItem::ProcessForBounds(
+ DisplayItemListBoundsCalculator* calculator) const {
+ calculator->AddEndingDisplayItem();
+}
+
void EndClipPathDisplayItem::AsValueInto(
base::trace_event::TracedValue* array) const {
array->AppendString("EndClipPathDisplayItem");
diff --git a/chromium/cc/playback/clip_path_display_item.h b/chromium/cc/playback/clip_path_display_item.h
index 732087b9789..08581e29dd1 100644
--- a/chromium/cc/playback/clip_path_display_item.h
+++ b/chromium/cc/playback/clip_path_display_item.h
@@ -26,6 +26,8 @@ class CC_EXPORT ClipPathDisplayItem : public DisplayItem {
const gfx::Rect& canvas_target_playback_rect,
SkPicture::AbortCallback* callback) const override;
void AsValueInto(base::trace_event::TracedValue* array) const override;
+ void ProcessForBounds(
+ DisplayItemListBoundsCalculator* calculator) const override;
private:
SkPath clip_path_;
@@ -46,6 +48,8 @@ class CC_EXPORT EndClipPathDisplayItem : public DisplayItem {
const gfx::Rect& canvas_target_playback_rect,
SkPicture::AbortCallback* callback) const override;
void AsValueInto(base::trace_event::TracedValue* array) const override;
+ void ProcessForBounds(
+ DisplayItemListBoundsCalculator* calculator) const override;
};
} // namespace cc
diff --git a/chromium/cc/playback/compositing_display_item.cc b/chromium/cc/playback/compositing_display_item.cc
index 31365b5881c..c9b74fc4786 100644
--- a/chromium/cc/playback/compositing_display_item.cc
+++ b/chromium/cc/playback/compositing_display_item.cc
@@ -47,6 +47,12 @@ void CompositingDisplayItem::Raster(
canvas->saveLayer(has_bounds_ ? &bounds_ : nullptr, &paint);
}
+void CompositingDisplayItem::ProcessForBounds(
+ DisplayItemListBoundsCalculator* calculator) const {
+ calculator->AddStartingDisplayItem();
+ calculator->Save();
+}
+
void CompositingDisplayItem::AsValueInto(
base::trace_event::TracedValue* array) const {
array->AppendString(base::StringPrintf(
@@ -73,6 +79,12 @@ void EndCompositingDisplayItem::Raster(
canvas->restore();
}
+void EndCompositingDisplayItem::ProcessForBounds(
+ DisplayItemListBoundsCalculator* calculator) const {
+ calculator->Restore();
+ calculator->AddEndingDisplayItem();
+}
+
void EndCompositingDisplayItem::AsValueInto(
base::trace_event::TracedValue* array) const {
array->AppendString("EndCompositingDisplayItem");
diff --git a/chromium/cc/playback/compositing_display_item.h b/chromium/cc/playback/compositing_display_item.h
index 91cd3e71f8e..9ee6b7a0eca 100644
--- a/chromium/cc/playback/compositing_display_item.h
+++ b/chromium/cc/playback/compositing_display_item.h
@@ -32,6 +32,8 @@ class CC_EXPORT CompositingDisplayItem : public DisplayItem {
const gfx::Rect& canvas_target_playback_rect,
SkPicture::AbortCallback* callback) const override;
void AsValueInto(base::trace_event::TracedValue* array) const override;
+ void ProcessForBounds(
+ DisplayItemListBoundsCalculator* calculator) const override;
private:
uint8_t alpha_;
@@ -54,6 +56,8 @@ class CC_EXPORT EndCompositingDisplayItem : public DisplayItem {
const gfx::Rect& canvas_target_playback_rect,
SkPicture::AbortCallback* callback) const override;
void AsValueInto(base::trace_event::TracedValue* array) const override;
+ void ProcessForBounds(
+ DisplayItemListBoundsCalculator* calculator) const override;
};
} // namespace cc
diff --git a/chromium/cc/playback/discardable_image_map.cc b/chromium/cc/playback/discardable_image_map.cc
new file mode 100644
index 00000000000..a78ef5fc812
--- /dev/null
+++ b/chromium/cc/playback/discardable_image_map.cc
@@ -0,0 +1,136 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/playback/discardable_image_map.h"
+
+#include <algorithm>
+#include <limits>
+
+#include "cc/base/math_util.h"
+#include "cc/playback/display_item_list.h"
+#include "third_party/skia/include/utils/SkNWayCanvas.h"
+#include "ui/gfx/geometry/rect_conversions.h"
+#include "ui/gfx/skia_util.h"
+
+namespace cc {
+
+namespace {
+
+SkRect MapRect(const SkMatrix& matrix, const SkRect& src) {
+ SkRect dst;
+ matrix.mapRect(&dst, src);
+ return dst;
+}
+
+// We're using an NWay canvas with no added canvases, so in effect
+// non-overridden functions are no-ops.
+class DiscardableImagesMetadataCanvas : public SkNWayCanvas {
+ public:
+ DiscardableImagesMetadataCanvas(int width,
+ int height,
+ std::vector<PositionImage>* image_set)
+ : SkNWayCanvas(width, height),
+ image_set_(image_set),
+ canvas_bounds_(SkRect::MakeIWH(width, height)) {}
+
+ protected:
+ // we need to "undo" the behavior of SkNWayCanvas, which will try to forward
+ // it.
+ void onDrawPicture(const SkPicture* picture,
+ const SkMatrix* matrix,
+ const SkPaint* paint) override {
+ SkCanvas::onDrawPicture(picture, matrix, paint);
+ }
+
+ void onDrawImage(const SkImage* image,
+ SkScalar x,
+ SkScalar y,
+ const SkPaint* paint) override {
+ const SkMatrix& ctm = this->getTotalMatrix();
+ AddImage(image, MapRect(ctm, SkRect::MakeXYWH(x, y, image->width(),
+ image->height())),
+ ctm, paint);
+ }
+
+ void onDrawImageRect(const SkImage* image,
+ const SkRect* src,
+ const SkRect& dst,
+ const SkPaint* paint,
+ SrcRectConstraint) override {
+ const SkMatrix& ctm = this->getTotalMatrix();
+ SkRect src_storage;
+ if (!src) {
+ src_storage = SkRect::MakeIWH(image->width(), image->height());
+ src = &src_storage;
+ }
+ SkMatrix matrix;
+ matrix.setRectToRect(*src, dst, SkMatrix::kFill_ScaleToFit);
+ matrix.postConcat(ctm);
+ AddImage(image, MapRect(ctm, dst), matrix, paint);
+ }
+
+ void onDrawImageNine(const SkImage* image,
+ const SkIRect& center,
+ const SkRect& dst,
+ const SkPaint* paint) override {
+ AddImage(image, dst, this->getTotalMatrix(), paint);
+ }
+
+ private:
+ void AddImage(const SkImage* image,
+ const SkRect& rect,
+ const SkMatrix& matrix,
+ const SkPaint* paint) {
+ if (rect.intersects(canvas_bounds_) && image->isLazyGenerated()) {
+ SkFilterQuality filter_quality = kNone_SkFilterQuality;
+ if (paint) {
+ filter_quality = paint->getFilterQuality();
+ }
+ image_set_->push_back(PositionImage(image, rect, matrix, filter_quality));
+ }
+ }
+
+ std::vector<PositionImage>* image_set_;
+ const SkRect canvas_bounds_;
+};
+
+} // namespace
+
+DiscardableImageMap::DiscardableImageMap() {}
+
+DiscardableImageMap::~DiscardableImageMap() {}
+
+scoped_ptr<SkCanvas> DiscardableImageMap::BeginGeneratingMetadata(
+ const gfx::Size& bounds) {
+ DCHECK(all_images_.empty());
+ return scoped_ptr<SkCanvas>(new DiscardableImagesMetadataCanvas(
+ bounds.width(), bounds.height(), &all_images_));
+}
+
+void DiscardableImageMap::EndGeneratingMetadata() {
+ images_rtree_.Build(all_images_, [](const PositionImage& image) {
+ return gfx::SkRectToRectF(image.image_rect);
+ });
+}
+
+void DiscardableImageMap::GetDiscardableImagesInRect(
+ const gfx::Rect& rect,
+ std::vector<PositionImage>* images) {
+ std::vector<size_t> indices;
+ images_rtree_.Search(gfx::RectF(rect), &indices);
+ for (size_t index : indices)
+ images->push_back(all_images_[index]);
+}
+
+DiscardableImageMap::ScopedMetadataGenerator::ScopedMetadataGenerator(
+ DiscardableImageMap* image_map,
+ const gfx::Size& bounds)
+ : image_map_(image_map),
+ metadata_canvas_(image_map->BeginGeneratingMetadata(bounds)) {}
+
+DiscardableImageMap::ScopedMetadataGenerator::~ScopedMetadataGenerator() {
+ image_map_->EndGeneratingMetadata();
+}
+
+} // namespace cc
diff --git a/chromium/cc/playback/discardable_image_map.h b/chromium/cc/playback/discardable_image_map.h
new file mode 100644
index 00000000000..e5928f7aedc
--- /dev/null
+++ b/chromium/cc/playback/discardable_image_map.h
@@ -0,0 +1,67 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_PLAYBACK_DISCARDABLE_IMAGE_MAP_H_
+#define CC_PLAYBACK_DISCARDABLE_IMAGE_MAP_H_
+
+#include <utility>
+#include <vector>
+
+#include "base/containers/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "cc/base/cc_export.h"
+#include "cc/base/rtree.h"
+#include "cc/playback/position_image.h"
+#include "third_party/skia/include/core/SkPicture.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/size.h"
+
+class SkImage;
+
+namespace cc {
+
+class DisplayItemList;
+
+// This class is used for generating discardable images data (see PositionImage
+// for the type of data it stores). It allows the client to query a particular
+// rect and get back a list of PositionImages in that rect.
+class CC_EXPORT DiscardableImageMap {
+ public:
+ using Images = std::vector<PositionImage>;
+
+ class CC_EXPORT ScopedMetadataGenerator {
+ public:
+ ScopedMetadataGenerator(DiscardableImageMap* image_map,
+ const gfx::Size& bounds);
+ ~ScopedMetadataGenerator();
+
+ SkCanvas* canvas() { return metadata_canvas_.get(); }
+
+ private:
+ DiscardableImageMap* image_map_;
+ scoped_ptr<SkCanvas> metadata_canvas_;
+ };
+
+ DiscardableImageMap();
+ ~DiscardableImageMap();
+
+ bool empty() const { return all_images_.empty(); }
+ void GetDiscardableImagesInRect(const gfx::Rect& rect,
+ std::vector<PositionImage>* images);
+
+ private:
+ friend class ScopedMetadataGenerator;
+
+ scoped_ptr<SkCanvas> BeginGeneratingMetadata(const gfx::Size& bounds);
+ void EndGeneratingMetadata();
+
+ Images all_images_;
+ RTree images_rtree_;
+};
+
+} // namespace cc
+
+#endif // CC_PLAYBACK_DISCARDABLE_IMAGE_MAP_H_
diff --git a/chromium/cc/playback/discardable_image_map_unittest.cc b/chromium/cc/playback/discardable_image_map_unittest.cc
new file mode 100644
index 00000000000..65bf68e4287
--- /dev/null
+++ b/chromium/cc/playback/discardable_image_map_unittest.cc
@@ -0,0 +1,316 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/playback/discardable_image_map.h"
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/values.h"
+#include "cc/base/region.h"
+#include "cc/playback/raster_source.h"
+#include "cc/test/fake_content_layer_client.h"
+#include "cc/test/fake_display_list_recording_source.h"
+#include "cc/test/skia_common.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkGraphics.h"
+#include "third_party/skia/include/core/SkImageGenerator.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/skia_util.h"
+
+namespace cc {
+namespace {
+
+class TestImageGenerator : public SkImageGenerator {
+ public:
+ explicit TestImageGenerator(const SkImageInfo& info)
+ : SkImageGenerator(info) {}
+};
+
+skia::RefPtr<SkImage> CreateDiscardableImage(const gfx::Size& size) {
+ const SkImageInfo info =
+ SkImageInfo::MakeN32Premul(size.width(), size.height());
+ return skia::AdoptRef(
+ SkImage::NewFromGenerator(new TestImageGenerator(info)));
+}
+
+TEST(DiscardableImageMapTest, GetDiscardableImagesInRect) {
+ gfx::Rect visible_rect(2048, 2048);
+ FakeContentLayerClient content_layer_client;
+
+ // Discardable pixel refs are found in the following grids:
+ // |---|---|---|---|
+ // | | x | | x |
+ // |---|---|---|---|
+ // | x | | x | |
+ // |---|---|---|---|
+ // | | x | | x |
+ // |---|---|---|---|
+ // | x | | x | |
+ // |---|---|---|---|
+ skia::RefPtr<SkImage> discardable_image[4][4];
+ for (int y = 0; y < 4; ++y) {
+ for (int x = 0; x < 4; ++x) {
+ if ((x + y) & 1) {
+ discardable_image[y][x] = CreateDiscardableImage(gfx::Size(500, 500));
+ SkPaint paint;
+ content_layer_client.add_draw_image(
+ discardable_image[y][x].get(), gfx::Point(x * 512 + 6, y * 512 + 6),
+ paint);
+ }
+ }
+ }
+
+ FakeDisplayListRecordingSource recording_source;
+ Region invalidation(visible_rect);
+ recording_source.SetGenerateDiscardableImagesMetadata(true);
+ recording_source.UpdateAndExpandInvalidation(
+ &content_layer_client, &invalidation, visible_rect.size(), visible_rect,
+ 1, RecordingSource::RECORD_NORMALLY);
+ DisplayItemList* display_list = recording_source.display_list();
+
+ DiscardableImageMap image_map;
+ {
+ DiscardableImageMap::ScopedMetadataGenerator generator(&image_map,
+ visible_rect.size());
+ display_list->Raster(generator.canvas(), nullptr, visible_rect, 1.f);
+ }
+
+ for (int y = 0; y < 4; ++y) {
+ for (int x = 0; x < 4; ++x) {
+ std::vector<PositionImage> images;
+ image_map.GetDiscardableImagesInRect(
+ gfx::Rect(x * 512, y * 512, 500, 500), &images);
+ if ((x + y) & 1) {
+ EXPECT_EQ(1u, images.size()) << x << " " << y;
+ EXPECT_TRUE(images[0].image == discardable_image[y][x].get())
+ << x << " " << y;
+ EXPECT_EQ(gfx::RectF(x * 512 + 6, y * 512 + 6, 500, 500).ToString(),
+ gfx::SkRectToRectF(images[0].image_rect).ToString());
+ } else {
+ EXPECT_EQ(0u, images.size()) << x << " " << y;
+ }
+ }
+ }
+
+ // Capture 4 pixel refs.
+ std::vector<PositionImage> images;
+ image_map.GetDiscardableImagesInRect(gfx::Rect(512, 512, 2048, 2048),
+ &images);
+ EXPECT_EQ(4u, images.size());
+ EXPECT_TRUE(images[0].image == discardable_image[1][2].get());
+ EXPECT_EQ(gfx::RectF(2 * 512 + 6, 512 + 6, 500, 500).ToString(),
+ gfx::SkRectToRectF(images[0].image_rect).ToString());
+ EXPECT_TRUE(images[1].image == discardable_image[2][1].get());
+ EXPECT_EQ(gfx::RectF(512 + 6, 2 * 512 + 6, 500, 500).ToString(),
+ gfx::SkRectToRectF(images[1].image_rect).ToString());
+ EXPECT_TRUE(images[2].image == discardable_image[2][3].get());
+ EXPECT_EQ(gfx::RectF(3 * 512 + 6, 2 * 512 + 6, 500, 500).ToString(),
+ gfx::SkRectToRectF(images[2].image_rect).ToString());
+ EXPECT_TRUE(images[3].image == discardable_image[3][2].get());
+ EXPECT_EQ(gfx::RectF(2 * 512 + 6, 3 * 512 + 6, 500, 500).ToString(),
+ gfx::SkRectToRectF(images[3].image_rect).ToString());
+}
+
+TEST(DiscardableImageMapTest, GetDiscardableImagesInRectNonZeroLayer) {
+ gfx::Rect visible_rect(1024, 0, 2048, 2048);
+ // Make sure visible rect fits into the layer size.
+ gfx::Size layer_size(visible_rect.right(), visible_rect.bottom());
+ FakeContentLayerClient content_layer_client;
+
+ // Discardable pixel refs are found in the following grids:
+ // |---|---|---|---|
+ // | | x | | x |
+ // |---|---|---|---|
+ // | x | | x | |
+ // |---|---|---|---|
+ // | | x | | x |
+ // |---|---|---|---|
+ // | x | | x | |
+ // |---|---|---|---|
+ skia::RefPtr<SkImage> discardable_image[4][4];
+ for (int y = 0; y < 4; ++y) {
+ for (int x = 0; x < 4; ++x) {
+ if ((x + y) & 1) {
+ discardable_image[y][x] = CreateDiscardableImage(gfx::Size(500, 500));
+ SkPaint paint;
+ content_layer_client.add_draw_image(
+ discardable_image[y][x].get(),
+ gfx::Point(1024 + x * 512 + 6, y * 512 + 6), paint);
+ }
+ }
+ }
+
+ FakeDisplayListRecordingSource recording_source;
+ Region invalidation(visible_rect);
+ recording_source.set_pixel_record_distance(0);
+ recording_source.SetGenerateDiscardableImagesMetadata(true);
+ recording_source.UpdateAndExpandInvalidation(
+ &content_layer_client, &invalidation, layer_size, visible_rect, 1,
+ RecordingSource::RECORD_NORMALLY);
+ DisplayItemList* display_list = recording_source.display_list();
+
+ DiscardableImageMap image_map;
+ {
+ DiscardableImageMap::ScopedMetadataGenerator generator(&image_map,
+ layer_size);
+ display_list->Raster(generator.canvas(), nullptr, visible_rect, 1.f);
+ }
+
+ for (int y = 0; y < 4; ++y) {
+ for (int x = 0; x < 4; ++x) {
+ std::vector<PositionImage> images;
+ image_map.GetDiscardableImagesInRect(
+ gfx::Rect(1024 + x * 512, y * 512, 500, 500), &images);
+ if ((x + y) & 1) {
+ EXPECT_EQ(1u, images.size()) << x << " " << y;
+ EXPECT_TRUE(images[0].image == discardable_image[y][x].get())
+ << x << " " << y;
+ EXPECT_EQ(
+ gfx::RectF(1024 + x * 512 + 6, y * 512 + 6, 500, 500).ToString(),
+ gfx::SkRectToRectF(images[0].image_rect).ToString());
+ } else {
+ EXPECT_EQ(0u, images.size()) << x << " " << y;
+ }
+ }
+ }
+ // Capture 4 pixel refs.
+ {
+ std::vector<PositionImage> images;
+ image_map.GetDiscardableImagesInRect(gfx::Rect(1024 + 512, 512, 2048, 2048),
+ &images);
+ EXPECT_EQ(4u, images.size());
+ EXPECT_TRUE(images[0].image == discardable_image[1][2].get());
+ EXPECT_EQ(gfx::RectF(1024 + 2 * 512 + 6, 512 + 6, 500, 500).ToString(),
+ gfx::SkRectToRectF(images[0].image_rect).ToString());
+ EXPECT_TRUE(images[1].image == discardable_image[2][1].get());
+ EXPECT_EQ(gfx::RectF(1024 + 512 + 6, 2 * 512 + 6, 500, 500).ToString(),
+ gfx::SkRectToRectF(images[1].image_rect).ToString());
+ EXPECT_TRUE(images[2].image == discardable_image[2][3].get());
+ EXPECT_EQ(gfx::RectF(1024 + 3 * 512 + 6, 2 * 512 + 6, 500, 500).ToString(),
+ gfx::SkRectToRectF(images[2].image_rect).ToString());
+ EXPECT_TRUE(images[3].image == discardable_image[3][2].get());
+ EXPECT_EQ(gfx::RectF(1024 + 2 * 512 + 6, 3 * 512 + 6, 500, 500).ToString(),
+ gfx::SkRectToRectF(images[3].image_rect).ToString());
+ }
+
+ // Non intersecting rects
+ {
+ std::vector<PositionImage> images;
+ image_map.GetDiscardableImagesInRect(gfx::Rect(0, 0, 1000, 1000), &images);
+ EXPECT_EQ(0u, images.size());
+ }
+ {
+ std::vector<PositionImage> images;
+ image_map.GetDiscardableImagesInRect(gfx::Rect(3500, 0, 1000, 1000),
+ &images);
+ EXPECT_EQ(0u, images.size());
+ }
+ {
+ std::vector<PositionImage> images;
+ image_map.GetDiscardableImagesInRect(gfx::Rect(0, 1100, 1000, 1000),
+ &images);
+ EXPECT_EQ(0u, images.size());
+ }
+ {
+ std::vector<PositionImage> images;
+ image_map.GetDiscardableImagesInRect(gfx::Rect(3500, 1100, 1000, 1000),
+ &images);
+ EXPECT_EQ(0u, images.size());
+ }
+}
+
+TEST(DiscardableImageMapTest, GetDiscardableImagesInRectOnePixelQuery) {
+ gfx::Rect visible_rect(2048, 2048);
+ FakeContentLayerClient content_layer_client;
+
+ // Discardable pixel refs are found in the following grids:
+ // |---|---|---|---|
+ // | | x | | x |
+ // |---|---|---|---|
+ // | x | | x | |
+ // |---|---|---|---|
+ // | | x | | x |
+ // |---|---|---|---|
+ // | x | | x | |
+ // |---|---|---|---|
+ skia::RefPtr<SkImage> discardable_image[4][4];
+ for (int y = 0; y < 4; ++y) {
+ for (int x = 0; x < 4; ++x) {
+ if ((x + y) & 1) {
+ discardable_image[y][x] = CreateDiscardableImage(gfx::Size(500, 500));
+ SkPaint paint;
+ content_layer_client.add_draw_image(
+ discardable_image[y][x].get(), gfx::Point(x * 512 + 6, y * 512 + 6),
+ paint);
+ }
+ }
+ }
+
+ FakeDisplayListRecordingSource recording_source;
+ Region invalidation(visible_rect);
+ recording_source.SetGenerateDiscardableImagesMetadata(true);
+ recording_source.UpdateAndExpandInvalidation(
+ &content_layer_client, &invalidation, visible_rect.size(), visible_rect,
+ 1, RecordingSource::RECORD_NORMALLY);
+ DisplayItemList* display_list = recording_source.display_list();
+
+ DiscardableImageMap image_map;
+ {
+ DiscardableImageMap::ScopedMetadataGenerator generator(&image_map,
+ visible_rect.size());
+ display_list->Raster(generator.canvas(), nullptr, visible_rect, 1.f);
+ }
+
+ for (int y = 0; y < 4; ++y) {
+ for (int x = 0; x < 4; ++x) {
+ std::vector<PositionImage> images;
+ image_map.GetDiscardableImagesInRect(
+ gfx::Rect(x * 512 + 256, y * 512 + 256, 1, 1), &images);
+ if ((x + y) & 1) {
+ EXPECT_EQ(1u, images.size()) << x << " " << y;
+ EXPECT_TRUE(images[0].image == discardable_image[y][x].get())
+ << x << " " << y;
+ EXPECT_EQ(gfx::RectF(x * 512 + 6, y * 512 + 6, 500, 500).ToString(),
+ gfx::SkRectToRectF(images[0].image_rect).ToString());
+ } else {
+ EXPECT_EQ(0u, images.size()) << x << " " << y;
+ }
+ }
+ }
+}
+
+TEST(DiscardableImageMapTest, GetDiscardableImagesInRectMassiveImage) {
+ gfx::Rect visible_rect(2048, 2048);
+ FakeContentLayerClient content_layer_client;
+
+ skia::RefPtr<SkImage> discardable_image;
+ discardable_image = CreateDiscardableImage(gfx::Size(1 << 25, 1 << 25));
+ SkPaint paint;
+ content_layer_client.add_draw_image(discardable_image.get(), gfx::Point(0, 0),
+ paint);
+
+ FakeDisplayListRecordingSource recording_source;
+ Region invalidation(visible_rect);
+ recording_source.SetGenerateDiscardableImagesMetadata(true);
+ recording_source.UpdateAndExpandInvalidation(
+ &content_layer_client, &invalidation, visible_rect.size(), visible_rect,
+ 1, RecordingSource::RECORD_NORMALLY);
+ DisplayItemList* display_list = recording_source.display_list();
+
+ DiscardableImageMap image_map;
+ {
+ DiscardableImageMap::ScopedMetadataGenerator generator(&image_map,
+ visible_rect.size());
+ display_list->Raster(generator.canvas(), nullptr, visible_rect, 1.f);
+ }
+ std::vector<PositionImage> images;
+ image_map.GetDiscardableImagesInRect(gfx::Rect(0, 0, 1, 1), &images);
+ EXPECT_EQ(1u, images.size());
+ EXPECT_TRUE(images[0].image == discardable_image.get());
+ EXPECT_EQ(gfx::RectF(0, 0, 1 << 25, 1 << 25).ToString(),
+ gfx::SkRectToRectF(images[0].image_rect).ToString());
+}
+
+} // namespace
+} // namespace cc
diff --git a/chromium/cc/playback/display_item.h b/chromium/cc/playback/display_item.h
index d89807dd3ce..bc089138ff9 100644
--- a/chromium/cc/playback/display_item.h
+++ b/chromium/cc/playback/display_item.h
@@ -8,6 +8,7 @@
#include "base/memory/scoped_ptr.h"
#include "cc/base/cc_export.h"
#include "cc/debug/traced_value.h"
+#include "cc/playback/display_item_list_bounds_calculator.h"
#include "third_party/skia/include/core/SkPicture.h"
#include "ui/gfx/geometry/rect.h"
@@ -31,6 +32,8 @@ class CC_EXPORT DisplayItem {
const gfx::Rect& canvas_target_playback_rect,
SkPicture::AbortCallback* callback) const = 0;
virtual void AsValueInto(base::trace_event::TracedValue* array) const = 0;
+ virtual void ProcessForBounds(
+ DisplayItemListBoundsCalculator* calculator) const = 0;
bool is_suitable_for_gpu_rasterization() const {
return is_suitable_for_gpu_rasterization_;
diff --git a/chromium/cc/playback/display_item_list.cc b/chromium/cc/playback/display_item_list.cc
index 08fe71d26e6..a9fbfaa37e0 100644
--- a/chromium/cc/playback/display_item_list.cc
+++ b/chromium/cc/playback/display_item_list.cc
@@ -12,7 +12,6 @@
#include "cc/base/math_util.h"
#include "cc/debug/picture_debug_util.h"
#include "cc/debug/traced_display_item_list.h"
-#include "cc/debug/traced_picture.h"
#include "cc/debug/traced_value.h"
#include "cc/playback/display_item_list_settings.h"
#include "cc/playback/largest_display_item.h"
@@ -25,6 +24,10 @@ namespace cc {
namespace {
+// We don't perform per-layer solid color analysis when there are too many skia
+// operations.
+const int kOpCountThatIsOkToAnalyze = 10;
+
bool DisplayItemsTracingEnabled() {
bool tracing_enabled;
TRACE_EVENT_CATEGORY_GROUP_ENABLED(
@@ -36,17 +39,22 @@ const int kDefaultNumDisplayItemsToReserve = 100;
} // namespace
+scoped_refptr<DisplayItemList> DisplayItemList::Create(
+ const gfx::Rect& layer_rect,
+ const DisplayItemListSettings& settings) {
+ return make_scoped_refptr(new DisplayItemList(
+ layer_rect, settings,
+ !settings.use_cached_picture || DisplayItemsTracingEnabled()));
+}
+
DisplayItemList::DisplayItemList(gfx::Rect layer_rect,
const DisplayItemListSettings& settings,
bool retain_individual_display_items)
- : items_(LargestDisplayItemSize(),
- settings.max_sidecar_size,
- kDefaultNumDisplayItemsToReserve,
- settings.sidecar_destroyer),
+ : items_(LargestDisplayItemSize(), kDefaultNumDisplayItemsToReserve),
use_cached_picture_(settings.use_cached_picture),
retain_individual_display_items_(retain_individual_display_items),
layer_rect_(layer_rect),
- all_items_are_suitable_for_gpu_rasterization_(true),
+ is_suitable_for_gpu_rasterization_(true),
approximate_op_count_(0),
picture_memory_usage_(0),
external_memory_usage_(0) {
@@ -63,34 +71,6 @@ DisplayItemList::DisplayItemList(gfx::Rect layer_rect,
}
}
-DisplayItemList::DisplayItemList(gfx::Rect layer_rect,
- const DisplayItemListSettings& settings)
- : DisplayItemList(
- layer_rect,
- settings,
- !settings.use_cached_picture || DisplayItemsTracingEnabled()) {
-}
-
-scoped_refptr<DisplayItemList> DisplayItemList::CreateWithoutCachedPicture(
- const DisplayItemListSettings& settings) {
- DCHECK(!settings.use_cached_picture);
- return Create(gfx::Rect(), settings);
-}
-
-scoped_refptr<DisplayItemList> DisplayItemList::Create(
- gfx::Rect layer_rect,
- bool use_cached_picture) {
- DisplayItemListSettings settings;
- settings.use_cached_picture = use_cached_picture;
- return Create(layer_rect, settings);
-}
-
-scoped_refptr<DisplayItemList> DisplayItemList::Create(
- gfx::Rect layer_rect,
- const DisplayItemListSettings& settings) {
- return make_scoped_refptr(new DisplayItemList(layer_rect, settings));
-}
-
DisplayItemList::~DisplayItemList() {
}
@@ -142,13 +122,19 @@ void DisplayItemList::ProcessAppendedItems() {
needs_process_ = false;
#endif
for (const DisplayItem* item : items_) {
- all_items_are_suitable_for_gpu_rasterization_ &=
- item->is_suitable_for_gpu_rasterization();
- approximate_op_count_ += item->approximate_op_count();
-
if (use_cached_picture_) {
+ // When using a cached picture we will calculate gpu suitability on the
+ // entire cached picture instead of the items. This is more permissive
+ // since none of the items might individually trigger a veto even though
+ // they collectively have enough "bad" operations that a corresponding
+ // Picture would get vetoed. See crbug.com/513016.
DCHECK(canvas_);
- item->Raster(canvas_.get(), gfx::Rect(), NULL);
+ approximate_op_count_ += item->approximate_op_count();
+ item->Raster(canvas_.get(), gfx::Rect(), nullptr);
+ } else {
+ is_suitable_for_gpu_rasterization_ &=
+ item->is_suitable_for_gpu_rasterization();
+ approximate_op_count_ += item->approximate_op_count();
}
if (retain_individual_display_items_) {
@@ -165,11 +151,9 @@ void DisplayItemList::ProcessAppendedItems() {
void DisplayItemList::RasterIntoCanvas(const DisplayItem& item) {
DCHECK(canvas_);
DCHECK(!retain_individual_display_items_);
- all_items_are_suitable_for_gpu_rasterization_ &=
- item.is_suitable_for_gpu_rasterization();
approximate_op_count_ += item.approximate_op_count();
- item.Raster(canvas_.get(), gfx::Rect(), NULL);
+ item.Raster(canvas_.get(), gfx::Rect(), nullptr);
}
bool DisplayItemList::RetainsIndividualDisplayItems() const {
@@ -198,19 +182,14 @@ void DisplayItemList::Finalize() {
SkPictureUtils::ApproximateBytesUsed(picture_.get());
recorder_.reset();
canvas_.clear();
+ is_suitable_for_gpu_rasterization_ =
+ picture_->suitableForGpuRasterization(nullptr);
}
}
bool DisplayItemList::IsSuitableForGpuRasterization() const {
DCHECK(ProcessAppendedItemsCalled());
- if (use_cached_picture_)
- return picture_->suitableForGpuRasterization(NULL);
-
- // This is more permissive than Picture's implementation, since none of the
- // items might individually trigger a veto even though they collectively have
- // enough "bad" operations that a corresponding Picture would get vetoed. See
- // crbug.com/513016.
- return all_items_are_suitable_for_gpu_rasterization_;
+ return is_suitable_for_gpu_rasterization_;
}
int DisplayItemList::ApproximateOpCount() const {
@@ -240,21 +219,26 @@ size_t DisplayItemList::ApproximateMemoryUsage() const {
return memory_usage;
}
+bool DisplayItemList::ShouldBeAnalyzedForSolidColor() const {
+ return ApproximateOpCount() <= kOpCountThatIsOkToAnalyze;
+}
+
scoped_refptr<base::trace_event::ConvertableToTraceFormat>
DisplayItemList::AsValue(bool include_items) const {
DCHECK(ProcessAppendedItemsCalled());
scoped_refptr<base::trace_event::TracedValue> state =
new base::trace_event::TracedValue();
+ state->BeginDictionary("params");
if (include_items) {
- state->BeginArray("params.items");
+ state->BeginArray("items");
for (const DisplayItem* item : items_) {
item->AsValueInto(state.get());
}
- state->EndArray();
+ state->EndArray(); // "items".
}
-
- state->SetValue("params.layer_rect", MathUtil::AsValue(layer_rect_));
+ state->SetValue("layer_rect", MathUtil::AsValue(layer_rect_));
+ state->EndDictionary(); // "params".
if (!layer_rect_.IsEmpty()) {
SkPictureRecorder recorder;
@@ -285,20 +269,27 @@ void DisplayItemList::EmitTraceSnapshot() const {
DisplayItemsTracingEnabled()));
}
-void DisplayItemList::GatherPixelRefs(const gfx::Size& grid_cell_size) {
+void DisplayItemList::GenerateDiscardableImagesMetadata() {
DCHECK(ProcessAppendedItemsCalled());
// This should be only called once, and only after CreateAndCacheSkPicture.
DCHECK(picture_);
- DCHECK(!pixel_refs_);
- pixel_refs_ = make_scoped_ptr(new PixelRefMap(grid_cell_size));
+ DCHECK(image_map_.empty());
if (!picture_->willPlayBackBitmaps())
return;
- pixel_refs_->GatherPixelRefsFromPicture(picture_.get());
+ // The cached picture is translated by -layer_rect_.origin during record,
+ // so we need to offset that back in order to get right positioning for
+ // images.
+ DiscardableImageMap::ScopedMetadataGenerator generator(
+ &image_map_, gfx::Size(layer_rect_.right(), layer_rect_.bottom()));
+ generator.canvas()->translate(layer_rect_.x(), layer_rect_.y());
+ generator.canvas()->drawPicture(picture_.get());
}
-void* DisplayItemList::GetSidecar(DisplayItem* display_item) {
- return items_.GetSidecar(display_item);
+void DisplayItemList::GetDiscardableImagesInRect(
+ const gfx::Rect& rect,
+ std::vector<PositionImage>* images) {
+ image_map_.GetDiscardableImagesInRect(rect, images);
}
} // namespace cc
diff --git a/chromium/cc/playback/display_item_list.h b/chromium/cc/playback/display_item_list.h
index 35bcb8cc4b6..12ad23cdad5 100644
--- a/chromium/cc/playback/display_item_list.h
+++ b/chromium/cc/playback/display_item_list.h
@@ -10,10 +10,9 @@
#include "base/memory/scoped_ptr.h"
#include "base/trace_event/trace_event.h"
#include "cc/base/cc_export.h"
-#include "cc/base/scoped_ptr_vector.h"
-#include "cc/base/sidecar_list_container.h"
+#include "cc/base/list_container.h"
+#include "cc/playback/discardable_image_map.h"
#include "cc/playback/display_item.h"
-#include "cc/playback/pixel_ref_map.h"
#include "skia/ext/refptr.h"
#include "third_party/skia/include/core/SkPicture.h"
#include "ui/gfx/geometry/rect.h"
@@ -28,16 +27,13 @@ class DisplayItemListSettings;
class CC_EXPORT DisplayItemList
: public base::RefCountedThreadSafe<DisplayItemList> {
public:
- static scoped_refptr<DisplayItemList> CreateWithoutCachedPicture(
- const DisplayItemListSettings& settings);
-
- // Creates a display item list with the given cull rect (if picture caching
- // is used). The resulting display list will not support sidecar data.
- static scoped_refptr<DisplayItemList> Create(gfx::Rect layer_rect,
- bool use_cached_picture);
-
+ // Creates a display item list. If picture caching is used, then layer_rect
+ // specifies the cull rect of the display item list (the picture will not
+ // exceed this rect). If picture caching is not used, then the given rect can
+ // be empty.
+ // TODO(vmpstr): Maybe this cull rect can be part of the settings instead.
static scoped_refptr<DisplayItemList> Create(
- gfx::Rect layer_rect,
+ const gfx::Rect& layer_rect,
const DisplayItemListSettings& settings);
void Raster(SkCanvas* canvas,
@@ -71,6 +67,7 @@ class CC_EXPORT DisplayItemList
bool IsSuitableForGpuRasterization() const;
int ApproximateOpCount() const;
size_t ApproximateMemoryUsage() const;
+ bool ShouldBeAnalyzedForSolidColor() const;
bool RetainsIndividualDisplayItems() const;
@@ -79,17 +76,14 @@ class CC_EXPORT DisplayItemList
void EmitTraceSnapshot() const;
- void GatherPixelRefs(const gfx::Size& grid_cell_size);
-
- // Finds the sidecar for a display item in this list.
- void* GetSidecar(DisplayItem* display_item);
+ void GenerateDiscardableImagesMetadata();
+ void GetDiscardableImagesInRect(const gfx::Rect& rect,
+ std::vector<PositionImage>* images);
private:
DisplayItemList(gfx::Rect layer_rect,
const DisplayItemListSettings& display_list_settings,
bool retain_individual_display_items);
- DisplayItemList(gfx::Rect layer_rect,
- const DisplayItemListSettings& display_list_settings);
~DisplayItemList();
// While appending new items, if they are not being retained, this can process
@@ -103,16 +97,16 @@ class CC_EXPORT DisplayItemList
bool ProcessAppendedItemsCalled() const { return true; }
#endif
- SidecarListContainer<DisplayItem> items_;
+ ListContainer<DisplayItem> items_;
skia::RefPtr<SkPicture> picture_;
scoped_ptr<SkPictureRecorder> recorder_;
skia::RefPtr<SkCanvas> canvas_;
- bool use_cached_picture_;
+ const bool use_cached_picture_;
bool retain_individual_display_items_;
gfx::Rect layer_rect_;
- bool all_items_are_suitable_for_gpu_rasterization_;
+ bool is_suitable_for_gpu_rasterization_;
int approximate_op_count_;
// Memory usage due to the cached SkPicture.
@@ -121,10 +115,9 @@ class CC_EXPORT DisplayItemList
// Memory usage due to external data held by display items.
size_t external_memory_usage_;
- scoped_ptr<PixelRefMap> pixel_refs_;
+ DiscardableImageMap image_map_;
friend class base::RefCountedThreadSafe<DisplayItemList>;
- friend class PixelRefMap::Iterator;
FRIEND_TEST_ALL_PREFIXES(DisplayItemListTest, ApproximateMemoryUsage);
DISALLOW_COPY_AND_ASSIGN(DisplayItemList);
};
diff --git a/chromium/cc/playback/display_item_list_bounds_calculator.cc b/chromium/cc/playback/display_item_list_bounds_calculator.cc
new file mode 100644
index 00000000000..b6dfdd58871
--- /dev/null
+++ b/chromium/cc/playback/display_item_list_bounds_calculator.cc
@@ -0,0 +1,61 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/playback/display_item_list_bounds_calculator.h"
+
+#include "base/logging.h"
+#include "ui/gfx/skia_util.h"
+
+namespace cc {
+
+DisplayItemListBoundsCalculator::DisplayItemListBoundsCalculator() {
+ matrix_stack_.push_back(SkMatrix::I());
+}
+
+DisplayItemListBoundsCalculator::~DisplayItemListBoundsCalculator() {}
+
+void DisplayItemListBoundsCalculator::AddStartingDisplayItem() {
+ bounds_.push_back(gfx::RectF());
+ started_items_indices_.push_back(bounds_.size() - 1);
+}
+
+void DisplayItemListBoundsCalculator::AddEndingDisplayItem() {
+ size_t last_start_index = started_items_indices_.back();
+ started_items_indices_.pop_back();
+
+ // Ending bounds match the starting bounds.
+ bounds_.push_back(bounds_[last_start_index]);
+
+ // The block that ended just now needs to be considered in the bounds of the
+ // enclosing block.
+ if (!started_items_indices_.empty())
+ bounds_[started_items_indices_.back()].Union(bounds_.back());
+}
+
+void DisplayItemListBoundsCalculator::AddDisplayItemWithBounds(
+ const SkRect& rect) {
+ SkRect target_rect;
+ matrix()->mapRect(&target_rect, rect);
+ bounds_.push_back(gfx::SkRectToRectF(target_rect));
+ if (!started_items_indices_.empty())
+ bounds_[started_items_indices_.back()].Union(bounds_.back());
+}
+
+void DisplayItemListBoundsCalculator::Save() {
+ matrix_stack_.push_back(matrix_stack_.back());
+}
+
+void DisplayItemListBoundsCalculator::Restore() {
+ DCHECK_GT(matrix_stack_.size(), 1u);
+ matrix_stack_.pop_back();
+}
+
+void DisplayItemListBoundsCalculator::Finalize() {
+ while (!started_items_indices_.empty()) {
+ bounds_[started_items_indices_.back()].Union(bounds_.back());
+ started_items_indices_.pop_back();
+ }
+}
+
+} // namespace cc
diff --git a/chromium/cc/playback/display_item_list_bounds_calculator.h b/chromium/cc/playback/display_item_list_bounds_calculator.h
new file mode 100644
index 00000000000..8a84e346ae2
--- /dev/null
+++ b/chromium/cc/playback/display_item_list_bounds_calculator.h
@@ -0,0 +1,39 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_PLAYBACK_DISPLAY_ITEM_LIST_BOUNDS_CALCULATOR_H_
+#define CC_PLAYBACK_DISPLAY_ITEM_LIST_BOUNDS_CALCULATOR_H_
+
+#include <vector>
+
+#include "third_party/skia/include/core/SkMatrix.h"
+#include "ui/gfx/geometry/rect_f.h"
+
+namespace cc {
+
+class DisplayItemListBoundsCalculator {
+ public:
+ DisplayItemListBoundsCalculator();
+ ~DisplayItemListBoundsCalculator();
+
+ void AddStartingDisplayItem();
+ void AddEndingDisplayItem();
+ void AddDisplayItemWithBounds(const SkRect& rect);
+ void Finalize();
+
+ void Save();
+ void Restore();
+ SkMatrix* matrix() { return &matrix_stack_.back(); }
+
+ void TakeBounds(std::vector<gfx::RectF>* bounds) { bounds->swap(bounds_); }
+
+ private:
+ std::vector<gfx::RectF> bounds_;
+ std::vector<size_t> started_items_indices_;
+ std::vector<SkMatrix> matrix_stack_;
+};
+
+} // namespace cc
+
+#endif // CC_PLAYBACK_DISPLAY_ITEM_LIST_BOUNDS_CALCULATOR_H_
diff --git a/chromium/cc/playback/display_item_list_settings.cc b/chromium/cc/playback/display_item_list_settings.cc
index e471d7e54ca..c71d9eecc3e 100644
--- a/chromium/cc/playback/display_item_list_settings.cc
+++ b/chromium/cc/playback/display_item_list_settings.cc
@@ -7,10 +7,7 @@
namespace cc {
DisplayItemListSettings::DisplayItemListSettings()
- : use_cached_picture(false),
- max_sidecar_size(0),
- sidecar_destroyer([](void* sidecar) {}) {
-}
+ : use_cached_picture(false) {}
DisplayItemListSettings::~DisplayItemListSettings() {
}
diff --git a/chromium/cc/playback/display_item_list_settings.h b/chromium/cc/playback/display_item_list_settings.h
index 277a2ea8da9..85fe8db3fa6 100644
--- a/chromium/cc/playback/display_item_list_settings.h
+++ b/chromium/cc/playback/display_item_list_settings.h
@@ -18,10 +18,6 @@ class CC_EXPORT DisplayItemListSettings {
// If set, a picture will be cached inside the DisplayItemList.
bool use_cached_picture;
-
- // Settings that control sidecar data.
- size_t max_sidecar_size;
- void (*sidecar_destroyer)(void* sidecar);
};
} // namespace cc
diff --git a/chromium/cc/playback/display_item_list_unittest.cc b/chromium/cc/playback/display_item_list_unittest.cc
index 89d4970da8a..c490bbfab73 100644
--- a/chromium/cc/playback/display_item_list_unittest.cc
+++ b/chromium/cc/playback/display_item_list_unittest.cc
@@ -20,7 +20,8 @@
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkPictureRecorder.h"
-#include "third_party/skia/include/effects/SkBitmapSource.h"
+#include "third_party/skia/include/core/SkSurface.h"
+#include "third_party/skia/include/effects/SkImageSource.h"
#include "third_party/skia/include/utils/SkPictureUtils.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/skia_util.h"
@@ -37,12 +38,13 @@ TEST(DisplayItemListTest, SingleDrawingItem) {
SkPaint red_paint;
red_paint.setColor(SK_ColorRED);
unsigned char pixels[4 * 100 * 100] = {0};
- const bool use_cached_picture = true;
+ DisplayItemListSettings settings;
+ settings.use_cached_picture = true;
scoped_refptr<DisplayItemList> list =
- DisplayItemList::Create(layer_rect, use_cached_picture);
+ DisplayItemList::Create(layer_rect, settings);
gfx::PointF offset(8.f, 9.f);
- gfx::RectF recording_rect(offset, layer_rect.size());
+ gfx::RectF recording_rect(offset, gfx::SizeF(layer_rect.size()));
canvas = skia::SharePtr(
recorder.beginRecording(gfx::RectFToSkRect(recording_rect)));
canvas->translate(offset.x(), offset.y());
@@ -81,12 +83,13 @@ TEST(DisplayItemListTest, ClipItem) {
SkPaint red_paint;
red_paint.setColor(SK_ColorRED);
unsigned char pixels[4 * 100 * 100] = {0};
- const bool use_cached_picture = true;
+ DisplayItemListSettings settings;
+ settings.use_cached_picture = true;
scoped_refptr<DisplayItemList> list =
- DisplayItemList::Create(layer_rect, use_cached_picture);
+ DisplayItemList::Create(layer_rect, settings);
gfx::PointF first_offset(8.f, 9.f);
- gfx::RectF first_recording_rect(first_offset, layer_rect.size());
+ gfx::RectF first_recording_rect(first_offset, gfx::SizeF(layer_rect.size()));
canvas = skia::SharePtr(
recorder.beginRecording(gfx::RectFToSkRect(first_recording_rect)));
canvas->translate(first_offset.x(), first_offset.y());
@@ -100,7 +103,8 @@ TEST(DisplayItemListTest, ClipItem) {
item2->SetNew(clip_rect, std::vector<SkRRect>());
gfx::PointF second_offset(2.f, 3.f);
- gfx::RectF second_recording_rect(second_offset, layer_rect.size());
+ gfx::RectF second_recording_rect(second_offset,
+ gfx::SizeF(layer_rect.size()));
canvas = skia::SharePtr(
recorder.beginRecording(gfx::RectFToSkRect(second_recording_rect)));
canvas->translate(second_offset.x(), second_offset.y());
@@ -142,12 +146,13 @@ TEST(DisplayItemListTest, TransformItem) {
SkPaint red_paint;
red_paint.setColor(SK_ColorRED);
unsigned char pixels[4 * 100 * 100] = {0};
- const bool use_cached_picture = true;
+ DisplayItemListSettings settings;
+ settings.use_cached_picture = true;
scoped_refptr<DisplayItemList> list =
- DisplayItemList::Create(layer_rect, use_cached_picture);
+ DisplayItemList::Create(layer_rect, settings);
gfx::PointF first_offset(8.f, 9.f);
- gfx::RectF first_recording_rect(first_offset, layer_rect.size());
+ gfx::RectF first_recording_rect(first_offset, gfx::SizeF(layer_rect.size()));
canvas = skia::SharePtr(
recorder.beginRecording(gfx::RectFToSkRect(first_recording_rect)));
canvas->translate(first_offset.x(), first_offset.y());
@@ -162,7 +167,8 @@ TEST(DisplayItemListTest, TransformItem) {
item2->SetNew(transform);
gfx::PointF second_offset(2.f, 3.f);
- gfx::RectF second_recording_rect(second_offset, layer_rect.size());
+ gfx::RectF second_recording_rect(second_offset,
+ gfx::SizeF(layer_rect.size()));
canvas = skia::SharePtr(
recorder.beginRecording(gfx::RectFToSkRect(second_recording_rect)));
canvas->translate(second_offset.x(), second_offset.y());
@@ -198,28 +204,31 @@ TEST(DisplayItemListTest, FilterItem) {
gfx::Rect layer_rect(100, 100);
FilterOperations filters;
unsigned char pixels[4 * 100 * 100] = {0};
- const bool use_cached_picture = true;
+ DisplayItemListSettings settings;
+ settings.use_cached_picture = true;
scoped_refptr<DisplayItemList> list =
- DisplayItemList::Create(layer_rect, use_cached_picture);
+ DisplayItemList::Create(layer_rect, settings);
- SkBitmap source_bitmap;
- source_bitmap.allocN32Pixels(50, 50);
- SkCanvas source_canvas(source_bitmap);
- source_canvas.clear(SkColorSetRGB(128, 128, 128));
+ skia::RefPtr<SkSurface> source_surface =
+ skia::AdoptRef(SkSurface::NewRasterN32Premul(50, 50));
+ SkCanvas* source_canvas = source_surface->getCanvas();
+ source_canvas->clear(SkColorSetRGB(128, 128, 128));
+ skia::RefPtr<SkImage> source_image =
+ skia::AdoptRef(source_surface->newImageSnapshot());
// For most SkImageFilters, the |dst| bounds computed by computeFastBounds are
// dependent on the provided |src| bounds. This means, for example, that
// translating |src| results in a corresponding translation of |dst|. But this
// is not the case for all SkImageFilters; for some of them (e.g.
- // SkBitmapSource), the computation of |dst| in computeFastBounds doesn't
+ // SkImageSource), the computation of |dst| in computeFastBounds doesn't
// involve |src| at all. Incorrectly assuming such a relationship (e.g. by
// translating |dst| after it is computed by computeFastBounds, rather than
// translating |src| before it provided to computedFastBounds) can cause
// incorrect clipping of filter output. To test for this, we include an
- // SkBitmapSource filter in |filters|. Here, |src| is |filter_bounds|, defined
+ // SkImageSource filter in |filters|. Here, |src| is |filter_bounds|, defined
// below.
skia::RefPtr<SkImageFilter> image_filter =
- skia::AdoptRef(SkBitmapSource::Create(source_bitmap));
+ skia::AdoptRef(SkImageSource::Create(source_image.get()));
filters.Append(FilterOperation::CreateReferenceFilter(image_filter));
filters.Append(FilterOperation::CreateBrightnessFilter(0.5f));
gfx::RectF filter_bounds(10.f, 10.f, 50.f, 50.f);
@@ -255,11 +264,12 @@ TEST(DisplayItemListTest, CompactingItems) {
unsigned char pixels[4 * 100 * 100] = {0};
gfx::PointF offset(8.f, 9.f);
- gfx::RectF recording_rect(offset, layer_rect.size());
+ gfx::RectF recording_rect(offset, gfx::SizeF(layer_rect.size()));
- bool use_cached_picture = false;
+ DisplayItemListSettings no_caching_settings;
+ no_caching_settings.use_cached_picture = false;
scoped_refptr<DisplayItemList> list_without_caching =
- DisplayItemList::Create(layer_rect, use_cached_picture);
+ DisplayItemList::Create(layer_rect, no_caching_settings);
canvas = skia::SharePtr(
recorder.beginRecording(gfx::RectFToSkRect(recording_rect)));
@@ -273,9 +283,10 @@ TEST(DisplayItemListTest, CompactingItems) {
DrawDisplayList(pixels, layer_rect, list_without_caching);
unsigned char expected_pixels[4 * 100 * 100] = {0};
- use_cached_picture = true;
+ DisplayItemListSettings caching_settings;
+ caching_settings.use_cached_picture = true;
scoped_refptr<DisplayItemList> list_with_caching =
- DisplayItemList::Create(layer_rect, use_cached_picture);
+ DisplayItemList::Create(layer_rect, caching_settings);
auto* item2 = list_with_caching->CreateAndAppendItem<DrawingDisplayItem>();
item2->SetNew(picture);
list_with_caching->Finalize();
@@ -290,9 +301,10 @@ TEST(DisplayItemListTest, IsSuitableForGpuRasterizationWithCachedPicture) {
skia::RefPtr<SkCanvas> canvas;
skia::RefPtr<SkPicture> picture;
- bool use_cached_picture = true;
+ DisplayItemListSettings settings;
+ settings.use_cached_picture = true;
scoped_refptr<DisplayItemList> list =
- DisplayItemList::Create(layer_rect, use_cached_picture);
+ DisplayItemList::Create(layer_rect, settings);
canvas =
skia::SharePtr(recorder.beginRecording(gfx::RectToSkRect(layer_rect)));
@@ -317,7 +329,7 @@ TEST(DisplayItemListTest, IsSuitableForGpuRasterizationWithCachedPicture) {
// a veto.
EXPECT_TRUE(list->IsSuitableForGpuRasterization());
- list = DisplayItemList::Create(layer_rect, use_cached_picture);
+ list = DisplayItemList::Create(layer_rect, settings);
canvas =
skia::SharePtr(recorder.beginRecording(gfx::RectToSkRect(layer_rect)));
for (int i = 0; i < 10; ++i)
@@ -331,7 +343,7 @@ TEST(DisplayItemListTest, IsSuitableForGpuRasterizationWithCachedPicture) {
// trigger a veto.
EXPECT_FALSE(list->IsSuitableForGpuRasterization());
- list = DisplayItemList::Create(layer_rect, use_cached_picture);
+ list = DisplayItemList::Create(layer_rect, settings);
for (int i = 0; i < 10; ++i) {
canvas =
skia::SharePtr(recorder.beginRecording(gfx::RectToSkRect(layer_rect)));
@@ -353,9 +365,10 @@ TEST(DisplayItemListTest, IsSuitableForGpuRasterizationWithoutCachedPicture) {
skia::RefPtr<SkCanvas> canvas;
skia::RefPtr<SkPicture> picture;
- bool use_cached_picture = false;
+ DisplayItemListSettings settings;
+ settings.use_cached_picture = false;
scoped_refptr<DisplayItemList> list =
- DisplayItemList::Create(layer_rect, use_cached_picture);
+ DisplayItemList::Create(layer_rect, settings);
canvas =
skia::SharePtr(recorder.beginRecording(gfx::RectToSkRect(layer_rect)));
@@ -380,7 +393,7 @@ TEST(DisplayItemListTest, IsSuitableForGpuRasterizationWithoutCachedPicture) {
// a veto.
EXPECT_TRUE(list->IsSuitableForGpuRasterization());
- list = DisplayItemList::Create(layer_rect, use_cached_picture);
+ list = DisplayItemList::Create(layer_rect, settings);
canvas =
skia::SharePtr(recorder.beginRecording(gfx::RectToSkRect(layer_rect)));
for (int i = 0; i < 10; ++i)
@@ -394,7 +407,7 @@ TEST(DisplayItemListTest, IsSuitableForGpuRasterizationWithoutCachedPicture) {
// trigger a veto.
EXPECT_FALSE(list->IsSuitableForGpuRasterization());
- list = DisplayItemList::Create(layer_rect, use_cached_picture);
+ list = DisplayItemList::Create(layer_rect, settings);
for (int i = 0; i < 10; ++i) {
canvas =
skia::SharePtr(recorder.beginRecording(gfx::RectToSkRect(layer_rect)));
@@ -421,7 +434,7 @@ TEST(DisplayItemListTest, ApproximateMemoryUsage) {
SkPictureRecorder recorder;
SkPaint blue_paint;
blue_paint.setColor(SK_ColorBLUE);
- SkCanvas* canvas = recorder.beginRecording(gfx::RectFToSkRect(layer_rect));
+ SkCanvas* canvas = recorder.beginRecording(gfx::RectToSkRect(layer_rect));
for (int i = 0; i < kNumCommandsInTestSkPicture; i++)
canvas->drawPaint(blue_paint);
skia::RefPtr<SkPicture> picture =
@@ -430,7 +443,9 @@ TEST(DisplayItemListTest, ApproximateMemoryUsage) {
ASSERT_GE(picture_size, kNumCommandsInTestSkPicture * sizeof(blue_paint));
// Using a cached picture, we should get about the right size.
- list = DisplayItemList::Create(layer_rect, true);
+ DisplayItemListSettings caching_settings;
+ caching_settings.use_cached_picture = true;
+ list = DisplayItemList::Create(layer_rect, caching_settings);
auto* item = list->CreateAndAppendItem<DrawingDisplayItem>();
item->SetNew(picture);
list->Finalize();
@@ -439,7 +454,9 @@ TEST(DisplayItemListTest, ApproximateMemoryUsage) {
EXPECT_LE(memory_usage, 2 * picture_size);
// Using no cached picture, we should still get the right size.
- list = DisplayItemList::Create(layer_rect, false);
+ DisplayItemListSettings no_caching_settings;
+ no_caching_settings.use_cached_picture = false;
+ list = DisplayItemList::Create(layer_rect, no_caching_settings);
item = list->CreateAndAppendItem<DrawingDisplayItem>();
item->SetNew(picture);
list->Finalize();
@@ -450,9 +467,7 @@ TEST(DisplayItemListTest, ApproximateMemoryUsage) {
// To avoid double counting, we expect zero size to be computed if both the
// picture and items are retained (currently this only happens due to certain
// categories being traced).
- DisplayItemListSettings settings;
- settings.use_cached_picture = true;
- list = new DisplayItemList(layer_rect, settings, true);
+ list = new DisplayItemList(layer_rect, caching_settings, true);
item = list->CreateAndAppendItem<DrawingDisplayItem>();
item->SetNew(picture);
list->Finalize();
diff --git a/chromium/cc/playback/display_list_raster_source.cc b/chromium/cc/playback/display_list_raster_source.cc
index 4911e846029..215f7d75a53 100644
--- a/chromium/cc/playback/display_list_raster_source.cc
+++ b/chromium/cc/playback/display_list_raster_source.cc
@@ -25,20 +25,21 @@ DisplayListRasterSource::CreateFromDisplayListRecordingSource(
}
DisplayListRasterSource::DisplayListRasterSource()
- : background_color_(SK_ColorTRANSPARENT),
+ : painter_reported_memory_usage_(0),
+ background_color_(SK_ColorTRANSPARENT),
requires_clear_(true),
can_use_lcd_text_(true),
is_solid_color_(false),
solid_color_(SK_ColorTRANSPARENT),
clear_canvas_with_debug_color_(false),
slow_down_raster_scale_factor_for_debug_(0),
- should_attempt_to_use_distance_field_text_(false) {
-}
+ should_attempt_to_use_distance_field_text_(false) {}
DisplayListRasterSource::DisplayListRasterSource(
const DisplayListRecordingSource* other,
bool can_use_lcd_text)
: display_list_(other->display_list_),
+ painter_reported_memory_usage_(other->painter_reported_memory_usage_),
background_color_(other->background_color_),
requires_clear_(other->requires_clear_),
can_use_lcd_text_(can_use_lcd_text),
@@ -49,13 +50,13 @@ DisplayListRasterSource::DisplayListRasterSource(
clear_canvas_with_debug_color_(other->clear_canvas_with_debug_color_),
slow_down_raster_scale_factor_for_debug_(
other->slow_down_raster_scale_factor_for_debug_),
- should_attempt_to_use_distance_field_text_(false) {
-}
+ should_attempt_to_use_distance_field_text_(false) {}
DisplayListRasterSource::DisplayListRasterSource(
const DisplayListRasterSource* other,
bool can_use_lcd_text)
: display_list_(other->display_list_),
+ painter_reported_memory_usage_(other->painter_reported_memory_usage_),
background_color_(other->background_color_),
requires_clear_(other->requires_clear_),
can_use_lcd_text_(can_use_lcd_text),
@@ -67,8 +68,7 @@ DisplayListRasterSource::DisplayListRasterSource(
slow_down_raster_scale_factor_for_debug_(
other->slow_down_raster_scale_factor_for_debug_),
should_attempt_to_use_distance_field_text_(
- other->should_attempt_to_use_distance_field_text_) {
-}
+ other->should_attempt_to_use_distance_field_text_) {}
DisplayListRasterSource::~DisplayListRasterSource() {
}
@@ -108,7 +108,7 @@ void DisplayListRasterSource::RasterCommon(
float contents_scale) const {
canvas->translate(-canvas_bitmap_rect.x(), -canvas_bitmap_rect.y());
gfx::Rect content_rect =
- gfx::ToEnclosingRect(gfx::ScaleRect(gfx::Rect(size_), contents_scale));
+ gfx::ScaleToEnclosingRect(gfx::Rect(size_), contents_scale);
content_rect.Intersect(canvas_playback_rect);
canvas->clipRect(gfx::RectToSkRect(content_rect), SkRegion::kIntersect_Op);
@@ -116,8 +116,11 @@ void DisplayListRasterSource::RasterCommon(
DCHECK(display_list_.get());
gfx::Rect canvas_target_playback_rect =
canvas_playback_rect - canvas_bitmap_rect.OffsetFromOrigin();
- display_list_->Raster(canvas, callback, canvas_target_playback_rect,
- contents_scale);
+ int repeat_count = std::max(1, slow_down_raster_scale_factor_for_debug_);
+ for (int i = 0; i < repeat_count; ++i) {
+ display_list_->Raster(canvas, callback, canvas_target_playback_rect,
+ contents_scale);
+ }
}
skia::RefPtr<SkPicture> DisplayListRasterSource::GetFlattenedPicture() {
@@ -138,7 +141,8 @@ skia::RefPtr<SkPicture> DisplayListRasterSource::GetFlattenedPicture() {
size_t DisplayListRasterSource::GetPictureMemoryUsage() const {
if (!display_list_)
return 0;
- return display_list_->ApproximateMemoryUsage();
+ return display_list_->ApproximateMemoryUsage() +
+ painter_reported_memory_usage_;
}
void DisplayListRasterSource::PerformSolidColorAnalysis(
@@ -157,31 +161,19 @@ void DisplayListRasterSource::PerformSolidColorAnalysis(
analysis->is_solid_color = canvas.GetColorIfSolid(&analysis->solid_color);
}
-void DisplayListRasterSource::GatherPixelRefs(
- const gfx::Rect& content_rect,
- float contents_scale,
- std::vector<SkPixelRef*>* pixel_refs) const {
- DCHECK_EQ(0u, pixel_refs->size());
-
- gfx::Rect layer_rect =
- gfx::ScaleToEnclosingRect(content_rect, 1.0f / contents_scale);
-
- PixelRefMap::Iterator iterator(layer_rect, display_list_.get());
- while (iterator) {
- pixel_refs->push_back(*iterator);
- ++iterator;
- }
+void DisplayListRasterSource::GetDiscardableImagesInRect(
+ const gfx::Rect& layer_rect,
+ std::vector<PositionImage>* images) const {
+ DCHECK_EQ(0u, images->size());
+ display_list_->GetDiscardableImagesInRect(layer_rect, images);
}
-bool DisplayListRasterSource::CoversRect(const gfx::Rect& content_rect,
- float contents_scale) const {
+bool DisplayListRasterSource::CoversRect(const gfx::Rect& layer_rect) const {
if (size_.IsEmpty())
return false;
- gfx::Rect layer_rect =
- gfx::ScaleToEnclosingRect(content_rect, 1.f / contents_scale);
- layer_rect.Intersect(gfx::Rect(size_));
-
- return recorded_viewport_.Contains(layer_rect);
+ gfx::Rect bounded_rect = layer_rect;
+ bounded_rect.Intersect(gfx::Rect(size_));
+ return recorded_viewport_.Contains(bounded_rect);
}
gfx::Size DisplayListRasterSource::GetSize() const {
@@ -201,6 +193,10 @@ bool DisplayListRasterSource::HasRecordings() const {
return !!display_list_.get();
}
+gfx::Rect DisplayListRasterSource::RecordedViewport() const {
+ return recorded_viewport_;
+}
+
void DisplayListRasterSource::SetShouldAttemptToUseDistanceFieldText() {
should_attempt_to_use_distance_field_text_ = true;
}
diff --git a/chromium/cc/playback/display_list_raster_source.h b/chromium/cc/playback/display_list_raster_source.h
index 24faa33c7fc..8b49b670d42 100644
--- a/chromium/cc/playback/display_list_raster_source.h
+++ b/chromium/cc/playback/display_list_raster_source.h
@@ -40,12 +40,12 @@ class CC_EXPORT DisplayListRasterSource : public RasterSource {
bool IsSolidColor() const override;
SkColor GetSolidColor() const override;
gfx::Size GetSize() const override;
- void GatherPixelRefs(const gfx::Rect& content_rect,
- float contents_scale,
- std::vector<SkPixelRef*>* pixel_refs) const override;
- bool CoversRect(const gfx::Rect& content_rect,
- float contents_scale) const override;
+ void GetDiscardableImagesInRect(
+ const gfx::Rect& layer_rect,
+ std::vector<PositionImage>* images) const override;
+ bool CoversRect(const gfx::Rect& layer_rect) const override;
bool HasRecordings() const override;
+ gfx::Rect RecordedViewport() const override;
void SetShouldAttemptToUseDistanceFieldText() override;
bool ShouldAttemptToUseDistanceFieldText() const override;
void DidBeginTracing() override;
@@ -66,6 +66,7 @@ class CC_EXPORT DisplayListRasterSource : public RasterSource {
// These members are const as this raster source may be in use on another
// thread and so should not be touched after construction.
const scoped_refptr<DisplayItemList> display_list_;
+ const size_t painter_reported_memory_usage_;
const SkColor background_color_;
const bool requires_clear_;
const bool can_use_lcd_text_;
diff --git a/chromium/cc/playback/display_list_raster_source_unittest.cc b/chromium/cc/playback/display_list_raster_source_unittest.cc
index d936af51f9c..9322a765a80 100644
--- a/chromium/cc/playback/display_list_raster_source_unittest.cc
+++ b/chromium/cc/playback/display_list_raster_source_unittest.cc
@@ -175,10 +175,10 @@ TEST(DisplayListRasterSourceTest, PixelRefIteratorDiscardableRefsOneTile) {
scoped_ptr<FakeDisplayListRecordingSource> recording_source =
FakeDisplayListRecordingSource::CreateFilledRecordingSource(layer_bounds);
- SkBitmap discardable_bitmap[2][2];
- CreateBitmap(gfx::Size(32, 32), "discardable", &discardable_bitmap[0][0]);
- CreateBitmap(gfx::Size(32, 32), "discardable", &discardable_bitmap[0][1]);
- CreateBitmap(gfx::Size(32, 32), "discardable", &discardable_bitmap[1][1]);
+ skia::RefPtr<SkImage> discardable_image[2][2];
+ discardable_image[0][0] = CreateDiscardableImage(gfx::Size(32, 32));
+ discardable_image[0][1] = CreateDiscardableImage(gfx::Size(32, 32));
+ discardable_image[1][1] = CreateDiscardableImage(gfx::Size(32, 32));
// Discardable pixel refs are found in the following cells:
// |---|---|
@@ -186,12 +186,13 @@ TEST(DisplayListRasterSourceTest, PixelRefIteratorDiscardableRefsOneTile) {
// |---|---|
// | | x |
// |---|---|
- recording_source->add_draw_bitmap(discardable_bitmap[0][0], gfx::Point(0, 0));
- recording_source->add_draw_bitmap(discardable_bitmap[0][1],
- gfx::Point(260, 0));
- recording_source->add_draw_bitmap(discardable_bitmap[1][1],
- gfx::Point(260, 260));
- recording_source->SetGatherPixelRefs(true);
+ recording_source->add_draw_image(discardable_image[0][0].get(),
+ gfx::Point(0, 0));
+ recording_source->add_draw_image(discardable_image[0][1].get(),
+ gfx::Point(260, 0));
+ recording_source->add_draw_image(discardable_image[1][1].get(),
+ gfx::Point(260, 260));
+ recording_source->SetGenerateDiscardableImagesMetadata(true);
recording_source->Rerecord();
scoped_refptr<DisplayListRasterSource> raster =
@@ -200,72 +201,42 @@ TEST(DisplayListRasterSourceTest, PixelRefIteratorDiscardableRefsOneTile) {
// Tile sized iterators. These should find only one pixel ref.
{
- std::vector<SkPixelRef*> pixel_refs;
- raster->GatherPixelRefs(gfx::Rect(0, 0, 256, 256), 1.0, &pixel_refs);
- EXPECT_EQ(1u, pixel_refs.size());
- EXPECT_EQ(discardable_bitmap[0][0].pixelRef(), pixel_refs[0]);
- }
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster->GatherPixelRefs(gfx::Rect(0, 0, 512, 512), 2.0, &pixel_refs);
- EXPECT_EQ(1u, pixel_refs.size());
- EXPECT_EQ(discardable_bitmap[0][0].pixelRef(), pixel_refs[0]);
- }
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster->GatherPixelRefs(gfx::Rect(0, 0, 128, 128), 0.5, &pixel_refs);
- EXPECT_EQ(1u, pixel_refs.size());
- EXPECT_EQ(discardable_bitmap[0][0].pixelRef(), pixel_refs[0]);
+ std::vector<PositionImage> images;
+ raster->GetDiscardableImagesInRect(gfx::Rect(0, 0, 256, 256), &images);
+ EXPECT_EQ(1u, images.size());
+ EXPECT_EQ(discardable_image[0][0].get(), images[0].image);
+ EXPECT_EQ(gfx::RectF(32, 32).ToString(),
+ gfx::SkRectToRectF(images[0].image_rect).ToString());
}
// Shifted tile sized iterators. These should find only one pixel ref.
{
- std::vector<SkPixelRef*> pixel_refs;
- raster->GatherPixelRefs(gfx::Rect(260, 260, 256, 256), 1.0, &pixel_refs);
- EXPECT_EQ(1u, pixel_refs.size());
- EXPECT_EQ(discardable_bitmap[1][1].pixelRef(), pixel_refs[0]);
- }
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster->GatherPixelRefs(gfx::Rect(520, 520, 512, 512), 2.0, &pixel_refs);
- EXPECT_EQ(1u, pixel_refs.size());
- EXPECT_EQ(discardable_bitmap[1][1].pixelRef(), pixel_refs[0]);
- }
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster->GatherPixelRefs(gfx::Rect(130, 130, 128, 128), 0.5, &pixel_refs);
- EXPECT_EQ(1u, pixel_refs.size());
- EXPECT_EQ(discardable_bitmap[1][1].pixelRef(), pixel_refs[0]);
+ std::vector<PositionImage> images;
+ raster->GetDiscardableImagesInRect(gfx::Rect(260, 260, 256, 256), &images);
+ EXPECT_EQ(1u, images.size());
+ EXPECT_EQ(discardable_image[1][1].get(), images[0].image);
+ EXPECT_EQ(gfx::RectF(260, 260, 32, 32).ToString(),
+ gfx::SkRectToRectF(images[0].image_rect).ToString());
}
// Ensure there's no discardable pixel refs in the empty cell
{
- std::vector<SkPixelRef*> pixel_refs;
- raster->GatherPixelRefs(gfx::Rect(0, 256, 256, 256), 1.0, &pixel_refs);
- EXPECT_EQ(0u, pixel_refs.size());
+ std::vector<PositionImage> images;
+ raster->GetDiscardableImagesInRect(gfx::Rect(0, 256, 256, 256), &images);
+ EXPECT_EQ(0u, images.size());
}
// Layer sized iterators. These should find three pixel ref.
{
- std::vector<SkPixelRef*> pixel_refs;
- raster->GatherPixelRefs(gfx::Rect(0, 0, 512, 512), 1.0, &pixel_refs);
- EXPECT_EQ(3u, pixel_refs.size());
- EXPECT_EQ(discardable_bitmap[0][0].pixelRef(), pixel_refs[0]);
- EXPECT_EQ(discardable_bitmap[0][1].pixelRef(), pixel_refs[1]);
- EXPECT_EQ(discardable_bitmap[1][1].pixelRef(), pixel_refs[2]);
- }
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster->GatherPixelRefs(gfx::Rect(0, 0, 1024, 1024), 2.0, &pixel_refs);
- EXPECT_EQ(3u, pixel_refs.size());
- EXPECT_EQ(discardable_bitmap[0][0].pixelRef(), pixel_refs[0]);
- EXPECT_EQ(discardable_bitmap[0][1].pixelRef(), pixel_refs[1]);
- EXPECT_EQ(discardable_bitmap[1][1].pixelRef(), pixel_refs[2]);
- }
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster->GatherPixelRefs(gfx::Rect(0, 0, 256, 256), 0.5, &pixel_refs);
- EXPECT_EQ(3u, pixel_refs.size());
- EXPECT_EQ(discardable_bitmap[0][0].pixelRef(), pixel_refs[0]);
- EXPECT_EQ(discardable_bitmap[0][1].pixelRef(), pixel_refs[1]);
- EXPECT_EQ(discardable_bitmap[1][1].pixelRef(), pixel_refs[2]);
+ std::vector<PositionImage> images;
+ raster->GetDiscardableImagesInRect(gfx::Rect(0, 0, 512, 512), &images);
+ EXPECT_EQ(3u, images.size());
+ EXPECT_EQ(discardable_image[0][0].get(), images[0].image);
+ EXPECT_EQ(discardable_image[0][1].get(), images[1].image);
+ EXPECT_EQ(discardable_image[1][1].get(), images[2].image);
+ EXPECT_EQ(gfx::RectF(32, 32).ToString(),
+ gfx::SkRectToRectF(images[0].image_rect).ToString());
+ EXPECT_EQ(gfx::RectF(260, 0, 32, 32).ToString(),
+ gfx::SkRectToRectF(images[1].image_rect).ToString());
+ EXPECT_EQ(gfx::RectF(260, 260, 32, 32).ToString(),
+ gfx::SkRectToRectF(images[2].image_rect).ToString());
}
}
@@ -292,7 +263,7 @@ TEST(DisplayListRasterSourceTest, RasterFullContents) {
recording_source.get(), false);
gfx::Size content_bounds(
- gfx::ToCeiledSize(gfx::ScaleSize(layer_bounds, contents_scale)));
+ gfx::ScaleToCeiledSize(layer_bounds, contents_scale));
// Simulate drawing into different tiles at different offsets.
int step_x = std::ceil(content_bounds.width() / raster_divisions);
@@ -357,7 +328,7 @@ TEST(DisplayListRasterSourceTest, RasterPartialContents) {
recording_source.get(), false);
gfx::Size content_bounds(
- gfx::ToCeiledSize(gfx::ScaleSize(layer_bounds, contents_scale)));
+ gfx::ScaleToCeiledSize(layer_bounds, contents_scale));
SkBitmap bitmap;
bitmap.allocN32Pixels(content_bounds.width(), content_bounds.height());
@@ -453,7 +424,7 @@ TEST(DisplayListRasterSourceTest, RasterPartialClear) {
recording_source.get(), false);
gfx::Size content_bounds(
- gfx::ToCeiledSize(gfx::ScaleSize(layer_bounds, contents_scale)));
+ gfx::ScaleToCeiledSize(layer_bounds, contents_scale));
SkBitmap bitmap;
bitmap.allocN32Pixels(content_bounds.width(), content_bounds.height());
@@ -500,8 +471,8 @@ TEST(DisplayListRasterSourceTest, RasterPartialClear) {
// We're going to playback from alpha(18) white rectangle into a smaller area
// of the recording resulting in a smaller lighter white rectangle over a
// darker white background rectangle.
- playback_rect = gfx::Rect(
- gfx::ToCeiledSize(gfx::ScaleSize(partial_bounds, contents_scale)));
+ playback_rect =
+ gfx::Rect(gfx::ScaleToCeiledSize(partial_bounds, contents_scale));
raster->PlaybackToCanvas(&canvas, raster_full_rect, playback_rect,
contents_scale);
@@ -534,7 +505,7 @@ TEST(DisplayListRasterSourceTest, RasterContentsTransparent) {
DisplayListRasterSource::CreateFromDisplayListRecordingSource(
recording_source.get(), false);
gfx::Size content_bounds(
- gfx::ToCeiledSize(gfx::ScaleSize(layer_bounds, contents_scale)));
+ gfx::ScaleToCeiledSize(layer_bounds, contents_scale));
gfx::Rect canvas_rect(content_bounds);
canvas_rect.Inset(0, 0, -1, -1);
@@ -552,5 +523,22 @@ TEST(DisplayListRasterSourceTest, RasterContentsTransparent) {
}
}
+TEST(DisplayListRasterSourceTest,
+ GetPictureMemoryUsageIncludesClientReportedMemory) {
+ const size_t kReportedMemoryUsageInBytes = 100 * 1024 * 1024;
+ gfx::Size layer_bounds(5, 3);
+ scoped_ptr<FakeDisplayListRecordingSource> recording_source =
+ FakeDisplayListRecordingSource::CreateFilledRecordingSource(layer_bounds);
+ recording_source->set_reported_memory_usage(kReportedMemoryUsageInBytes);
+ recording_source->Rerecord();
+
+ scoped_refptr<DisplayListRasterSource> raster =
+ DisplayListRasterSource::CreateFromDisplayListRecordingSource(
+ recording_source.get(), false);
+ size_t total_memory_usage = raster->GetPictureMemoryUsage();
+ EXPECT_GE(total_memory_usage, kReportedMemoryUsageInBytes);
+ EXPECT_LT(total_memory_usage, 2 * kReportedMemoryUsageInBytes);
+}
+
} // namespace
} // namespace cc
diff --git a/chromium/cc/playback/display_list_recording_source.cc b/chromium/cc/playback/display_list_recording_source.cc
index e88343cb6b7..c790ebebe0f 100644
--- a/chromium/cc/playback/display_list_recording_source.cc
+++ b/chromium/cc/playback/display_list_recording_source.cc
@@ -6,6 +6,7 @@
#include <algorithm>
+#include "base/numerics/safe_math.h"
#include "cc/base/histograms.h"
#include "cc/base/region.h"
#include "cc/layers/content_layer_client.h"
@@ -18,10 +19,7 @@ namespace {
// Layout pixel buffer around the visible layer rect to record. Any base
// picture that intersects the visible layer rect expanded by this distance
// will be recorded.
-const int kPixelDistanceToRecord = 8000;
-// We don't perform solid color analysis on images that have more than 10 skia
-// operations.
-const int kOpCountThatIsOkToAnalyze = 10;
+const int kPixelDistanceToRecord = 4000;
// This is the distance, in layer space, by which the recorded viewport has to
// change before causing a paint of the new content. For example, it means
@@ -37,26 +35,23 @@ const bool kDefaultClearCanvasSetting = true;
DEFINE_SCOPED_UMA_HISTOGRAM_AREA_TIMER(
ScopedDisplayListRecordingSourceUpdateTimer,
- "Compositing.DisplayListRecordingSource.UpdateUs",
- "Compositing.DisplayListRecordingSource.UpdateInvalidatedAreaPerMs");
+ "Compositing.%s.DisplayListRecordingSource.UpdateUs",
+ "Compositing.%s.DisplayListRecordingSource.UpdateInvalidatedAreaPerMs");
} // namespace
namespace cc {
-DisplayListRecordingSource::DisplayListRecordingSource(
- const gfx::Size& grid_cell_size)
+DisplayListRecordingSource::DisplayListRecordingSource()
: slow_down_raster_scale_factor_for_debug_(0),
- gather_pixel_refs_(false),
+ generate_discardable_images_metadata_(false),
requires_clear_(false),
is_solid_color_(false),
clear_canvas_with_debug_color_(kDefaultClearCanvasSetting),
solid_color_(SK_ColorTRANSPARENT),
background_color_(SK_ColorTRANSPARENT),
pixel_record_distance_(kPixelDistanceToRecord),
- grid_cell_size_(grid_cell_size),
- is_suitable_for_gpu_rasterization_(true) {
-}
+ painter_reported_memory_usage_(0) {}
DisplayListRecordingSource::~DisplayListRecordingSource() {
}
@@ -153,8 +148,13 @@ bool DisplayListRecordingSource::UpdateAndExpandInvalidation(
// Count the area that is being invalidated.
Region recorded_invalidation(*invalidation);
recorded_invalidation.Intersect(recorded_viewport_);
- for (Region::Iterator it(recorded_invalidation); it.has_rect(); it.next())
- timer.AddArea(it.rect().size().GetArea());
+ for (Region::Iterator it(recorded_invalidation); it.has_rect(); it.next()) {
+ // gfx::Size::GetArea might overflow in this case, so use an explicit
+ // CheckedNumeric instead.
+ base::CheckedNumeric<int> checked_area = it.rect().size().width();
+ checked_area *= it.rect().size().height();
+ timer.AddArea(checked_area);
+ }
if (!updated && !invalidation->Intersects(recorded_viewport_))
return false;
@@ -180,23 +180,16 @@ bool DisplayListRecordingSource::UpdateAndExpandInvalidation(
NOTREACHED();
}
- int repeat_count = 1;
- if (slow_down_raster_scale_factor_for_debug_ > 1) {
- repeat_count = slow_down_raster_scale_factor_for_debug_;
- painting_control = ContentLayerClient::DISPLAY_LIST_CACHING_DISABLED;
- }
-
- for (int i = 0; i < repeat_count; ++i) {
- display_list_ = painter->PaintContentsToDisplayList(recorded_viewport_,
- painting_control);
- }
+ // TODO(vmpstr): Add a slow_down_recording_scale_factor_for_debug_ to be able
+ // to slow down recording.
+ display_list_ =
+ painter->PaintContentsToDisplayList(recorded_viewport_, painting_control);
+ painter_reported_memory_usage_ = painter->GetApproximateUnsharedMemoryUsage();
- is_suitable_for_gpu_rasterization_ =
- display_list_->IsSuitableForGpuRasterization();
DetermineIfSolidColor();
display_list_->EmitTraceSnapshot();
- if (gather_pixel_refs_)
- display_list_->GatherPixelRefs(grid_cell_size_);
+ if (generate_discardable_images_metadata_)
+ display_list_->GenerateDiscardableImagesMetadata();
return true;
}
@@ -214,8 +207,9 @@ void DisplayListRecordingSource::SetSlowdownRasterScaleFactor(int factor) {
slow_down_raster_scale_factor_for_debug_ = factor;
}
-void DisplayListRecordingSource::SetGatherPixelRefs(bool gather_pixel_refs) {
- gather_pixel_refs_ = gather_pixel_refs;
+void DisplayListRecordingSource::SetGenerateDiscardableImagesMetadata(
+ bool generate_metadata) {
+ generate_discardable_images_metadata_ = generate_metadata;
}
void DisplayListRecordingSource::SetBackgroundColor(SkColor background_color) {
@@ -226,12 +220,12 @@ void DisplayListRecordingSource::SetRequiresClear(bool requires_clear) {
requires_clear_ = requires_clear;
}
-void DisplayListRecordingSource::SetUnsuitableForGpuRasterizationForTesting() {
- is_suitable_for_gpu_rasterization_ = false;
-}
-
bool DisplayListRecordingSource::IsSuitableForGpuRasterization() const {
- return is_suitable_for_gpu_rasterization_;
+ // The display list needs to be created (see: UpdateAndExpandInvalidation)
+ // before checking for suitability. There are cases where an update will not
+ // create a display list (e.g., if the size is empty). We return true in these
+ // cases because the gpu suitability bit sticks false.
+ return !display_list_ || display_list_->IsSuitableForGpuRasterization();
}
scoped_refptr<RasterSource> DisplayListRecordingSource::CreateRasterSource(
@@ -241,16 +235,12 @@ scoped_refptr<RasterSource> DisplayListRecordingSource::CreateRasterSource(
this, can_use_lcd_text));
}
-gfx::Size DisplayListRecordingSource::GetTileGridSizeForTesting() const {
- return gfx::Size();
-}
-
void DisplayListRecordingSource::DetermineIfSolidColor() {
- DCHECK(display_list_.get());
+ DCHECK(display_list_);
is_solid_color_ = false;
solid_color_ = SK_ColorTRANSPARENT;
- if (display_list_->ApproximateOpCount() > kOpCountThatIsOkToAnalyze)
+ if (!display_list_->ShouldBeAnalyzedForSolidColor())
return;
gfx::Size layer_size = GetSize();
@@ -261,7 +251,8 @@ void DisplayListRecordingSource::DetermineIfSolidColor() {
void DisplayListRecordingSource::Clear() {
recorded_viewport_ = gfx::Rect();
- display_list_ = NULL;
+ display_list_ = nullptr;
+ painter_reported_memory_usage_ = 0;
is_solid_color_ = false;
}
diff --git a/chromium/cc/playback/display_list_recording_source.h b/chromium/cc/playback/display_list_recording_source.h
index 8d4e52f0cc3..b4250d0b3bb 100644
--- a/chromium/cc/playback/display_list_recording_source.h
+++ b/chromium/cc/playback/display_list_recording_source.h
@@ -14,7 +14,7 @@ class DisplayListRasterSource;
class CC_EXPORT DisplayListRecordingSource : public RecordingSource {
public:
- explicit DisplayListRecordingSource(const gfx::Size& grid_cell_size);
+ DisplayListRecordingSource();
~DisplayListRecordingSource() override;
// RecordingSource overrides.
@@ -29,12 +29,10 @@ class CC_EXPORT DisplayListRecordingSource : public RecordingSource {
gfx::Size GetSize() const final;
void SetEmptyBounds() override;
void SetSlowdownRasterScaleFactor(int factor) override;
- void SetGatherPixelRefs(bool gather_pixel_refs) override;
+ void SetGenerateDiscardableImagesMetadata(bool generate_metadata) override;
void SetBackgroundColor(SkColor background_color) override;
void SetRequiresClear(bool requires_clear) override;
bool IsSuitableForGpuRasterization() const override;
- void SetUnsuitableForGpuRasterizationForTesting() override;
- gfx::Size GetTileGridSizeForTesting() const override;
// Returns true if the new recorded viewport exposes enough new area to be
// worth re-recording.
static bool ExposesEnoughNewArea(
@@ -50,24 +48,22 @@ class CC_EXPORT DisplayListRecordingSource : public RecordingSource {
gfx::Rect recorded_viewport_;
gfx::Size size_;
int slow_down_raster_scale_factor_for_debug_;
- bool gather_pixel_refs_;
+ bool generate_discardable_images_metadata_;
bool requires_clear_;
bool is_solid_color_;
bool clear_canvas_with_debug_color_;
SkColor solid_color_;
SkColor background_color_;
int pixel_record_distance_;
- gfx::Size grid_cell_size_;
scoped_refptr<DisplayItemList> display_list_;
+ size_t painter_reported_memory_usage_;
private:
friend class DisplayListRasterSource;
void DetermineIfSolidColor();
- bool is_suitable_for_gpu_rasterization_;
-
DISALLOW_COPY_AND_ASSIGN(DisplayListRecordingSource);
};
diff --git a/chromium/cc/playback/display_list_recording_source_unittest.cc b/chromium/cc/playback/display_list_recording_source_unittest.cc
index 0ddfb6fc5c8..83d44036305 100644
--- a/chromium/cc/playback/display_list_recording_source_unittest.cc
+++ b/chromium/cc/playback/display_list_recording_source_unittest.cc
@@ -14,40 +14,55 @@
namespace cc {
namespace {
-class DisplayListRecordingSourceTest : public testing::Test {
- public:
- void SetUp() override {}
-};
+scoped_ptr<FakeDisplayListRecordingSource> CreateRecordingSource(
+ const gfx::Rect& viewport) {
+ gfx::Rect layer_rect(viewport.right(), viewport.bottom());
+ scoped_ptr<FakeDisplayListRecordingSource> recording_source =
+ FakeDisplayListRecordingSource::CreateRecordingSource(viewport,
+ layer_rect.size());
+ return recording_source.Pass();
+}
+
+scoped_refptr<RasterSource> CreateRasterSource(
+ FakeDisplayListRecordingSource* recording_source) {
+ bool can_use_lcd_text = true;
+ return DisplayListRasterSource::CreateFromDisplayListRecordingSource(
+ recording_source, can_use_lcd_text);
+}
-TEST_F(DisplayListRecordingSourceTest, DiscardablePixelRefsWithTransform) {
- gfx::Size grid_cell_size(128, 128);
+TEST(DisplayListRecordingSourceTest, DiscardableImagesWithTransform) {
gfx::Rect recorded_viewport(256, 256);
scoped_ptr<FakeDisplayListRecordingSource> recording_source =
FakeDisplayListRecordingSource::CreateFilledRecordingSource(
recorded_viewport.size());
- recording_source->SetGridCellSize(grid_cell_size);
- SkBitmap discardable_bitmap[2][2];
+ skia::RefPtr<SkImage> discardable_image[2][2];
gfx::Transform identity_transform;
- CreateBitmap(gfx::Size(32, 32), "discardable", &discardable_bitmap[0][0]);
+ discardable_image[0][0] = CreateDiscardableImage(gfx::Size(32, 32));
// Translate transform is equivalent to moving using point.
gfx::Transform translate_transform;
translate_transform.Translate(0, 130);
- CreateBitmap(gfx::Size(32, 32), "discardable", &discardable_bitmap[1][0]);
+ discardable_image[1][0] = CreateDiscardableImage(gfx::Size(32, 32));
// This moves the bitmap to center of viewport and rotate, this would make
// this bitmap in all four tile grids.
gfx::Transform rotate_transform;
rotate_transform.Translate(112, 112);
rotate_transform.Rotate(45);
- CreateBitmap(gfx::Size(32, 32), "discardable", &discardable_bitmap[1][1]);
-
- recording_source->add_draw_bitmap_with_transform(discardable_bitmap[0][0],
- identity_transform);
- recording_source->add_draw_bitmap_with_transform(discardable_bitmap[1][0],
- translate_transform);
- recording_source->add_draw_bitmap_with_transform(discardable_bitmap[1][1],
- rotate_transform);
- recording_source->SetGatherPixelRefs(true);
+ discardable_image[1][1] = CreateDiscardableImage(gfx::Size(32, 32));
+
+ gfx::RectF rect(0, 0, 32, 32);
+ gfx::RectF translate_rect = rect;
+ translate_transform.TransformRect(&translate_rect);
+ gfx::RectF rotate_rect = rect;
+ rotate_transform.TransformRect(&rotate_rect);
+
+ recording_source->add_draw_image_with_transform(discardable_image[0][0].get(),
+ identity_transform);
+ recording_source->add_draw_image_with_transform(discardable_image[1][0].get(),
+ translate_transform);
+ recording_source->add_draw_image_with_transform(discardable_image[1][1].get(),
+ rotate_transform);
+ recording_source->SetGenerateDiscardableImagesMetadata(true);
recording_source->Rerecord();
bool can_use_lcd_text = true;
@@ -57,119 +72,60 @@ TEST_F(DisplayListRecordingSourceTest, DiscardablePixelRefsWithTransform) {
// Tile sized iterators. These should find only one pixel ref.
{
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(0, 0, 128, 128), 1.0, &pixel_refs);
- EXPECT_FALSE(pixel_refs.empty());
- EXPECT_TRUE(pixel_refs[0] == discardable_bitmap[0][0].pixelRef());
- EXPECT_TRUE(pixel_refs[1] == discardable_bitmap[1][1].pixelRef());
- EXPECT_EQ(2u, pixel_refs.size());
- }
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(0, 0, 256, 256), 2.0, &pixel_refs);
- EXPECT_FALSE(pixel_refs.empty());
- EXPECT_TRUE(pixel_refs[0] == discardable_bitmap[0][0].pixelRef());
- EXPECT_TRUE(pixel_refs[1] == discardable_bitmap[1][1].pixelRef());
- EXPECT_EQ(2u, pixel_refs.size());
- }
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(0, 0, 64, 64), 0.5, &pixel_refs);
- EXPECT_FALSE(pixel_refs.empty());
- EXPECT_TRUE(pixel_refs[0] == discardable_bitmap[0][0].pixelRef());
- EXPECT_TRUE(pixel_refs[1] == discardable_bitmap[1][1].pixelRef());
- EXPECT_EQ(2u, pixel_refs.size());
+ std::vector<PositionImage> images;
+ raster_source->GetDiscardableImagesInRect(gfx::Rect(0, 0, 128, 128),
+ &images);
+ EXPECT_EQ(2u, images.size());
+ EXPECT_TRUE(images[0].image == discardable_image[0][0].get());
+ EXPECT_TRUE(images[1].image == discardable_image[1][1].get());
+ EXPECT_EQ(rect.ToString(),
+ gfx::SkRectToRectF(images[0].image_rect).ToString());
+ EXPECT_EQ(rotate_rect.ToString(),
+ gfx::SkRectToRectF(images[1].image_rect).ToString());
}
// Shifted tile sized iterators. These should find only one pixel ref.
{
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(140, 140, 128, 128), 1.0,
- &pixel_refs);
- EXPECT_FALSE(pixel_refs.empty());
- EXPECT_TRUE(pixel_refs[0] == discardable_bitmap[1][1].pixelRef());
- EXPECT_EQ(1u, pixel_refs.size());
- }
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(280, 280, 256, 256), 2.0,
- &pixel_refs);
- EXPECT_FALSE(pixel_refs.empty());
- EXPECT_TRUE(pixel_refs[0] == discardable_bitmap[1][1].pixelRef());
- EXPECT_EQ(1u, pixel_refs.size());
- }
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(70, 70, 64, 64), 0.5, &pixel_refs);
- EXPECT_FALSE(pixel_refs.empty());
- EXPECT_TRUE(pixel_refs[0] == discardable_bitmap[1][1].pixelRef());
- EXPECT_EQ(1u, pixel_refs.size());
+ std::vector<PositionImage> images;
+ raster_source->GetDiscardableImagesInRect(gfx::Rect(130, 140, 128, 128),
+ &images);
+ EXPECT_EQ(1u, images.size());
+ EXPECT_TRUE(images[0].image == discardable_image[1][1].get());
+ EXPECT_EQ(rotate_rect.ToString(),
+ gfx::SkRectToRectF(images[0].image_rect).ToString());
}
// The rotated bitmap would still be in the top right tile.
{
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(140, 0, 128, 128), 1.0,
- &pixel_refs);
- EXPECT_FALSE(pixel_refs.empty());
- EXPECT_TRUE(pixel_refs[0] == discardable_bitmap[1][1].pixelRef());
- EXPECT_EQ(1u, pixel_refs.size());
+ std::vector<PositionImage> images;
+ raster_source->GetDiscardableImagesInRect(gfx::Rect(130, 0, 128, 128),
+ &images);
+ EXPECT_EQ(1u, images.size());
+ EXPECT_TRUE(images[0].image == discardable_image[1][1].get());
+ EXPECT_EQ(rotate_rect.ToString(),
+ gfx::SkRectToRectF(images[0].image_rect).ToString());
}
- // Layer sized iterators. These should find all 6 pixel refs, including 1
- // pixel ref bitmap[0][0], 1 pixel ref for bitmap[1][0], and 4 pixel refs for
- // bitmap[1][1].
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(0, 0, 256, 256), 1.0, &pixel_refs);
- EXPECT_FALSE(pixel_refs.empty());
- // Top left tile with bitmap[0][0] and bitmap[1][1].
- EXPECT_TRUE(pixel_refs[0] == discardable_bitmap[0][0].pixelRef());
- EXPECT_TRUE(pixel_refs[1] == discardable_bitmap[1][1].pixelRef());
- // Top right tile with bitmap[1][1].
- EXPECT_TRUE(pixel_refs[2] == discardable_bitmap[1][1].pixelRef());
- // Bottom left tile with bitmap[1][0] and bitmap[1][1].
- EXPECT_TRUE(pixel_refs[3] == discardable_bitmap[1][0].pixelRef());
- EXPECT_TRUE(pixel_refs[4] == discardable_bitmap[1][1].pixelRef());
- // Bottom right tile with bitmap[1][1].
- EXPECT_TRUE(pixel_refs[5] == discardable_bitmap[1][1].pixelRef());
- EXPECT_EQ(6u, pixel_refs.size());
- }
+ // Layer sized iterators. These should find all pixel refs.
{
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(0, 0, 512, 512), 2.0, &pixel_refs);
- EXPECT_FALSE(pixel_refs.empty());
+ std::vector<PositionImage> images;
+ raster_source->GetDiscardableImagesInRect(gfx::Rect(0, 0, 256, 256),
+ &images);
+ EXPECT_EQ(3u, images.size());
// Top left tile with bitmap[0][0] and bitmap[1][1].
- EXPECT_TRUE(pixel_refs[0] == discardable_bitmap[0][0].pixelRef());
- EXPECT_TRUE(pixel_refs[1] == discardable_bitmap[1][1].pixelRef());
- // Top right tile with bitmap[1][1].
- EXPECT_TRUE(pixel_refs[2] == discardable_bitmap[1][1].pixelRef());
- // Bottom left tile with bitmap[1][0] and bitmap[1][1].
- EXPECT_TRUE(pixel_refs[3] == discardable_bitmap[1][0].pixelRef());
- EXPECT_TRUE(pixel_refs[4] == discardable_bitmap[1][1].pixelRef());
- // Bottom right tile with bitmap[1][1].
- EXPECT_TRUE(pixel_refs[5] == discardable_bitmap[1][1].pixelRef());
- EXPECT_EQ(6u, pixel_refs.size());
- }
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(0, 0, 128, 128), 0.5, &pixel_refs);
- EXPECT_FALSE(pixel_refs.empty());
- // Top left tile with bitmap[0][0] and bitmap[1][1].
- EXPECT_TRUE(pixel_refs[0] == discardable_bitmap[0][0].pixelRef());
- EXPECT_TRUE(pixel_refs[1] == discardable_bitmap[1][1].pixelRef());
- // Top right tile with bitmap[1][1].
- EXPECT_TRUE(pixel_refs[2] == discardable_bitmap[1][1].pixelRef());
- // Bottom left tile with bitmap[1][0] and bitmap[1][1].
- EXPECT_TRUE(pixel_refs[3] == discardable_bitmap[1][0].pixelRef());
- EXPECT_TRUE(pixel_refs[4] == discardable_bitmap[1][1].pixelRef());
- // Bottom right tile with bitmap[1][1].
- EXPECT_TRUE(pixel_refs[5] == discardable_bitmap[1][1].pixelRef());
- EXPECT_EQ(6u, pixel_refs.size());
+ EXPECT_TRUE(images[0].image == discardable_image[0][0].get());
+ EXPECT_TRUE(images[1].image == discardable_image[1][0].get());
+ EXPECT_TRUE(images[2].image == discardable_image[1][1].get());
+ EXPECT_EQ(rect.ToString(),
+ gfx::SkRectToRectF(images[0].image_rect).ToString());
+ EXPECT_EQ(translate_rect.ToString(),
+ gfx::SkRectToRectF(images[1].image_rect).ToString());
+ EXPECT_EQ(rotate_rect.ToString(),
+ gfx::SkRectToRectF(images[2].image_rect).ToString());
}
}
-TEST_F(DisplayListRecordingSourceTest, ExposesEnoughNewAreaEmpty) {
+TEST(DisplayListRecordingSourceTest, ExposesEnoughNewAreaEmpty) {
gfx::Size layer_size(1000, 1000);
// Both empty means there is nothing to do.
@@ -185,7 +141,7 @@ TEST_F(DisplayListRecordingSourceTest, ExposesEnoughNewAreaEmpty) {
gfx::Rect(1, 1), gfx::Rect(), layer_size));
}
-TEST_F(DisplayListRecordingSourceTest, ExposesEnoughNewAreaNotBigEnough) {
+TEST(DisplayListRecordingSourceTest, ExposesEnoughNewAreaNotBigEnough) {
gfx::Size layer_size(1000, 1000);
gfx::Rect current_recorded_viewport(100, 100, 100, 100);
EXPECT_FALSE(DisplayListRecordingSource::ExposesEnoughNewArea(
@@ -196,8 +152,8 @@ TEST_F(DisplayListRecordingSourceTest, ExposesEnoughNewAreaNotBigEnough) {
current_recorded_viewport, gfx::Rect(1, 1, 200, 200), layer_size));
}
-TEST_F(DisplayListRecordingSourceTest,
- ExposesEnoughNewAreaNotBigEnoughButNewAreaTouchesEdge) {
+TEST(DisplayListRecordingSourceTest,
+ ExposesEnoughNewAreaNotBigEnoughButNewAreaTouchesEdge) {
gfx::Size layer_size(500, 500);
gfx::Rect current_recorded_viewport(100, 100, 100, 100);
@@ -220,8 +176,8 @@ TEST_F(DisplayListRecordingSourceTest,
// Verifies that having a current viewport that touches a layer edge does not
// force re-recording.
-TEST_F(DisplayListRecordingSourceTest,
- ExposesEnoughNewAreaCurrentViewportTouchesEdge) {
+TEST(DisplayListRecordingSourceTest,
+ ExposesEnoughNewAreaCurrentViewportTouchesEdge) {
gfx::Size layer_size(500, 500);
gfx::Rect potential_new_viewport(100, 100, 300, 300);
@@ -242,7 +198,7 @@ TEST_F(DisplayListRecordingSourceTest,
gfx::Rect(400, 300, 100, 100), potential_new_viewport, layer_size));
}
-TEST_F(DisplayListRecordingSourceTest, ExposesEnoughNewAreaScrollScenarios) {
+TEST(DisplayListRecordingSourceTest, ExposesEnoughNewAreaScrollScenarios) {
gfx::Size layer_size(1000, 1000);
gfx::Rect current_recorded_viewport(100, 100, 100, 100);
@@ -265,10 +221,9 @@ TEST_F(DisplayListRecordingSourceTest, ExposesEnoughNewAreaScrollScenarios) {
// Verifies that UpdateAndExpandInvalidation calls ExposesEnoughNewArea with the
// right arguments.
-TEST_F(DisplayListRecordingSourceTest,
- ExposesEnoughNewAreaCalledWithCorrectArguments) {
- gfx::Size grid_cell_size(128, 128);
- DisplayListRecordingSource recording_source(grid_cell_size);
+TEST(DisplayListRecordingSourceTest,
+ ExposesEnoughNewAreaCalledWithCorrectArguments) {
+ DisplayListRecordingSource recording_source;
FakeContentLayerClient client;
Region invalidation;
gfx::Size layer_size(9000, 9000);
@@ -277,20 +232,20 @@ TEST_F(DisplayListRecordingSourceTest,
recording_source.UpdateAndExpandInvalidation(
&client, &invalidation, layer_size, visible_rect, 0,
RecordingSource::RECORD_NORMALLY);
- EXPECT_EQ(gfx::Rect(0, 0, 8256, 8256), recording_source.recorded_viewport());
+ EXPECT_EQ(gfx::Rect(0, 0, 4256, 4256), recording_source.recorded_viewport());
visible_rect.Offset(0, 512);
recording_source.UpdateAndExpandInvalidation(
&client, &invalidation, layer_size, visible_rect, 0,
RecordingSource::RECORD_NORMALLY);
- EXPECT_EQ(gfx::Rect(0, 0, 8256, 8256), recording_source.recorded_viewport());
+ EXPECT_EQ(gfx::Rect(0, 0, 4256, 4256), recording_source.recorded_viewport());
// Move past the threshold for enough exposed new area.
visible_rect.Offset(0, 1);
recording_source.UpdateAndExpandInvalidation(
&client, &invalidation, layer_size, visible_rect, 0,
RecordingSource::RECORD_NORMALLY);
- EXPECT_EQ(gfx::Rect(0, 0, 8256, 8769), recording_source.recorded_viewport());
+ EXPECT_EQ(gfx::Rect(0, 0, 4256, 4769), recording_source.recorded_viewport());
// Make the bottom of the potential new recorded viewport coincide with the
// layer's bottom edge.
@@ -298,7 +253,279 @@ TEST_F(DisplayListRecordingSourceTest,
recording_source.UpdateAndExpandInvalidation(
&client, &invalidation, layer_size, visible_rect, 0,
RecordingSource::RECORD_NORMALLY);
- EXPECT_EQ(gfx::Rect(0, 0, 8256, 9000), recording_source.recorded_viewport());
+ EXPECT_EQ(gfx::Rect(0, 0, 4256, 4769), recording_source.recorded_viewport());
+}
+
+TEST(DisplayListRecordingSourceTest, NoGatherImageEmptyImages) {
+ gfx::Rect recorded_viewport(0, 0, 256, 256);
+
+ scoped_ptr<FakeDisplayListRecordingSource> recording_source =
+ CreateRecordingSource(recorded_viewport);
+ recording_source->SetGenerateDiscardableImagesMetadata(false);
+ recording_source->Rerecord();
+
+ scoped_refptr<RasterSource> raster_source =
+ CreateRasterSource(recording_source.get());
+
+ // If recording source do not gather images, raster source is not going to
+ // get images.
+ {
+ std::vector<PositionImage> images;
+ raster_source->GetDiscardableImagesInRect(recorded_viewport, &images);
+ EXPECT_TRUE(images.empty());
+ }
+}
+
+TEST(DisplayListRecordingSourceTest, EmptyImages) {
+ gfx::Rect recorded_viewport(0, 0, 256, 256);
+
+ scoped_ptr<FakeDisplayListRecordingSource> recording_source =
+ CreateRecordingSource(recorded_viewport);
+ recording_source->SetGenerateDiscardableImagesMetadata(true);
+ recording_source->Rerecord();
+
+ scoped_refptr<RasterSource> raster_source =
+ CreateRasterSource(recording_source.get());
+
+ // Tile sized iterators.
+ {
+ std::vector<PositionImage> images;
+ raster_source->GetDiscardableImagesInRect(gfx::Rect(0, 0, 128, 128),
+ &images);
+ EXPECT_TRUE(images.empty());
+ }
+ // Shifted tile sized iterators.
+ {
+ std::vector<PositionImage> images;
+ raster_source->GetDiscardableImagesInRect(gfx::Rect(140, 140, 128, 128),
+ &images);
+ EXPECT_TRUE(images.empty());
+ }
+ // Layer sized iterators.
+ {
+ std::vector<PositionImage> images;
+ raster_source->GetDiscardableImagesInRect(gfx::Rect(0, 0, 256, 256),
+ &images);
+ EXPECT_TRUE(images.empty());
+ }
+}
+
+TEST(DisplayListRecordingSourceTest, NoDiscardableImages) {
+ gfx::Rect recorded_viewport(0, 0, 256, 256);
+
+ scoped_ptr<FakeDisplayListRecordingSource> recording_source =
+ CreateRecordingSource(recorded_viewport);
+
+ SkPaint simple_paint;
+ simple_paint.setColor(SkColorSetARGB(255, 12, 23, 34));
+
+ SkBitmap non_discardable_bitmap;
+ non_discardable_bitmap.allocN32Pixels(128, 128);
+ non_discardable_bitmap.setImmutable();
+ skia::RefPtr<SkImage> non_discardable_image =
+ skia::AdoptRef(SkImage::NewFromBitmap(non_discardable_bitmap));
+
+ recording_source->add_draw_rect_with_paint(gfx::Rect(0, 0, 256, 256),
+ simple_paint);
+ recording_source->add_draw_rect_with_paint(gfx::Rect(128, 128, 512, 512),
+ simple_paint);
+ recording_source->add_draw_rect_with_paint(gfx::Rect(512, 0, 256, 256),
+ simple_paint);
+ recording_source->add_draw_rect_with_paint(gfx::Rect(0, 512, 256, 256),
+ simple_paint);
+ recording_source->add_draw_image(non_discardable_image.get(),
+ gfx::Point(128, 0));
+ recording_source->add_draw_image(non_discardable_image.get(),
+ gfx::Point(0, 128));
+ recording_source->add_draw_image(non_discardable_image.get(),
+ gfx::Point(150, 150));
+ recording_source->SetGenerateDiscardableImagesMetadata(true);
+ recording_source->Rerecord();
+
+ scoped_refptr<RasterSource> raster_source =
+ CreateRasterSource(recording_source.get());
+
+ // Tile sized iterators.
+ {
+ std::vector<PositionImage> images;
+ raster_source->GetDiscardableImagesInRect(gfx::Rect(0, 0, 128, 128),
+ &images);
+ EXPECT_TRUE(images.empty());
+ }
+ // Shifted tile sized iterators.
+ {
+ std::vector<PositionImage> images;
+ raster_source->GetDiscardableImagesInRect(gfx::Rect(140, 140, 128, 128),
+ &images);
+ EXPECT_TRUE(images.empty());
+ }
+ // Layer sized iterators.
+ {
+ std::vector<PositionImage> images;
+ raster_source->GetDiscardableImagesInRect(gfx::Rect(0, 0, 256, 256),
+ &images);
+ EXPECT_TRUE(images.empty());
+ }
+}
+
+TEST(DisplayListRecordingSourceTest, DiscardableImages) {
+ gfx::Rect recorded_viewport(0, 0, 256, 256);
+
+ scoped_ptr<FakeDisplayListRecordingSource> recording_source =
+ CreateRecordingSource(recorded_viewport);
+
+ skia::RefPtr<SkImage> discardable_image[2][2];
+ discardable_image[0][0] = CreateDiscardableImage(gfx::Size(32, 32));
+ discardable_image[1][0] = CreateDiscardableImage(gfx::Size(32, 32));
+ discardable_image[1][1] = CreateDiscardableImage(gfx::Size(32, 32));
+
+ // Discardable images are found in the following cells:
+ // |---|---|
+ // | x | |
+ // |---|---|
+ // | x | x |
+ // |---|---|
+ recording_source->add_draw_image(discardable_image[0][0].get(),
+ gfx::Point(0, 0));
+ recording_source->add_draw_image(discardable_image[1][0].get(),
+ gfx::Point(0, 130));
+ recording_source->add_draw_image(discardable_image[1][1].get(),
+ gfx::Point(140, 140));
+ recording_source->SetGenerateDiscardableImagesMetadata(true);
+ recording_source->Rerecord();
+
+ scoped_refptr<RasterSource> raster_source =
+ CreateRasterSource(recording_source.get());
+
+ // Tile sized iterators. These should find only one image.
+ {
+ std::vector<PositionImage> images;
+ raster_source->GetDiscardableImagesInRect(gfx::Rect(0, 0, 128, 128),
+ &images);
+ EXPECT_EQ(1u, images.size());
+ EXPECT_TRUE(images[0].image == discardable_image[0][0].get());
+ EXPECT_EQ(gfx::RectF(32, 32).ToString(),
+ gfx::SkRectToRectF(images[0].image_rect).ToString());
+ }
+
+ // Shifted tile sized iterators. These should find only one image.
+ {
+ std::vector<PositionImage> images;
+ raster_source->GetDiscardableImagesInRect(gfx::Rect(140, 140, 128, 128),
+ &images);
+ EXPECT_EQ(1u, images.size());
+ EXPECT_TRUE(images[0].image == discardable_image[1][1].get());
+ EXPECT_EQ(gfx::RectF(140, 140, 32, 32).ToString(),
+ gfx::SkRectToRectF(images[0].image_rect).ToString());
+ }
+
+ // Ensure there's no discardable images in the empty cell
+ {
+ std::vector<PositionImage> images;
+ raster_source->GetDiscardableImagesInRect(gfx::Rect(140, 0, 128, 128),
+ &images);
+ EXPECT_TRUE(images.empty());
+ }
+
+ // Layer sized iterators. These should find all 3 images.
+ {
+ std::vector<PositionImage> images;
+ raster_source->GetDiscardableImagesInRect(gfx::Rect(0, 0, 256, 256),
+ &images);
+ EXPECT_EQ(3u, images.size());
+ EXPECT_TRUE(images[0].image == discardable_image[0][0].get());
+ EXPECT_TRUE(images[1].image == discardable_image[1][0].get());
+ EXPECT_TRUE(images[2].image == discardable_image[1][1].get());
+ EXPECT_EQ(gfx::RectF(32, 32).ToString(),
+ gfx::SkRectToRectF(images[0].image_rect).ToString());
+ EXPECT_EQ(gfx::RectF(0, 130, 32, 32).ToString(),
+ gfx::SkRectToRectF(images[1].image_rect).ToString());
+ EXPECT_EQ(gfx::RectF(140, 140, 32, 32).ToString(),
+ gfx::SkRectToRectF(images[2].image_rect).ToString());
+ }
+}
+
+TEST(DisplayListRecordingSourceTest, DiscardableImagesBaseNonDiscardable) {
+ gfx::Rect recorded_viewport(0, 0, 512, 512);
+
+ scoped_ptr<FakeDisplayListRecordingSource> recording_source =
+ CreateRecordingSource(recorded_viewport);
+
+ SkBitmap non_discardable_bitmap;
+ non_discardable_bitmap.allocN32Pixels(512, 512);
+ non_discardable_bitmap.setImmutable();
+ skia::RefPtr<SkImage> non_discardable_image =
+ skia::AdoptRef(SkImage::NewFromBitmap(non_discardable_bitmap));
+
+ skia::RefPtr<SkImage> discardable_image[2][2];
+ discardable_image[0][0] = CreateDiscardableImage(gfx::Size(128, 128));
+ discardable_image[0][1] = CreateDiscardableImage(gfx::Size(128, 128));
+ discardable_image[1][1] = CreateDiscardableImage(gfx::Size(128, 128));
+
+ // One large non-discardable image covers the whole grid.
+ // Discardable images are found in the following cells:
+ // |---|---|
+ // | x | x |
+ // |---|---|
+ // | | x |
+ // |---|---|
+ recording_source->add_draw_image(non_discardable_image.get(),
+ gfx::Point(0, 0));
+ recording_source->add_draw_image(discardable_image[0][0].get(),
+ gfx::Point(0, 0));
+ recording_source->add_draw_image(discardable_image[0][1].get(),
+ gfx::Point(260, 0));
+ recording_source->add_draw_image(discardable_image[1][1].get(),
+ gfx::Point(260, 260));
+ recording_source->SetGenerateDiscardableImagesMetadata(true);
+ recording_source->Rerecord();
+
+ scoped_refptr<RasterSource> raster_source =
+ CreateRasterSource(recording_source.get());
+
+ // Tile sized iterators. These should find only one image.
+ {
+ std::vector<PositionImage> images;
+ raster_source->GetDiscardableImagesInRect(gfx::Rect(0, 0, 256, 256),
+ &images);
+ EXPECT_EQ(1u, images.size());
+ EXPECT_TRUE(images[0].image == discardable_image[0][0].get());
+ EXPECT_EQ(gfx::RectF(128, 128).ToString(),
+ gfx::SkRectToRectF(images[0].image_rect).ToString());
+ }
+ // Shifted tile sized iterators. These should find only one image.
+ {
+ std::vector<PositionImage> images;
+ raster_source->GetDiscardableImagesInRect(gfx::Rect(260, 260, 256, 256),
+ &images);
+ EXPECT_EQ(1u, images.size());
+ EXPECT_TRUE(images[0].image == discardable_image[1][1].get());
+ EXPECT_EQ(gfx::RectF(260, 260, 128, 128).ToString(),
+ gfx::SkRectToRectF(images[0].image_rect).ToString());
+ }
+ // Ensure there's no discardable images in the empty cell
+ {
+ std::vector<PositionImage> images;
+ raster_source->GetDiscardableImagesInRect(gfx::Rect(0, 256, 256, 256),
+ &images);
+ EXPECT_TRUE(images.empty());
+ }
+ // Layer sized iterators. These should find three images.
+ {
+ std::vector<PositionImage> images;
+ raster_source->GetDiscardableImagesInRect(gfx::Rect(0, 0, 512, 512),
+ &images);
+ EXPECT_EQ(3u, images.size());
+ EXPECT_TRUE(images[0].image == discardable_image[0][0].get());
+ EXPECT_TRUE(images[1].image == discardable_image[0][1].get());
+ EXPECT_TRUE(images[2].image == discardable_image[1][1].get());
+ EXPECT_EQ(gfx::RectF(128, 128).ToString(),
+ gfx::SkRectToRectF(images[0].image_rect).ToString());
+ EXPECT_EQ(gfx::RectF(260, 0, 128, 128).ToString(),
+ gfx::SkRectToRectF(images[1].image_rect).ToString());
+ EXPECT_EQ(gfx::RectF(260, 260, 128, 128).ToString(),
+ gfx::SkRectToRectF(images[2].image_rect).ToString());
+ }
}
} // namespace
diff --git a/chromium/cc/playback/drawing_display_item.cc b/chromium/cc/playback/drawing_display_item.cc
index 6cebed2ae00..a1f54b42d01 100644
--- a/chromium/cc/playback/drawing_display_item.cc
+++ b/chromium/cc/playback/drawing_display_item.cc
@@ -51,6 +51,11 @@ void DrawingDisplayItem::Raster(SkCanvas* canvas,
canvas->drawPicture(picture_.get());
}
+void DrawingDisplayItem::ProcessForBounds(
+ DisplayItemListBoundsCalculator* calculator) const {
+ calculator->AddDisplayItemWithBounds(picture_->cullRect());
+}
+
void DrawingDisplayItem::AsValueInto(
base::trace_event::TracedValue* array) const {
array->BeginDictionary();
diff --git a/chromium/cc/playback/drawing_display_item.h b/chromium/cc/playback/drawing_display_item.h
index f94e7c9ca6e..5103bb52484 100644
--- a/chromium/cc/playback/drawing_display_item.h
+++ b/chromium/cc/playback/drawing_display_item.h
@@ -27,6 +27,8 @@ class CC_EXPORT DrawingDisplayItem : public DisplayItem {
const gfx::Rect& canvas_playback_rect,
SkPicture::AbortCallback* callback) const override;
void AsValueInto(base::trace_event::TracedValue* array) const override;
+ void ProcessForBounds(
+ DisplayItemListBoundsCalculator* calculator) const override;
void CloneTo(DrawingDisplayItem* item) const;
diff --git a/chromium/cc/playback/filter_display_item.cc b/chromium/cc/playback/filter_display_item.cc
index fbed01509c8..48fcab33ec1 100644
--- a/chromium/cc/playback/filter_display_item.cc
+++ b/chromium/cc/playback/filter_display_item.cc
@@ -43,9 +43,14 @@ void FilterDisplayItem::Raster(SkCanvas* canvas,
skia::RefPtr<SkImageFilter> image_filter =
RenderSurfaceFilters::BuildImageFilter(
filters_, gfx::SizeF(bounds_.width(), bounds_.height()));
+#ifdef SK_SAVE_LAYER_BOUNDS_ARE_FILTERED
+ // TODO(senorblanco): remove this once callsites updated (crbug.com/525748)
SkRect boundaries;
image_filter->computeFastBounds(
SkRect::MakeWH(bounds_.width(), bounds_.height()), &boundaries);
+#else
+ SkRect boundaries = SkRect::MakeWH(bounds_.width(), bounds_.height());
+#endif
SkPaint paint;
paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
@@ -55,6 +60,12 @@ void FilterDisplayItem::Raster(SkCanvas* canvas,
canvas->translate(-bounds_.x(), -bounds_.y());
}
+void FilterDisplayItem::ProcessForBounds(
+ DisplayItemListBoundsCalculator* calculator) const {
+ calculator->AddStartingDisplayItem();
+ calculator->Save();
+}
+
void FilterDisplayItem::AsValueInto(
base::trace_event::TracedValue* array) const {
array->AppendString(base::StringPrintf("FilterDisplayItem bounds: [%s]",
@@ -76,6 +87,12 @@ void EndFilterDisplayItem::Raster(SkCanvas* canvas,
canvas->restore();
}
+void EndFilterDisplayItem::ProcessForBounds(
+ DisplayItemListBoundsCalculator* calculator) const {
+ calculator->Restore();
+ calculator->AddEndingDisplayItem();
+}
+
void EndFilterDisplayItem::AsValueInto(
base::trace_event::TracedValue* array) const {
array->AppendString("EndFilterDisplayItem");
diff --git a/chromium/cc/playback/filter_display_item.h b/chromium/cc/playback/filter_display_item.h
index 9672878752a..d9714c07cdc 100644
--- a/chromium/cc/playback/filter_display_item.h
+++ b/chromium/cc/playback/filter_display_item.h
@@ -26,6 +26,8 @@ class CC_EXPORT FilterDisplayItem : public DisplayItem {
const gfx::Rect& canvas_target_playback_rect,
SkPicture::AbortCallback* callback) const override;
void AsValueInto(base::trace_event::TracedValue* array) const override;
+ void ProcessForBounds(
+ DisplayItemListBoundsCalculator* calculator) const override;
private:
FilterOperations filters_;
@@ -45,6 +47,8 @@ class CC_EXPORT EndFilterDisplayItem : public DisplayItem {
const gfx::Rect& canvas_target_playback_rect,
SkPicture::AbortCallback* callback) const override;
void AsValueInto(base::trace_event::TracedValue* array) const override;
+ void ProcessForBounds(
+ DisplayItemListBoundsCalculator* calculator) const override;
};
} // namespace cc
diff --git a/chromium/cc/playback/float_clip_display_item.cc b/chromium/cc/playback/float_clip_display_item.cc
index 8b29fc214c5..5ba79a53f17 100644
--- a/chromium/cc/playback/float_clip_display_item.cc
+++ b/chromium/cc/playback/float_clip_display_item.cc
@@ -31,6 +31,11 @@ void FloatClipDisplayItem::Raster(SkCanvas* canvas,
canvas->clipRect(gfx::RectFToSkRect(clip_rect_));
}
+void FloatClipDisplayItem::ProcessForBounds(
+ DisplayItemListBoundsCalculator* calculator) const {
+ calculator->AddStartingDisplayItem();
+}
+
void FloatClipDisplayItem::AsValueInto(
base::trace_event::TracedValue* array) const {
array->AppendString(base::StringPrintf("FloatClipDisplayItem rect: [%s]",
@@ -52,6 +57,11 @@ void EndFloatClipDisplayItem::Raster(
canvas->restore();
}
+void EndFloatClipDisplayItem::ProcessForBounds(
+ DisplayItemListBoundsCalculator* calculator) const {
+ calculator->AddEndingDisplayItem();
+}
+
void EndFloatClipDisplayItem::AsValueInto(
base::trace_event::TracedValue* array) const {
array->AppendString("EndFloatClipDisplayItem");
diff --git a/chromium/cc/playback/float_clip_display_item.h b/chromium/cc/playback/float_clip_display_item.h
index 13d637f85a3..65449b886a8 100644
--- a/chromium/cc/playback/float_clip_display_item.h
+++ b/chromium/cc/playback/float_clip_display_item.h
@@ -27,6 +27,8 @@ class CC_EXPORT FloatClipDisplayItem : public DisplayItem {
const gfx::Rect& canvas_target_playback_rect,
SkPicture::AbortCallback* callback) const override;
void AsValueInto(base::trace_event::TracedValue* array) const override;
+ void ProcessForBounds(
+ DisplayItemListBoundsCalculator* calculator) const override;
private:
gfx::RectF clip_rect_;
@@ -45,6 +47,8 @@ class CC_EXPORT EndFloatClipDisplayItem : public DisplayItem {
const gfx::Rect& canvas_target_playback_rect,
SkPicture::AbortCallback* callback) const override;
void AsValueInto(base::trace_event::TracedValue* array) const override;
+ void ProcessForBounds(
+ DisplayItemListBoundsCalculator* calculator) const override;
};
} // namespace cc
diff --git a/chromium/cc/playback/picture.cc b/chromium/cc/playback/picture.cc
deleted file mode 100644
index 8ce9c66ff8f..00000000000
--- a/chromium/cc/playback/picture.cc
+++ /dev/null
@@ -1,338 +0,0 @@
-// Copyright 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cc/playback/picture.h"
-
-#include <set>
-#include <string>
-
-#include "base/base64.h"
-#include "base/trace_event/trace_event.h"
-#include "base/trace_event/trace_event_argument.h"
-#include "base/values.h"
-#include "cc/base/math_util.h"
-#include "cc/debug/picture_debug_util.h"
-#include "cc/debug/traced_picture.h"
-#include "cc/debug/traced_value.h"
-#include "cc/layers/content_layer_client.h"
-#include "skia/ext/pixel_ref_utils.h"
-#include "third_party/skia/include/core/SkCanvas.h"
-#include "third_party/skia/include/core/SkPaint.h"
-#include "third_party/skia/include/core/SkPictureRecorder.h"
-#include "third_party/skia/include/core/SkStream.h"
-#include "third_party/skia/include/utils/SkNullCanvas.h"
-#include "third_party/skia/include/utils/SkPictureUtils.h"
-#include "ui/gfx/codec/jpeg_codec.h"
-#include "ui/gfx/codec/png_codec.h"
-#include "ui/gfx/geometry/rect_conversions.h"
-#include "ui/gfx/skia_util.h"
-
-namespace cc {
-
-namespace {
-
-bool DecodeBitmap(const void* buffer, size_t size, SkBitmap* bm) {
- const unsigned char* data = static_cast<const unsigned char *>(buffer);
-
- // Try PNG first.
- if (gfx::PNGCodec::Decode(data, size, bm))
- return true;
-
- // Try JPEG.
- scoped_ptr<SkBitmap> decoded_jpeg(gfx::JPEGCodec::Decode(data, size));
- if (decoded_jpeg) {
- *bm = *decoded_jpeg;
- return true;
- }
- return false;
-}
-
-} // namespace
-
-scoped_refptr<Picture> Picture::Create(
- const gfx::Rect& layer_rect,
- ContentLayerClient* client,
- const gfx::Size& tile_grid_size,
- bool gather_pixel_refs,
- RecordingSource::RecordingMode recording_mode) {
- scoped_refptr<Picture> picture =
- make_scoped_refptr(new Picture(layer_rect, tile_grid_size));
-
- picture->Record(client, recording_mode);
- if (gather_pixel_refs)
- picture->GatherPixelRefs();
-
- return picture;
-}
-
-Picture::Picture(const gfx::Rect& layer_rect, const gfx::Size& tile_grid_size)
- : layer_rect_(layer_rect), pixel_refs_(tile_grid_size) {
- // Instead of recording a trace event for object creation here, we wait for
- // the picture to be recorded in Picture::Record.
-}
-
-scoped_refptr<Picture> Picture::CreateFromSkpValue(const base::Value* value) {
- // Decode the picture from base64.
- std::string encoded;
- if (!value->GetAsString(&encoded))
- return NULL;
-
- std::string decoded;
- base::Base64Decode(encoded, &decoded);
- SkMemoryStream stream(decoded.data(), decoded.size());
-
- // Read the picture. This creates an empty picture on failure.
- SkPicture* skpicture = SkPicture::CreateFromStream(&stream, &DecodeBitmap);
- if (skpicture == NULL)
- return NULL;
-
- gfx::Rect layer_rect(gfx::SkIRectToRect(skpicture->cullRect().roundOut()));
- return make_scoped_refptr(new Picture(skpicture, layer_rect));
-}
-
-scoped_refptr<Picture> Picture::CreateFromValue(const base::Value* raw_value) {
- const base::DictionaryValue* value = NULL;
- if (!raw_value->GetAsDictionary(&value))
- return NULL;
-
- // Decode the picture from base64.
- std::string encoded;
- if (!value->GetString("skp64", &encoded))
- return NULL;
-
- std::string decoded;
- base::Base64Decode(encoded, &decoded);
- SkMemoryStream stream(decoded.data(), decoded.size());
-
- const base::Value* layer_rect_value = NULL;
- if (!value->Get("params.layer_rect", &layer_rect_value))
- return NULL;
-
- gfx::Rect layer_rect;
- if (!MathUtil::FromValue(layer_rect_value, &layer_rect))
- return NULL;
-
- // Read the picture. This creates an empty picture on failure.
- SkPicture* skpicture = SkPicture::CreateFromStream(&stream, &DecodeBitmap);
- if (skpicture == NULL)
- return NULL;
-
- return make_scoped_refptr(new Picture(skpicture, layer_rect));
-}
-
-Picture::Picture(SkPicture* picture, const gfx::Rect& layer_rect)
- : layer_rect_(layer_rect),
- picture_(skia::AdoptRef(picture)),
- pixel_refs_(layer_rect.size()) {
-}
-
-Picture::Picture(const skia::RefPtr<SkPicture>& picture,
- const gfx::Rect& layer_rect,
- const PixelRefMap& pixel_refs)
- : layer_rect_(layer_rect), picture_(picture), pixel_refs_(pixel_refs) {
-}
-
-Picture::~Picture() {
- TRACE_EVENT_OBJECT_DELETED_WITH_ID(
- TRACE_DISABLED_BY_DEFAULT("cc.debug.picture"), "cc::Picture", this);
-}
-
-bool Picture::IsSuitableForGpuRasterization(const char** reason) const {
- DCHECK(picture_);
-
- // TODO(hendrikw): SkPicture::suitableForGpuRasterization takes a GrContext.
- // Currently the GrContext isn't used, and should probably be removed from
- // skia.
- return picture_->suitableForGpuRasterization(nullptr, reason);
-}
-
-int Picture::ApproximateOpCount() const {
- DCHECK(picture_);
- return picture_->approximateOpCount();
-}
-
-size_t Picture::ApproximateMemoryUsage() const {
- DCHECK(picture_);
- return SkPictureUtils::ApproximateBytesUsed(picture_.get());
-}
-
-bool Picture::HasText() const {
- DCHECK(picture_);
- return picture_->hasText();
-}
-
-void Picture::Record(ContentLayerClient* painter,
- RecordingSource::RecordingMode recording_mode) {
- TRACE_EVENT2("cc",
- "Picture::Record",
- "data",
- AsTraceableRecordData(),
- "recording_mode",
- recording_mode);
-
- DCHECK(!picture_);
-
- SkRTreeFactory factory;
- SkPictureRecorder recorder;
-
- skia::RefPtr<SkCanvas> canvas;
- canvas = skia::SharePtr(recorder.beginRecording(
- layer_rect_.width(), layer_rect_.height(), &factory,
- SkPictureRecorder::kComputeSaveLayerInfo_RecordFlag));
-
- ContentLayerClient::PaintingControlSetting painting_control =
- ContentLayerClient::PAINTING_BEHAVIOR_NORMAL;
-
- switch (recording_mode) {
- case RecordingSource::RECORD_NORMALLY:
- // Already setup for normal recording.
- break;
- case RecordingSource::RECORD_WITH_SK_NULL_CANVAS:
- canvas = skia::AdoptRef(SkCreateNullCanvas());
- break;
- case RecordingSource::RECORD_WITH_PAINTING_DISABLED:
- // We pass a disable flag through the paint calls when perfromance
- // testing (the only time this case should ever arise) when we want to
- // prevent the Blink GraphicsContext object from consuming any compute
- // time.
- canvas = skia::AdoptRef(SkCreateNullCanvas());
- painting_control = ContentLayerClient::DISPLAY_LIST_PAINTING_DISABLED;
- break;
- case RecordingSource::RECORD_WITH_CACHING_DISABLED:
- // This mode should give the same results as RECORD_NORMALLY.
- painting_control = ContentLayerClient::DISPLAY_LIST_CACHING_DISABLED;
- break;
- default:
- // case RecordingSource::RECORD_WITH_CONSTRUCTION_DISABLED should
- // not be reached
- NOTREACHED();
- }
-
- canvas->save();
- canvas->translate(SkFloatToScalar(-layer_rect_.x()),
- SkFloatToScalar(-layer_rect_.y()));
-
- canvas->clipRect(gfx::RectToSkRect(layer_rect_));
-
- painter->PaintContents(canvas.get(), layer_rect_, painting_control);
-
- canvas->restore();
- picture_ = skia::AdoptRef(recorder.endRecordingAsPicture());
- DCHECK(picture_);
-
- EmitTraceSnapshot();
-}
-
-void Picture::GatherPixelRefs() {
- TRACE_EVENT2("cc", "Picture::GatherPixelRefs",
- "width", layer_rect_.width(),
- "height", layer_rect_.height());
-
- DCHECK(picture_);
- DCHECK(pixel_refs_.empty());
- if (!WillPlayBackBitmaps())
- return;
-
- pixel_refs_.GatherPixelRefsFromPicture(picture_.get());
-}
-
-int Picture::Raster(SkCanvas* canvas,
- SkPicture::AbortCallback* callback,
- const Region& negated_content_region,
- float contents_scale) const {
- TRACE_EVENT_BEGIN1(
- "cc",
- "Picture::Raster",
- "data",
- AsTraceableRasterData(contents_scale));
-
- DCHECK(picture_);
-
- canvas->save();
-
- for (Region::Iterator it(negated_content_region); it.has_rect(); it.next())
- canvas->clipRect(gfx::RectToSkRect(it.rect()), SkRegion::kDifference_Op);
-
- canvas->scale(contents_scale, contents_scale);
- canvas->translate(layer_rect_.x(), layer_rect_.y());
- if (callback) {
- // If we have a callback, we need to call |draw()|, |drawPicture()| doesn't
- // take a callback. This is used by |AnalysisCanvas| to early out.
- picture_->playback(canvas, callback);
- } else {
- // Prefer to call |drawPicture()| on the canvas since it could place the
- // entire picture on the canvas instead of parsing the skia operations.
- canvas->drawPicture(picture_.get());
- }
- SkIRect bounds;
- canvas->getClipDeviceBounds(&bounds);
- canvas->restore();
- TRACE_EVENT_END1(
- "cc", "Picture::Raster",
- "num_pixels_rasterized", bounds.width() * bounds.height());
- return bounds.width() * bounds.height();
-}
-
-void Picture::Replay(SkCanvas* canvas, SkPicture::AbortCallback* callback) {
- TRACE_EVENT_BEGIN0("cc", "Picture::Replay");
- DCHECK(picture_);
- picture_->playback(canvas, callback);
- SkIRect bounds;
- canvas->getClipDeviceBounds(&bounds);
- TRACE_EVENT_END1("cc", "Picture::Replay",
- "num_pixels_replayed", bounds.width() * bounds.height());
-}
-
-scoped_ptr<base::Value> Picture::AsValue() const {
- // Encode the picture as base64.
- scoped_ptr<base::DictionaryValue> res(new base::DictionaryValue());
- res->Set("params.layer_rect", MathUtil::AsValue(layer_rect_).release());
- std::string b64_picture;
- PictureDebugUtil::SerializeAsBase64(picture_.get(), &b64_picture);
- res->SetString("skp64", b64_picture);
- return res.Pass();
-}
-
-void Picture::EmitTraceSnapshot() const {
- TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(
- TRACE_DISABLED_BY_DEFAULT("cc.debug.picture") ","
- TRACE_DISABLED_BY_DEFAULT("devtools.timeline.picture"),
- "cc::Picture",
- this,
- TracedPicture::AsTraceablePicture(this));
-}
-
-void Picture::EmitTraceSnapshotAlias(Picture* original) const {
- TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(
- TRACE_DISABLED_BY_DEFAULT("cc.debug.picture") ","
- TRACE_DISABLED_BY_DEFAULT("devtools.timeline.picture"),
- "cc::Picture",
- this,
- TracedPicture::AsTraceablePictureAlias(original));
-}
-
-PixelRefMap::Iterator Picture::GetPixelRefMapIterator(
- const gfx::Rect& layer_rect) const {
- return PixelRefMap::Iterator(layer_rect, this);
-}
-
-scoped_refptr<base::trace_event::ConvertableToTraceFormat>
- Picture::AsTraceableRasterData(float scale) const {
- scoped_refptr<base::trace_event::TracedValue> raster_data =
- new base::trace_event::TracedValue();
- TracedValue::SetIDRef(this, raster_data.get(), "picture_id");
- raster_data->SetDouble("scale", scale);
- return raster_data;
-}
-
-scoped_refptr<base::trace_event::ConvertableToTraceFormat>
- Picture::AsTraceableRecordData() const {
- scoped_refptr<base::trace_event::TracedValue> record_data =
- new base::trace_event::TracedValue();
- TracedValue::SetIDRef(this, record_data.get(), "picture_id");
- MathUtil::AddToTracedValue("layer_rect", layer_rect_, record_data.get());
- return record_data;
-}
-
-} // namespace cc
diff --git a/chromium/cc/playback/picture.h b/chromium/cc/playback/picture.h
deleted file mode 100644
index b19504b4270..00000000000
--- a/chromium/cc/playback/picture.h
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CC_PLAYBACK_PICTURE_H_
-#define CC_PLAYBACK_PICTURE_H_
-
-#include "base/basictypes.h"
-#include "base/containers/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/logging.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/trace_event/trace_event.h"
-#include "cc/base/cc_export.h"
-#include "cc/base/region.h"
-#include "cc/playback/pixel_ref_map.h"
-#include "cc/playback/recording_source.h"
-#include "skia/ext/refptr.h"
-#include "third_party/skia/include/core/SkPicture.h"
-#include "ui/gfx/geometry/rect.h"
-
-class SkPixelRef;
-
-namespace base {
-class Value;
-}
-
-namespace skia {
-class AnalysisCanvas;
-}
-
-namespace cc {
-
-class ContentLayerClient;
-
-class CC_EXPORT Picture
- : public base::RefCountedThreadSafe<Picture> {
- public:
- static scoped_refptr<Picture> Create(
- const gfx::Rect& layer_rect,
- ContentLayerClient* client,
- const gfx::Size& tile_grid_size,
- bool gather_pixels_refs,
- RecordingSource::RecordingMode recording_mode);
- static scoped_refptr<Picture> CreateFromValue(const base::Value* value);
- static scoped_refptr<Picture> CreateFromSkpValue(const base::Value* value);
-
- gfx::Rect LayerRect() const { return layer_rect_; }
-
- // Has Record() been called yet?
- bool HasRecording() const { return picture_.get() != NULL; }
-
- bool IsSuitableForGpuRasterization(const char** reason) const;
- int ApproximateOpCount() const;
- size_t ApproximateMemoryUsage() const;
-
- bool HasText() const;
-
- // Apply this scale and raster the negated region into the canvas.
- // |negated_content_region| specifies the region to be clipped out of the
- // raster operation, i.e., the parts of the canvas which will not get drawn
- // to.
- int Raster(SkCanvas* canvas,
- SkPicture::AbortCallback* callback,
- const Region& negated_content_region,
- float contents_scale) const;
-
- // Draw the picture directly into the given canvas, without applying any
- // clip/scale/layer transformations.
- void Replay(SkCanvas* canvas, SkPicture::AbortCallback* callback = NULL);
-
- scoped_ptr<base::Value> AsValue() const;
-
- void EmitTraceSnapshot() const;
- void EmitTraceSnapshotAlias(Picture* original) const;
-
- bool WillPlayBackBitmaps() const { return picture_->willPlayBackBitmaps(); }
-
- PixelRefMap::Iterator GetPixelRefMapIterator(
- const gfx::Rect& layer_rect) const;
-
- private:
- Picture(const gfx::Rect& layer_rect, const gfx::Size& tile_grid_size);
- // This constructor assumes SkPicture is already ref'd and transfers
- // ownership to this picture.
- Picture(const skia::RefPtr<SkPicture>&,
- const gfx::Rect& layer_rect,
- const PixelRefMap& pixel_refs);
- // This constructor will call AdoptRef on the SkPicture.
- Picture(SkPicture*, const gfx::Rect& layer_rect);
- ~Picture();
-
- // Record a paint operation. To be able to safely use this SkPicture for
- // playback on a different thread this can only be called once.
- void Record(ContentLayerClient* client,
- RecordingSource::RecordingMode recording_mode);
-
- // Gather pixel refs from recording.
- void GatherPixelRefs();
-
- gfx::Rect layer_rect_;
- skia::RefPtr<SkPicture> picture_;
-
- PixelRefMap pixel_refs_;
-
- scoped_refptr<base::trace_event::ConvertableToTraceFormat>
- AsTraceableRasterData(float scale) const;
- scoped_refptr<base::trace_event::ConvertableToTraceFormat>
- AsTraceableRecordData() const;
-
- friend class base::RefCountedThreadSafe<Picture>;
- friend class PixelRefMap::Iterator;
- DISALLOW_COPY_AND_ASSIGN(Picture);
-};
-
-} // namespace cc
-
-#endif // CC_PLAYBACK_PICTURE_H_
diff --git a/chromium/cc/playback/picture_pile.cc b/chromium/cc/playback/picture_pile.cc
deleted file mode 100644
index 55a5f80997a..00000000000
--- a/chromium/cc/playback/picture_pile.cc
+++ /dev/null
@@ -1,699 +0,0 @@
-// Copyright 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cc/playback/picture_pile.h"
-
-#include <algorithm>
-#include <limits>
-#include <vector>
-
-#include "cc/base/histograms.h"
-#include "cc/base/region.h"
-#include "cc/playback/picture_pile_impl.h"
-#include "skia/ext/analysis_canvas.h"
-
-namespace {
-// Layout pixel buffer around the visible layer rect to record. Any base
-// picture that intersects the visible layer rect expanded by this distance
-// will be recorded.
-const int kPixelDistanceToRecord = 8000;
-// We don't perform solid color analysis on images that have more than 10 skia
-// operations.
-const int kOpCountThatIsOkToAnalyze = 10;
-
-// Dimensions of the tiles in this picture pile as well as the dimensions of
-// the base picture in each tile.
-const int kBasePictureSize = 512;
-
-// TODO(humper): The density threshold here is somewhat arbitrary; need a
-// way to set // this from the command line so we can write a benchmark
-// script and find a sweet spot.
-const float kDensityThreshold = 0.5f;
-
-bool rect_sort_y(const gfx::Rect& r1, const gfx::Rect& r2) {
- return r1.y() < r2.y() || (r1.y() == r2.y() && r1.x() < r2.x());
-}
-
-bool rect_sort_x(const gfx::Rect& r1, const gfx::Rect& r2) {
- return r1.x() < r2.x() || (r1.x() == r2.x() && r1.y() < r2.y());
-}
-
-float PerformClustering(const std::vector<gfx::Rect>& tiles,
- std::vector<gfx::Rect>* clustered_rects) {
- // These variables track the record area and invalid area
- // for the entire clustering
- int total_record_area = 0;
- int total_invalid_area = 0;
-
- // These variables track the record area and invalid area
- // for the current cluster being constructed.
- gfx::Rect cur_record_rect;
- int cluster_record_area = 0, cluster_invalid_area = 0;
-
- for (std::vector<gfx::Rect>::const_iterator it = tiles.begin();
- it != tiles.end();
- it++) {
- gfx::Rect invalid_tile = *it;
-
- // For each tile, we consider adding the invalid tile to the
- // current record rectangle. Only add it if the amount of empty
- // space created is below a density threshold.
- int tile_area = invalid_tile.width() * invalid_tile.height();
-
- gfx::Rect proposed_union = cur_record_rect;
- proposed_union.Union(invalid_tile);
- int proposed_area = proposed_union.width() * proposed_union.height();
- float proposed_density =
- static_cast<float>(cluster_invalid_area + tile_area) /
- static_cast<float>(proposed_area);
-
- if (proposed_density >= kDensityThreshold) {
- // It's okay to add this invalid tile to the
- // current recording rectangle.
- cur_record_rect = proposed_union;
- cluster_record_area = proposed_area;
- cluster_invalid_area += tile_area;
- total_invalid_area += tile_area;
- } else {
- // Adding this invalid tile to the current recording rectangle
- // would exceed our badness threshold, so put the current rectangle
- // in the list of recording rects, and start a new one.
- clustered_rects->push_back(cur_record_rect);
- total_record_area += cluster_record_area;
- cur_record_rect = invalid_tile;
- cluster_invalid_area = tile_area;
- cluster_record_area = tile_area;
- }
- }
-
- DCHECK(!cur_record_rect.IsEmpty());
- clustered_rects->push_back(cur_record_rect);
- total_record_area += cluster_record_area;;
-
- DCHECK_NE(total_record_area, 0);
-
- return static_cast<float>(total_invalid_area) /
- static_cast<float>(total_record_area);
-}
-
-void ClusterTiles(const std::vector<gfx::Rect>& invalid_tiles,
- std::vector<gfx::Rect>* record_rects) {
- TRACE_EVENT1("cc", "ClusterTiles",
- "count",
- invalid_tiles.size());
- if (invalid_tiles.size() <= 1) {
- // Quickly handle the special case for common
- // single-invalidation update, and also the less common
- // case of no tiles passed in.
- *record_rects = invalid_tiles;
- return;
- }
-
- // Sort the invalid tiles by y coordinate.
- std::vector<gfx::Rect> invalid_tiles_vertical = invalid_tiles;
- std::sort(invalid_tiles_vertical.begin(),
- invalid_tiles_vertical.end(),
- rect_sort_y);
-
- std::vector<gfx::Rect> vertical_clustering;
- float vertical_density =
- PerformClustering(invalid_tiles_vertical, &vertical_clustering);
-
- // If vertical density is optimal, then we can return early.
- if (vertical_density == 1.f) {
- *record_rects = vertical_clustering;
- return;
- }
-
- // Now try again with a horizontal sort, see which one is best
- std::vector<gfx::Rect> invalid_tiles_horizontal = invalid_tiles;
- std::sort(invalid_tiles_horizontal.begin(),
- invalid_tiles_horizontal.end(),
- rect_sort_x);
-
- std::vector<gfx::Rect> horizontal_clustering;
- float horizontal_density =
- PerformClustering(invalid_tiles_horizontal, &horizontal_clustering);
-
- if (vertical_density < horizontal_density) {
- *record_rects = horizontal_clustering;
- return;
- }
-
- *record_rects = vertical_clustering;
-}
-
-#ifdef NDEBUG
-const bool kDefaultClearCanvasSetting = false;
-#else
-const bool kDefaultClearCanvasSetting = true;
-#endif
-
-DEFINE_SCOPED_UMA_HISTOGRAM_AREA_TIMER(
- ScopedPicturePileUpdateTimer,
- "Compositing.PicturePile.UpdateUs",
- "Compositing.PicturePile.UpdateInvalidatedAreaPerMs");
-
-} // namespace
-
-namespace cc {
-
-PicturePile::PicturePile(float min_contents_scale,
- const gfx::Size& tile_grid_size)
- : min_contents_scale_(0),
- slow_down_raster_scale_factor_for_debug_(0),
- gather_pixel_refs_(false),
- has_any_recordings_(false),
- clear_canvas_with_debug_color_(kDefaultClearCanvasSetting),
- requires_clear_(true),
- is_solid_color_(false),
- solid_color_(SK_ColorTRANSPARENT),
- background_color_(SK_ColorTRANSPARENT),
- pixel_record_distance_(kPixelDistanceToRecord),
- is_suitable_for_gpu_rasterization_(true) {
- tiling_.SetMaxTextureSize(gfx::Size(kBasePictureSize, kBasePictureSize));
- SetMinContentsScale(min_contents_scale);
- SetTileGridSize(tile_grid_size);
-}
-
-PicturePile::~PicturePile() {
-}
-
-bool PicturePile::UpdateAndExpandInvalidation(
- ContentLayerClient* painter,
- Region* invalidation,
- const gfx::Size& layer_size,
- const gfx::Rect& visible_layer_rect,
- int frame_number,
- RecordingSource::RecordingMode recording_mode) {
- ScopedPicturePileUpdateTimer timer;
-
- gfx::Rect interest_rect = visible_layer_rect;
- interest_rect.Inset(-pixel_record_distance_, -pixel_record_distance_);
- recorded_viewport_ = interest_rect;
- recorded_viewport_.Intersect(gfx::Rect(layer_size));
-
- bool updated = ApplyInvalidationAndResize(interest_rect, invalidation,
- layer_size, frame_number);
-
- // Count the area that is being invalidated.
- Region recorded_invalidation(*invalidation);
- recorded_invalidation.Intersect(recorded_viewport_);
- for (Region::Iterator it(recorded_invalidation); it.has_rect(); it.next())
- timer.AddArea(it.rect().size().GetArea());
-
- std::vector<gfx::Rect> invalid_tiles;
- GetInvalidTileRects(interest_rect, &invalid_tiles);
- std::vector<gfx::Rect> record_rects;
- ClusterTiles(invalid_tiles, &record_rects);
-
- if (record_rects.empty())
- return updated;
-
- CreatePictures(painter, recording_mode, record_rects);
-
- DetermineIfSolidColor();
-
- has_any_recordings_ = true;
- DCHECK(CanRasterSlowTileCheck(recorded_viewport_));
- return true;
-}
-
-bool PicturePile::ApplyInvalidationAndResize(const gfx::Rect& interest_rect,
- Region* invalidation,
- const gfx::Size& layer_size,
- int frame_number) {
- bool updated = false;
-
- Region synthetic_invalidation;
- gfx::Size old_tiling_size = GetSize();
- if (old_tiling_size != layer_size) {
- tiling_.SetTilingSize(layer_size);
- updated = true;
- }
-
- gfx::Rect interest_rect_over_tiles =
- tiling_.ExpandRectToTileBounds(interest_rect);
-
- if (old_tiling_size != layer_size) {
- gfx::Size min_tiling_size(
- std::min(GetSize().width(), old_tiling_size.width()),
- std::min(GetSize().height(), old_tiling_size.height()));
- gfx::Size max_tiling_size(
- std::max(GetSize().width(), old_tiling_size.width()),
- std::max(GetSize().height(), old_tiling_size.height()));
-
- has_any_recordings_ = false;
-
- // Drop recordings that are outside the new or old layer bounds or that
- // changed size. Newly exposed areas are considered invalidated.
- // Previously exposed areas that are now outside of bounds also need to
- // be invalidated, as they may become part of raster when scale < 1.
- std::vector<PictureMapKey> to_erase;
- int min_toss_x = tiling_.num_tiles_x();
- if (max_tiling_size.width() > min_tiling_size.width()) {
- min_toss_x =
- tiling_.FirstBorderTileXIndexFromSrcCoord(min_tiling_size.width());
- }
- int min_toss_y = tiling_.num_tiles_y();
- if (max_tiling_size.height() > min_tiling_size.height()) {
- min_toss_y =
- tiling_.FirstBorderTileYIndexFromSrcCoord(min_tiling_size.height());
- }
- for (const auto& key_picture_pair : picture_map_) {
- const PictureMapKey& key = key_picture_pair.first;
- if (key.first < min_toss_x && key.second < min_toss_y) {
- has_any_recordings_ = true;
- continue;
- }
- to_erase.push_back(key);
- }
-
- for (size_t i = 0; i < to_erase.size(); ++i)
- picture_map_.erase(to_erase[i]);
-
- // If a recording is dropped and not re-recorded below, invalidate that
- // full recording to cause any raster tiles that would use it to be
- // dropped.
- // If the recording will be replaced below, invalidate newly exposed
- // areas and previously exposed areas to force raster tiles that include the
- // old recording to know there is new recording to display.
- gfx::Rect min_tiling_rect_over_tiles =
- tiling_.ExpandRectToTileBounds(gfx::Rect(min_tiling_size));
- if (min_toss_x < tiling_.num_tiles_x()) {
- // The bounds which we want to invalidate are the tiles along the old
- // edge of the pile when expanding, or the new edge of the pile when
- // shrinking. In either case, it's the difference of the two, so we'll
- // call this bounding box the DELTA EDGE RECT.
- //
- // In the picture below, the delta edge rect would be the bounding box of
- // tiles {h,i,j}. |min_toss_x| would be equal to the horizontal index of
- // the same tiles.
- //
- // min pile edge-v max pile edge-v
- // ---------------+ - - - - - - - -+
- // mmppssvvyybbeeh|h .
- // mmppssvvyybbeeh|h .
- // nnqqttwwzzccffi|i .
- // nnqqttwwzzccffi|i .
- // oorruuxxaaddggj|j .
- // oorruuxxaaddggj|j .
- // ---------------+ - - - - - - - -+ <- min pile edge
- // .
- // - - - - - - - - - - - - - - - -+ <- max pile edge
- //
- // If you were to slide a vertical beam from the left edge of the
- // delta edge rect toward the right, it would either hit the right edge
- // of the delta edge rect, or the interest rect (expanded to the bounds
- // of the tiles it touches). The same is true for a beam parallel to
- // any of the four edges, sliding across the delta edge rect. We use
- // the union of these four rectangles generated by these beams to
- // determine which part of the delta edge rect is outside of the expanded
- // interest rect.
- //
- // Case 1: Intersect rect is outside the delta edge rect. It can be
- // either on the left or the right. The |left_rect| and |right_rect|,
- // cover this case, one will be empty and one will cover the full
- // delta edge rect. In the picture below, |left_rect| would cover the
- // delta edge rect, and |right_rect| would be empty.
- // +----------------------+ |^^^^^^^^^^^^^^^|
- // |===> DELTA EDGE RECT | | |
- // |===> | | INTEREST RECT |
- // |===> | | |
- // |===> | | |
- // +----------------------+ |vvvvvvvvvvvvvvv|
- //
- // Case 2: Interest rect is inside the delta edge rect. It will always
- // fill the entire delta edge rect horizontally since the old edge rect
- // is a single tile wide, and the interest rect has been expanded to the
- // bounds of the tiles it touches. In this case the |left_rect| and
- // |right_rect| will be empty, but the case is handled by the |top_rect|
- // and |bottom_rect|. In the picture below, neither the |top_rect| nor
- // |bottom_rect| would empty, they would each cover the area of the old
- // edge rect outside the expanded interest rect.
- // +-----------------+
- // |:::::::::::::::::|
- // |:::::::::::::::::|
- // |vvvvvvvvvvvvvvvvv|
- // | |
- // +-----------------+
- // | INTEREST RECT |
- // | |
- // +-----------------+
- // | |
- // | DELTA EDGE RECT |
- // +-----------------+
- //
- // Lastly, we need to consider tiles inside the expanded interest rect.
- // For those tiles, we want to invalidate exactly the newly exposed
- // pixels. In the picture below the tiles in the delta edge rect have
- // been resized and the area covered by periods must be invalidated. The
- // |exposed_rect| will cover exactly that area.
- // v-min pile edge
- // +---------+-------+
- // | ........|
- // | ........|
- // | DELTA EDGE.RECT.|
- // | ........|
- // | ........|
- // | ........|
- // | ........|
- // | ........|
- // | ........|
- // +---------+-------+
-
- int left = tiling_.TilePositionX(min_toss_x);
- int right = left + tiling_.TileSizeX(min_toss_x);
- int top = min_tiling_rect_over_tiles.y();
- int bottom = min_tiling_rect_over_tiles.bottom();
-
- int left_until = std::min(interest_rect_over_tiles.x(), right);
- int right_until = std::max(interest_rect_over_tiles.right(), left);
- int top_until = std::min(interest_rect_over_tiles.y(), bottom);
- int bottom_until = std::max(interest_rect_over_tiles.bottom(), top);
-
- int exposed_left = min_tiling_size.width();
- int exposed_left_until = max_tiling_size.width();
- int exposed_top = top;
- int exposed_bottom = max_tiling_size.height();
- DCHECK_GE(exposed_left, left);
-
- gfx::Rect left_rect(left, top, left_until - left, bottom - top);
- gfx::Rect right_rect(right_until, top, right - right_until, bottom - top);
- gfx::Rect top_rect(left, top, right - left, top_until - top);
- gfx::Rect bottom_rect(
- left, bottom_until, right - left, bottom - bottom_until);
- gfx::Rect exposed_rect(exposed_left,
- exposed_top,
- exposed_left_until - exposed_left,
- exposed_bottom - exposed_top);
- synthetic_invalidation.Union(left_rect);
- synthetic_invalidation.Union(right_rect);
- synthetic_invalidation.Union(top_rect);
- synthetic_invalidation.Union(bottom_rect);
- synthetic_invalidation.Union(exposed_rect);
- }
- if (min_toss_y < tiling_.num_tiles_y()) {
- // The same thing occurs here as in the case above, but the invalidation
- // rect is the bounding box around the bottom row of tiles in the min
- // pile. This would be tiles {o,r,u,x,a,d,g,j} in the above picture.
-
- int top = tiling_.TilePositionY(min_toss_y);
- int bottom = top + tiling_.TileSizeY(min_toss_y);
- int left = min_tiling_rect_over_tiles.x();
- int right = min_tiling_rect_over_tiles.right();
-
- int top_until = std::min(interest_rect_over_tiles.y(), bottom);
- int bottom_until = std::max(interest_rect_over_tiles.bottom(), top);
- int left_until = std::min(interest_rect_over_tiles.x(), right);
- int right_until = std::max(interest_rect_over_tiles.right(), left);
-
- int exposed_top = min_tiling_size.height();
- int exposed_top_until = max_tiling_size.height();
- int exposed_left = left;
- int exposed_right = max_tiling_size.width();
- DCHECK_GE(exposed_top, top);
-
- gfx::Rect left_rect(left, top, left_until - left, bottom - top);
- gfx::Rect right_rect(right_until, top, right - right_until, bottom - top);
- gfx::Rect top_rect(left, top, right - left, top_until - top);
- gfx::Rect bottom_rect(
- left, bottom_until, right - left, bottom - bottom_until);
- gfx::Rect exposed_rect(exposed_left,
- exposed_top,
- exposed_right - exposed_left,
- exposed_top_until - exposed_top);
- synthetic_invalidation.Union(left_rect);
- synthetic_invalidation.Union(right_rect);
- synthetic_invalidation.Union(top_rect);
- synthetic_invalidation.Union(bottom_rect);
- synthetic_invalidation.Union(exposed_rect);
- }
- }
-
- // Detect cases where the full pile is invalidated, in this situation we
- // can just drop/invalidate everything.
- if (invalidation->Contains(gfx::Rect(old_tiling_size)) ||
- invalidation->Contains(gfx::Rect(GetSize()))) {
- updated = !picture_map_.empty();
- picture_map_.clear();
- } else {
- // Expand invalidation that is on tiles that aren't in the interest rect and
- // will not be re-recorded below. These tiles are no longer valid and should
- // be considerered fully invalid, so we can know to not keep around raster
- // tiles that intersect with these recording tiles.
- Region invalidation_expanded_to_full_tiles;
-
- for (Region::Iterator i(*invalidation); i.has_rect(); i.next()) {
- gfx::Rect invalid_rect = i.rect();
-
- // This rect covers the bounds (excluding borders) of all tiles whose
- // bounds (including borders) touch the |interest_rect|. This matches
- // the iteration of the |invalid_rect| below which includes borders when
- // calling Invalidate() on pictures.
- gfx::Rect invalid_rect_outside_interest_rect_tiles =
- tiling_.ExpandRectToTileBounds(invalid_rect);
- // We subtract the |interest_rect_over_tiles| which represents the bounds
- // of tiles that will be re-recorded below. This matches the iteration of
- // |interest_rect| below which includes borders.
- // TODO(danakj): We should have a Rect-subtract-Rect-to-2-rects operator
- // instead of using Rect::Subtract which gives you the bounding box of the
- // subtraction.
- invalid_rect_outside_interest_rect_tiles.Subtract(
- interest_rect_over_tiles);
- invalidation_expanded_to_full_tiles.Union(
- invalid_rect_outside_interest_rect_tiles);
-
- // Split this inflated invalidation across tile boundaries and apply it
- // to all tiles that it touches.
- bool include_borders = true;
- for (TilingData::Iterator iter(&tiling_, invalid_rect, include_borders);
- iter;
- ++iter) {
- const PictureMapKey& key = iter.index();
-
- PictureMap::iterator picture_it = picture_map_.find(key);
- if (picture_it == picture_map_.end())
- continue;
-
- updated = true;
- picture_map_.erase(key);
-
- // Invalidate drops the picture so the whole tile better be invalidated
- // if it won't be re-recorded below.
- DCHECK_IMPLIES(!tiling_.TileBounds(key.first, key.second)
- .Intersects(interest_rect_over_tiles),
- invalidation_expanded_to_full_tiles.Contains(
- tiling_.TileBounds(key.first, key.second)));
- }
- }
- invalidation->Union(invalidation_expanded_to_full_tiles);
- }
-
- invalidation->Union(synthetic_invalidation);
- return updated;
-}
-
-void PicturePile::GetInvalidTileRects(const gfx::Rect& interest_rect,
- std::vector<gfx::Rect>* invalid_tiles) {
- // Make a list of all invalid tiles; we will attempt to
- // cluster these into multiple invalidation regions.
- bool include_borders = true;
- for (TilingData::Iterator it(&tiling_, interest_rect, include_borders); it;
- ++it) {
- const PictureMapKey& key = it.index();
- if (picture_map_.find(key) == picture_map_.end())
- invalid_tiles->push_back(tiling_.TileBounds(key.first, key.second));
- }
-}
-
-void PicturePile::CreatePictures(ContentLayerClient* painter,
- RecordingSource::RecordingMode recording_mode,
- const std::vector<gfx::Rect>& record_rects) {
- for (const auto& record_rect : record_rects) {
- gfx::Rect padded_record_rect = PadRect(record_rect);
-
- int repeat_count = std::max(1, slow_down_raster_scale_factor_for_debug_);
- scoped_refptr<Picture> picture;
-
- for (int i = 0; i < repeat_count; i++) {
- picture = Picture::Create(padded_record_rect, painter, tile_grid_size_,
- gather_pixel_refs_, recording_mode);
- // Note the '&&' with previous is-suitable state.
- // This means that once a picture-pile becomes unsuitable for gpu
- // rasterization due to some content, it will continue to be unsuitable
- // even if that content is replaced by gpu-friendly content.
- // This is an optimization to avoid iterating though all pictures in
- // the pile after each invalidation.
- if (is_suitable_for_gpu_rasterization_) {
- const char* reason = nullptr;
- is_suitable_for_gpu_rasterization_ &=
- picture->IsSuitableForGpuRasterization(&reason);
-
- if (!is_suitable_for_gpu_rasterization_) {
- TRACE_EVENT_INSTANT1("cc", "GPU Rasterization Veto",
- TRACE_EVENT_SCOPE_THREAD, "reason", reason);
- }
- }
- }
-
- bool found_tile_for_recorded_picture = false;
-
- bool include_borders = true;
- for (TilingData::Iterator it(&tiling_, padded_record_rect, include_borders);
- it; ++it) {
- const PictureMapKey& key = it.index();
- gfx::Rect tile = PaddedRect(key);
- if (padded_record_rect.Contains(tile)) {
- picture_map_[key] = picture;
- found_tile_for_recorded_picture = true;
- }
- }
- DCHECK(found_tile_for_recorded_picture);
- }
-}
-
-scoped_refptr<RasterSource> PicturePile::CreateRasterSource(
- bool can_use_lcd_text) const {
- return scoped_refptr<RasterSource>(
- PicturePileImpl::CreateFromPicturePile(this, can_use_lcd_text));
-}
-
-gfx::Size PicturePile::GetSize() const {
- return tiling_.tiling_size();
-}
-
-void PicturePile::SetEmptyBounds() {
- tiling_.SetTilingSize(gfx::Size());
- Clear();
-}
-
-void PicturePile::SetMinContentsScale(float min_contents_scale) {
- DCHECK(min_contents_scale);
- if (min_contents_scale_ == min_contents_scale)
- return;
-
- // Picture contents are played back scaled. When the final contents scale is
- // less than 1 (i.e. low res), then multiple recorded pixels will be used
- // to raster one final pixel. To avoid splitting a final pixel across
- // pictures (which would result in incorrect rasterization due to blending), a
- // buffer margin is added so that any picture can be snapped to integral
- // final pixels.
- //
- // For example, if a 1/4 contents scale is used, then that would be 3 buffer
- // pixels, since that's the minimum number of pixels to add so that resulting
- // content can be snapped to a four pixel aligned grid.
- int buffer_pixels = static_cast<int>(ceil(1 / min_contents_scale) - 1);
- buffer_pixels = std::max(0, buffer_pixels);
- SetBufferPixels(buffer_pixels);
- min_contents_scale_ = min_contents_scale;
-}
-
-void PicturePile::SetSlowdownRasterScaleFactor(int factor) {
- slow_down_raster_scale_factor_for_debug_ = factor;
-}
-
-void PicturePile::SetGatherPixelRefs(bool gather_pixel_refs) {
- gather_pixel_refs_ = gather_pixel_refs;
-}
-
-void PicturePile::SetBackgroundColor(SkColor background_color) {
- background_color_ = background_color;
-}
-
-void PicturePile::SetRequiresClear(bool requires_clear) {
- requires_clear_ = requires_clear;
-}
-
-bool PicturePile::IsSuitableForGpuRasterization() const {
- return is_suitable_for_gpu_rasterization_;
-}
-
-void PicturePile::SetTileGridSize(const gfx::Size& tile_grid_size) {
- DCHECK_GT(tile_grid_size.width(), 0);
- DCHECK_GT(tile_grid_size.height(), 0);
-
- tile_grid_size_ = tile_grid_size;
-}
-
-void PicturePile::SetUnsuitableForGpuRasterizationForTesting() {
- is_suitable_for_gpu_rasterization_ = false;
-}
-
-gfx::Size PicturePile::GetTileGridSizeForTesting() const {
- return tile_grid_size_;
-}
-
-bool PicturePile::CanRasterSlowTileCheck(const gfx::Rect& layer_rect) const {
- bool include_borders = false;
- for (TilingData::Iterator tile_iter(&tiling_, layer_rect, include_borders);
- tile_iter; ++tile_iter) {
- PictureMap::const_iterator map_iter = picture_map_.find(tile_iter.index());
- if (map_iter == picture_map_.end())
- return false;
- }
- return true;
-}
-
-void PicturePile::DetermineIfSolidColor() {
- is_solid_color_ = false;
- solid_color_ = SK_ColorTRANSPARENT;
-
- if (picture_map_.empty()) {
- return;
- }
-
- PictureMap::const_iterator it = picture_map_.begin();
- const Picture* picture = it->second.get();
-
- // Missing recordings due to frequent invalidations or being too far away
- // from the interest rect will cause the a null picture to exist.
- if (!picture)
- return;
-
- // Don't bother doing more work if the first image is too complicated.
- if (picture->ApproximateOpCount() > kOpCountThatIsOkToAnalyze)
- return;
-
- // Make sure all of the mapped images point to the same picture.
- for (++it; it != picture_map_.end(); ++it) {
- if (it->second.get() != picture)
- return;
- }
-
- gfx::Size layer_size = GetSize();
- skia::AnalysisCanvas canvas(layer_size.width(), layer_size.height());
-
- picture->Raster(&canvas, nullptr, Region(), 1.0f);
- is_solid_color_ = canvas.GetColorIfSolid(&solid_color_);
-}
-
-gfx::Rect PicturePile::PaddedRect(const PictureMapKey& key) const {
- gfx::Rect tile = tiling_.TileBounds(key.first, key.second);
- return PadRect(tile);
-}
-
-gfx::Rect PicturePile::PadRect(const gfx::Rect& rect) const {
- gfx::Rect padded_rect = rect;
- padded_rect.Inset(-buffer_pixels(), -buffer_pixels(), -buffer_pixels(),
- -buffer_pixels());
- return padded_rect;
-}
-
-void PicturePile::Clear() {
- picture_map_.clear();
- recorded_viewport_ = gfx::Rect();
- has_any_recordings_ = false;
- is_solid_color_ = false;
-}
-
-void PicturePile::SetBufferPixels(int new_buffer_pixels) {
- if (new_buffer_pixels == buffer_pixels())
- return;
-
- Clear();
- tiling_.SetBorderTexels(new_buffer_pixels);
-}
-
-} // namespace cc
diff --git a/chromium/cc/playback/picture_pile.h b/chromium/cc/playback/picture_pile.h
deleted file mode 100644
index 889e9f5d981..00000000000
--- a/chromium/cc/playback/picture_pile.h
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CC_PLAYBACK_PICTURE_PILE_H_
-#define CC_PLAYBACK_PICTURE_PILE_H_
-
-#include <bitset>
-#include <utility>
-#include <vector>
-
-#include "base/containers/hash_tables.h"
-#include "base/memory/ref_counted.h"
-#include "cc/base/tiling_data.h"
-#include "cc/playback/picture.h"
-
-namespace cc {
-class PicturePileImpl;
-
-class CC_EXPORT PicturePile : public RecordingSource {
- public:
- PicturePile(float min_contents_scale, const gfx::Size& tile_grid_size);
- ~PicturePile() override;
-
- // RecordingSource overrides.
- bool UpdateAndExpandInvalidation(ContentLayerClient* painter,
- Region* invalidation,
- const gfx::Size& layer_size,
- const gfx::Rect& visible_layer_rect,
- int frame_number,
- RecordingMode recording_mode) override;
- scoped_refptr<RasterSource> CreateRasterSource(
- bool can_use_lcd_text) const override;
- gfx::Size GetSize() const final;
- void SetEmptyBounds() override;
- void SetSlowdownRasterScaleFactor(int factor) override;
- void SetGatherPixelRefs(bool gather_pixel_refs) override;
- void SetBackgroundColor(SkColor background_color) override;
- void SetRequiresClear(bool requires_clear) override;
- bool IsSuitableForGpuRasterization() const override;
- void SetUnsuitableForGpuRasterizationForTesting() override;
- gfx::Size GetTileGridSizeForTesting() const override;
-
- typedef std::pair<int, int> PictureMapKey;
- typedef base::hash_map<PictureMapKey, scoped_refptr<const Picture>>
- PictureMap;
-
- // An internal CanRaster check that goes to the picture_map rather than
- // using the recorded_viewport hint.
- bool CanRasterSlowTileCheck(const gfx::Rect& layer_rect) const;
-
- void Clear();
-
- void SetMinContentsScale(float min_contents_scale);
- void SetTileGridSize(const gfx::Size& tile_grid_size);
-
- gfx::Rect PaddedRect(const PictureMapKey& key) const;
- gfx::Rect PadRect(const gfx::Rect& rect) const;
-
- int buffer_pixels() const { return tiling_.border_texels(); }
-
- // A picture pile is a tiled set of pictures. The picture map is a map of tile
- // indices to picture infos.
- PictureMap picture_map_;
- TilingData tiling_;
-
- // If non-empty, all pictures tiles inside this rect are recorded. There may
- // be recordings outside this rect, but everything inside the rect is
- // recorded.
- gfx::Rect recorded_viewport_;
- float min_contents_scale_;
- gfx::Size tile_grid_size_;
- int slow_down_raster_scale_factor_for_debug_;
- bool gather_pixel_refs_;
- // A hint about whether there are any recordings. This may be a false
- // positive.
- bool has_any_recordings_;
- bool clear_canvas_with_debug_color_;
- bool requires_clear_;
- bool is_solid_color_;
- SkColor solid_color_;
- SkColor background_color_;
- int pixel_record_distance_;
-
- private:
- friend class PicturePileImpl;
-
- void CreatePictures(ContentLayerClient* painter,
- RecordingMode recording_mode,
- const std::vector<gfx::Rect>& record_rects);
- void GetInvalidTileRects(const gfx::Rect& interest_rect,
- std::vector<gfx::Rect>* invalid_tiles);
- bool ApplyInvalidationAndResize(const gfx::Rect& interest_rect,
- Region* invalidation,
- const gfx::Size& layer_size,
- int frame_number);
- void DetermineIfSolidColor();
- void SetBufferPixels(int buffer_pixels);
-
- bool is_suitable_for_gpu_rasterization_;
-
- DISALLOW_COPY_AND_ASSIGN(PicturePile);
-};
-
-} // namespace cc
-
-#endif // CC_PLAYBACK_PICTURE_PILE_H_
diff --git a/chromium/cc/playback/picture_pile_impl.cc b/chromium/cc/playback/picture_pile_impl.cc
deleted file mode 100644
index 345c24c7093..00000000000
--- a/chromium/cc/playback/picture_pile_impl.cc
+++ /dev/null
@@ -1,465 +0,0 @@
-// Copyright 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <algorithm>
-#include <limits>
-#include <set>
-
-#include "base/trace_event/trace_event.h"
-#include "cc/base/region.h"
-#include "cc/debug/debug_colors.h"
-#include "cc/playback/picture_pile_impl.h"
-#include "cc/playback/raster_source_helper.h"
-#include "skia/ext/analysis_canvas.h"
-#include "third_party/skia/include/core/SkCanvas.h"
-#include "third_party/skia/include/core/SkPictureRecorder.h"
-#include "ui/gfx/geometry/rect_conversions.h"
-
-namespace cc {
-
-scoped_refptr<PicturePileImpl> PicturePileImpl::CreateFromPicturePile(
- const PicturePile* other,
- bool can_use_lcd_text) {
- return make_scoped_refptr(new PicturePileImpl(other, can_use_lcd_text));
-}
-
-PicturePileImpl::PicturePileImpl()
- : background_color_(SK_ColorTRANSPARENT),
- requires_clear_(true),
- can_use_lcd_text_(true),
- is_solid_color_(false),
- solid_color_(SK_ColorTRANSPARENT),
- has_any_recordings_(false),
- clear_canvas_with_debug_color_(false),
- min_contents_scale_(0.f),
- slow_down_raster_scale_factor_for_debug_(0),
- should_attempt_to_use_distance_field_text_(false),
- picture_memory_usage_(0) {
-}
-
-PicturePileImpl::PicturePileImpl(const PicturePile* other,
- bool can_use_lcd_text)
- : picture_map_(other->picture_map_),
- tiling_(other->tiling_),
- background_color_(other->background_color_),
- requires_clear_(other->requires_clear_),
- can_use_lcd_text_(can_use_lcd_text),
- is_solid_color_(other->is_solid_color_),
- solid_color_(other->solid_color_),
- recorded_viewport_(other->recorded_viewport_),
- has_any_recordings_(other->has_any_recordings_),
- clear_canvas_with_debug_color_(other->clear_canvas_with_debug_color_),
- min_contents_scale_(other->min_contents_scale_),
- slow_down_raster_scale_factor_for_debug_(
- other->slow_down_raster_scale_factor_for_debug_),
- should_attempt_to_use_distance_field_text_(false),
- picture_memory_usage_(0) {
- // Figure out the picture size upon construction.
- base::hash_set<const Picture*> pictures_seen;
- for (const auto& map_value : picture_map_) {
- const Picture* picture = map_value.second.get();
- if (pictures_seen.insert(picture).second)
- picture_memory_usage_ += picture->ApproximateMemoryUsage();
- }
-}
-
-PicturePileImpl::PicturePileImpl(const PicturePileImpl* other,
- bool can_use_lcd_text)
- : picture_map_(other->picture_map_),
- tiling_(other->tiling_),
- background_color_(other->background_color_),
- requires_clear_(other->requires_clear_),
- can_use_lcd_text_(can_use_lcd_text),
- is_solid_color_(other->is_solid_color_),
- solid_color_(other->solid_color_),
- recorded_viewport_(other->recorded_viewport_),
- has_any_recordings_(other->has_any_recordings_),
- clear_canvas_with_debug_color_(other->clear_canvas_with_debug_color_),
- min_contents_scale_(other->min_contents_scale_),
- slow_down_raster_scale_factor_for_debug_(
- other->slow_down_raster_scale_factor_for_debug_),
- should_attempt_to_use_distance_field_text_(
- other->should_attempt_to_use_distance_field_text_),
- picture_memory_usage_(other->picture_memory_usage_) {
-}
-
-PicturePileImpl::~PicturePileImpl() {
-}
-
-void PicturePileImpl::PlaybackToSharedCanvas(SkCanvas* canvas,
- const gfx::Rect& canvas_rect,
- float contents_scale) const {
- RasterCommon(canvas, NULL, canvas_rect, contents_scale);
-}
-
-void PicturePileImpl::RasterForAnalysis(skia::AnalysisCanvas* canvas,
- const gfx::Rect& canvas_rect,
- float contents_scale) const {
- RasterCommon(canvas, canvas, canvas_rect, contents_scale);
-}
-
-void PicturePileImpl::PlaybackToCanvas(SkCanvas* canvas,
- const gfx::Rect& canvas_bitmap_rect,
- const gfx::Rect& canvas_playback_rect,
- float contents_scale) const {
- RasterSourceHelper::PrepareForPlaybackToCanvas(
- canvas, canvas_bitmap_rect, canvas_bitmap_rect,
- gfx::Rect(tiling_.tiling_size()), contents_scale, background_color_,
- clear_canvas_with_debug_color_, requires_clear_);
- RasterCommon(canvas, NULL, canvas_bitmap_rect, contents_scale);
-}
-
-void PicturePileImpl::CoalesceRasters(const gfx::Rect& canvas_rect,
- const gfx::Rect& content_rect,
- float contents_scale,
- PictureRegionMap* results) const {
- DCHECK(results);
- // Rasterize the collection of relevant picture piles.
- gfx::Rect layer_rect = gfx::ScaleToEnclosingRect(
- content_rect, 1.f / contents_scale);
-
- // Make sure pictures don't overlap by keeping track of previous right/bottom.
- int min_content_left = -1;
- int min_content_top = -1;
- int last_row_index = -1;
- int last_col_index = -1;
- gfx::Rect last_content_rect;
-
- // Coalesce rasters of the same picture into different rects:
- // - Compute the clip of each of the pile chunks,
- // - Subtract it from the canvas rect to get difference region
- // - Later, use the difference region to subtract each of the comprising
- // rects from the canvas.
- // Note that in essence, we're trying to mimic clipRegion with intersect op
- // that also respects the current canvas transform and clip. In order to use
- // the canvas transform, we must stick to clipRect operations (clipRegion
- // ignores the transform). Intersect then can be written as subtracting the
- // negation of the region we're trying to intersect. Luckily, we know that all
- // of the rects will have to fit into |content_rect|, so we can start with
- // that and subtract chunk rects to get the region that we need to subtract
- // from the canvas. Then, we can use clipRect with difference op to subtract
- // each rect in the region.
- bool include_borders = true;
- for (TilingData::Iterator tile_iter(&tiling_, layer_rect, include_borders);
- tile_iter;
- ++tile_iter) {
- PictureMap::const_iterator map_iter = picture_map_.find(tile_iter.index());
- if (map_iter == picture_map_.end())
- continue;
- const Picture* picture = map_iter->second.get();
- DCHECK(picture);
-
- // This is intentionally *enclosed* rect, so that the clip is aligned on
- // integral post-scale content pixels and does not extend past the edges
- // of the picture chunk's layer rect. The min_contents_scale enforces that
- // enough buffer pixels have been added such that the enclosed rect
- // encompasses all invalidated pixels at any larger scale level.
- gfx::Rect chunk_rect = PaddedRect(tile_iter.index());
- gfx::Rect content_clip =
- gfx::ScaleToEnclosedRect(chunk_rect, contents_scale);
- DCHECK(!content_clip.IsEmpty()) << "Layer rect: "
- << picture->LayerRect().ToString()
- << "Contents scale: " << contents_scale;
- content_clip.Intersect(canvas_rect);
-
- // Make sure iterator goes top->bottom.
- DCHECK_GE(tile_iter.index_y(), last_row_index);
- if (tile_iter.index_y() > last_row_index) {
- // First tile in a new row.
- min_content_left = content_clip.x();
- min_content_top = last_content_rect.bottom();
- } else {
- // Make sure iterator goes left->right.
- DCHECK_GT(tile_iter.index_x(), last_col_index);
- min_content_left = last_content_rect.right();
- min_content_top = last_content_rect.y();
- }
-
- last_col_index = tile_iter.index_x();
- last_row_index = tile_iter.index_y();
-
- // Only inset if the content_clip is less than then previous min.
- int inset_left = std::max(0, min_content_left - content_clip.x());
- int inset_top = std::max(0, min_content_top - content_clip.y());
- content_clip.Inset(inset_left, inset_top, 0, 0);
-
- PictureRegionMap::iterator it = results->find(picture);
- Region* clip_region;
- if (it == results->end()) {
- // The clip for a set of coalesced pictures starts out clipping the entire
- // canvas. Each picture added to the set must subtract its own bounds
- // from the clip region, poking a hole so that the picture is unclipped.
- clip_region = &(*results)[picture];
- *clip_region = canvas_rect;
- } else {
- clip_region = &it->second;
- }
-
- DCHECK(clip_region->Contains(content_clip))
- << "Content clips should not overlap.";
- clip_region->Subtract(content_clip);
- last_content_rect = content_clip;
- }
-}
-
-void PicturePileImpl::RasterCommon(SkCanvas* canvas,
- SkPicture::AbortCallback* callback,
- const gfx::Rect& canvas_rect,
- float contents_scale) const {
- DCHECK(contents_scale >= min_contents_scale_);
-
- canvas->translate(-canvas_rect.x(), -canvas_rect.y());
- gfx::Rect content_tiling_rect = gfx::ToEnclosingRect(
- gfx::ScaleRect(gfx::Rect(tiling_.tiling_size()), contents_scale));
- content_tiling_rect.Intersect(canvas_rect);
-
- canvas->clipRect(gfx::RectToSkRect(content_tiling_rect),
- SkRegion::kIntersect_Op);
-
- PictureRegionMap picture_region_map;
- CoalesceRasters(
- canvas_rect, content_tiling_rect, contents_scale, &picture_region_map);
-
-#ifndef NDEBUG
- Region total_clip;
-#endif // NDEBUG
-
- // Iterate the coalesced map and use each picture's region
- // to clip the canvas.
- for (PictureRegionMap::iterator it = picture_region_map.begin();
- it != picture_region_map.end();
- ++it) {
- const Picture* picture = it->first;
- Region negated_clip_region = it->second;
-
-#ifndef NDEBUG
- Region positive_clip = content_tiling_rect;
- positive_clip.Subtract(negated_clip_region);
- // Make sure we never rasterize the same region twice.
- DCHECK(!total_clip.Intersects(positive_clip));
- total_clip.Union(positive_clip);
-#endif // NDEBUG
-
- int repeat_count = std::max(1, slow_down_raster_scale_factor_for_debug_);
-
- for (int j = 0; j < repeat_count; ++j)
- picture->Raster(canvas, callback, negated_clip_region, contents_scale);
- }
-
-#ifndef NDEBUG
- // Fill the clip with debug color. This allows us to
- // distinguish between non painted areas and problems with missing
- // pictures.
- SkPaint paint;
- for (Region::Iterator it(total_clip); it.has_rect(); it.next())
- canvas->clipRect(gfx::RectToSkRect(it.rect()), SkRegion::kDifference_Op);
- paint.setColor(DebugColors::MissingPictureFillColor());
- paint.setXfermodeMode(SkXfermode::kSrc_Mode);
- canvas->drawPaint(paint);
-#endif // NDEBUG
-}
-
-skia::RefPtr<SkPicture> PicturePileImpl::GetFlattenedPicture() {
- TRACE_EVENT0("cc", "PicturePileImpl::GetFlattenedPicture");
-
- gfx::Rect tiling_rect(tiling_.tiling_size());
- SkPictureRecorder recorder;
- SkCanvas* canvas =
- recorder.beginRecording(tiling_rect.width(), tiling_rect.height());
- if (!tiling_rect.IsEmpty())
- PlaybackToCanvas(canvas, tiling_rect, tiling_rect, 1.0);
- skia::RefPtr<SkPicture> picture =
- skia::AdoptRef(recorder.endRecordingAsPicture());
-
- return picture;
-}
-
-size_t PicturePileImpl::GetPictureMemoryUsage() const {
- return picture_memory_usage_;
-}
-
-void PicturePileImpl::PerformSolidColorAnalysis(
- const gfx::Rect& content_rect,
- float contents_scale,
- RasterSource::SolidColorAnalysis* analysis) const {
- DCHECK(analysis);
- TRACE_EVENT0("cc", "PicturePileImpl::PerformSolidColorAnalysis");
-
- gfx::Rect layer_rect = gfx::ScaleToEnclosingRect(
- content_rect, 1.0f / contents_scale);
-
- layer_rect.Intersect(gfx::Rect(tiling_.tiling_size()));
-
- skia::AnalysisCanvas canvas(layer_rect.width(), layer_rect.height());
-
- RasterForAnalysis(&canvas, layer_rect, 1.0f);
-
- analysis->is_solid_color = canvas.GetColorIfSolid(&analysis->solid_color);
-}
-
-void PicturePileImpl::GatherPixelRefs(
- const gfx::Rect& content_rect,
- float contents_scale,
- std::vector<SkPixelRef*>* pixel_refs) const {
- DCHECK_EQ(0u, pixel_refs->size());
- for (PixelRefIterator iter(content_rect, contents_scale, this); iter;
- ++iter) {
- pixel_refs->push_back(*iter);
- }
-}
-
-bool PicturePileImpl::CoversRect(const gfx::Rect& content_rect,
- float contents_scale) const {
- if (tiling_.tiling_size().IsEmpty())
- return false;
- gfx::Rect layer_rect =
- gfx::ScaleToEnclosingRect(content_rect, 1.f / contents_scale);
- layer_rect.Intersect(gfx::Rect(tiling_.tiling_size()));
-
- // Common case inside of viewport to avoid the slower map lookups.
- if (recorded_viewport_.Contains(layer_rect)) {
- // Sanity check that there are no false positives in recorded_viewport_.
- DCHECK(CanRasterSlowTileCheck(layer_rect));
- return true;
- }
-
- return CanRasterSlowTileCheck(layer_rect);
-}
-
-gfx::Size PicturePileImpl::GetSize() const {
- return tiling_.tiling_size();
-}
-
-bool PicturePileImpl::IsSolidColor() const {
- return is_solid_color_;
-}
-
-SkColor PicturePileImpl::GetSolidColor() const {
- DCHECK(IsSolidColor());
- return solid_color_;
-}
-
-bool PicturePileImpl::HasRecordings() const {
- return has_any_recordings_;
-}
-
-gfx::Rect PicturePileImpl::PaddedRect(const PictureMapKey& key) const {
- gfx::Rect padded_rect = tiling_.TileBounds(key.first, key.second);
- padded_rect.Inset(-buffer_pixels(), -buffer_pixels(), -buffer_pixels(),
- -buffer_pixels());
- return padded_rect;
-}
-
-bool PicturePileImpl::CanRasterSlowTileCheck(
- const gfx::Rect& layer_rect) const {
- bool include_borders = false;
- for (TilingData::Iterator tile_iter(&tiling_, layer_rect, include_borders);
- tile_iter; ++tile_iter) {
- PictureMap::const_iterator map_iter = picture_map_.find(tile_iter.index());
- if (map_iter == picture_map_.end())
- return false;
- }
- return true;
-}
-
-void PicturePileImpl::SetShouldAttemptToUseDistanceFieldText() {
- should_attempt_to_use_distance_field_text_ = true;
-}
-
-bool PicturePileImpl::ShouldAttemptToUseDistanceFieldText() const {
- return should_attempt_to_use_distance_field_text_;
-}
-
-void PicturePileImpl::AsValueInto(
- base::trace_event::TracedValue* pictures) const {
- gfx::Rect tiling_rect(tiling_.tiling_size());
- std::set<const void*> appended_pictures;
- bool include_borders = true;
- for (TilingData::Iterator tile_iter(&tiling_, tiling_rect, include_borders);
- tile_iter; ++tile_iter) {
- PictureMap::const_iterator map_iter = picture_map_.find(tile_iter.index());
- if (map_iter == picture_map_.end())
- continue;
-
- const Picture* picture = map_iter->second.get();
- if (appended_pictures.count(picture) == 0) {
- appended_pictures.insert(picture);
- TracedValue::AppendIDRef(picture, pictures);
- }
- }
-}
-
-bool PicturePileImpl::CanUseLCDText() const {
- return can_use_lcd_text_;
-}
-
-scoped_refptr<RasterSource> PicturePileImpl::CreateCloneWithoutLCDText() const {
- DCHECK(CanUseLCDText());
- bool can_use_lcd_text = false;
- return scoped_refptr<RasterSource>(
- new PicturePileImpl(this, can_use_lcd_text));
-}
-
-PicturePileImpl::PixelRefIterator::PixelRefIterator(
- const gfx::Rect& content_rect,
- float contents_scale,
- const PicturePileImpl* picture_pile)
- : picture_pile_(picture_pile),
- layer_rect_(
- gfx::ScaleToEnclosingRect(content_rect, 1.f / contents_scale)),
- tile_iterator_(&picture_pile_->tiling_,
- layer_rect_,
- false /* include_borders */) {
- // Early out if there isn't a single tile.
- if (!tile_iterator_)
- return;
-
- AdvanceToTilePictureWithPixelRefs();
-}
-
-PicturePileImpl::PixelRefIterator::~PixelRefIterator() {
-}
-
-PicturePileImpl::PixelRefIterator&
- PicturePileImpl::PixelRefIterator::operator++() {
- ++pixel_ref_iterator_;
- if (pixel_ref_iterator_)
- return *this;
-
- ++tile_iterator_;
- AdvanceToTilePictureWithPixelRefs();
- return *this;
-}
-
-void PicturePileImpl::PixelRefIterator::AdvanceToTilePictureWithPixelRefs() {
- for (; tile_iterator_; ++tile_iterator_) {
- PictureMap::const_iterator it =
- picture_pile_->picture_map_.find(tile_iterator_.index());
- if (it == picture_pile_->picture_map_.end())
- continue;
-
- const Picture* picture = it->second.get();
- if ((processed_pictures_.count(picture) != 0) ||
- !picture->WillPlayBackBitmaps())
- continue;
-
- processed_pictures_.insert(picture);
- pixel_ref_iterator_ = picture->GetPixelRefMapIterator(layer_rect_);
- if (pixel_ref_iterator_)
- break;
- }
-}
-
-void PicturePileImpl::DidBeginTracing() {
- std::set<const void*> processed_pictures;
- for (const auto& map_pair : picture_map_) {
- const Picture* picture = map_pair.second.get();
- if (processed_pictures.count(picture) == 0) {
- picture->EmitTraceSnapshot();
- processed_pictures.insert(picture);
- }
- }
-}
-
-} // namespace cc
diff --git a/chromium/cc/playback/picture_pile_impl.h b/chromium/cc/playback/picture_pile_impl.h
deleted file mode 100644
index 0e1164b2dff..00000000000
--- a/chromium/cc/playback/picture_pile_impl.h
+++ /dev/null
@@ -1,160 +0,0 @@
-// Copyright 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CC_PLAYBACK_PICTURE_PILE_IMPL_H_
-#define CC_PLAYBACK_PICTURE_PILE_IMPL_H_
-
-#include <map>
-#include <set>
-#include <vector>
-
-#include "base/time/time.h"
-#include "cc/base/cc_export.h"
-#include "cc/debug/rendering_stats_instrumentation.h"
-#include "cc/playback/picture_pile.h"
-#include "cc/playback/pixel_ref_map.h"
-#include "cc/playback/raster_source.h"
-#include "skia/ext/analysis_canvas.h"
-#include "skia/ext/refptr.h"
-
-class SkCanvas;
-class SkPicture;
-class SkPixelRef;
-
-namespace gfx {
-class Rect;
-}
-
-namespace cc {
-
-class CC_EXPORT PicturePileImpl : public RasterSource {
- public:
- static scoped_refptr<PicturePileImpl> CreateFromPicturePile(
- const PicturePile* other,
- bool can_use_lcd_text);
-
- // RasterSource overrides. See RasterSource header for full description.
- // When slow-down-raster-scale-factor is set to a value greater than 1, the
- // reported rasterize time (in stats_instrumentation) is the minimum measured
- // value over all runs.
- void PlaybackToCanvas(SkCanvas* canvas,
- const gfx::Rect& canvas_bitmap_rect,
- const gfx::Rect& canvas_playback_rect,
- float contents_scale) const override;
- void PlaybackToSharedCanvas(SkCanvas* canvas,
- const gfx::Rect& canvas_rect,
- float contents_scale) const override;
- void PerformSolidColorAnalysis(
- const gfx::Rect& content_rect,
- float contents_scale,
- RasterSource::SolidColorAnalysis* analysis) const override;
- void GatherPixelRefs(const gfx::Rect& content_rect,
- float contents_scale,
- std::vector<SkPixelRef*>* pixel_refs) const override;
- bool CoversRect(const gfx::Rect& content_rect,
- float contents_scale) const override;
- void SetShouldAttemptToUseDistanceFieldText() override;
- bool ShouldAttemptToUseDistanceFieldText() const override;
- gfx::Size GetSize() const override;
- bool IsSolidColor() const override;
- SkColor GetSolidColor() const override;
- bool HasRecordings() const override;
- bool CanUseLCDText() const override;
- scoped_refptr<RasterSource> CreateCloneWithoutLCDText() const override;
-
- // Tracing functionality.
- void DidBeginTracing() override;
- void AsValueInto(base::trace_event::TracedValue* array) const override;
- skia::RefPtr<SkPicture> GetFlattenedPicture() override;
- size_t GetPictureMemoryUsage() const override;
-
- // Iterator used to return SkPixelRefs from this picture pile.
- // Public for testing.
- class CC_EXPORT PixelRefIterator {
- public:
- PixelRefIterator(const gfx::Rect& content_rect,
- float contents_scale,
- const PicturePileImpl* picture_pile);
- ~PixelRefIterator();
-
- SkPixelRef* operator->() const { return *pixel_ref_iterator_; }
- SkPixelRef* operator*() const { return *pixel_ref_iterator_; }
- PixelRefIterator& operator++();
- operator bool() const { return pixel_ref_iterator_; }
-
- private:
- void AdvanceToTilePictureWithPixelRefs();
-
- const PicturePileImpl* picture_pile_;
- gfx::Rect layer_rect_;
- TilingData::Iterator tile_iterator_;
- PixelRefMap::Iterator pixel_ref_iterator_;
- std::set<const void*> processed_pictures_;
- };
-
- protected:
- friend class PicturePile;
- friend class PixelRefIterator;
-
- using PictureMapKey = PicturePile::PictureMapKey;
- using PictureMap = PicturePile::PictureMap;
-
- PicturePileImpl();
- explicit PicturePileImpl(const PicturePile* other, bool can_use_lcd_text);
- explicit PicturePileImpl(const PicturePileImpl* other, bool can_use_lcd_text);
- ~PicturePileImpl() override;
-
- int buffer_pixels() const { return tiling_.border_texels(); }
-
- // These members are const as this raster source may be in use on another
- // thread and so should not be touched after construction.
- const PictureMap picture_map_;
- const TilingData tiling_;
- const SkColor background_color_;
- const bool requires_clear_;
- const bool can_use_lcd_text_;
- const bool is_solid_color_;
- const SkColor solid_color_;
- const gfx::Rect recorded_viewport_;
- const bool has_any_recordings_;
- const bool clear_canvas_with_debug_color_;
- const float min_contents_scale_;
- const int slow_down_raster_scale_factor_for_debug_;
- // TODO(enne/vmiura): this has a read/write race between raster and compositor
- // threads with multi-threaded Ganesh. Make this const or remove it.
- bool should_attempt_to_use_distance_field_text_;
-
- size_t picture_memory_usage_;
-
- private:
- typedef std::map<const Picture*, Region> PictureRegionMap;
-
- // Called when analyzing a tile. We can use AnalysisCanvas as
- // SkPicture::AbortCallback, which allows us to early out from analysis.
- void RasterForAnalysis(skia::AnalysisCanvas* canvas,
- const gfx::Rect& canvas_rect,
- float contents_scale) const;
-
- void CoalesceRasters(const gfx::Rect& canvas_rect,
- const gfx::Rect& content_rect,
- float contents_scale,
- PictureRegionMap* result) const;
-
- void RasterCommon(SkCanvas* canvas,
- SkPicture::AbortCallback* callback,
- const gfx::Rect& canvas_rect,
- float contents_scale) const;
-
- // An internal CanRaster check that goes to the picture_map rather than
- // using the recorded_viewport hint.
- bool CanRasterSlowTileCheck(const gfx::Rect& layer_rect) const;
-
- gfx::Rect PaddedRect(const PictureMapKey& key) const;
-
- DISALLOW_COPY_AND_ASSIGN(PicturePileImpl);
-};
-
-} // namespace cc
-
-#endif // CC_PLAYBACK_PICTURE_PILE_IMPL_H_
diff --git a/chromium/cc/playback/picture_pile_impl_perftest.cc b/chromium/cc/playback/picture_pile_impl_perftest.cc
deleted file mode 100644
index e1560400f22..00000000000
--- a/chromium/cc/playback/picture_pile_impl_perftest.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cc/playback/picture_pile_impl.h"
-
-#include "cc/debug/lap_timer.h"
-#include "cc/test/fake_picture_pile_impl.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/perf/perf_test.h"
-
-namespace cc {
-namespace {
-
-const int kTimeLimitMillis = 2000;
-const int kWarmupRuns = 5;
-const int kTimeCheckInterval = 10;
-
-const int kTileSize = 100;
-const int kLayerSize = 1000;
-
-class PicturePileImplPerfTest : public testing::Test {
- public:
- PicturePileImplPerfTest()
- : timer_(kWarmupRuns,
- base::TimeDelta::FromMilliseconds(kTimeLimitMillis),
- kTimeCheckInterval) {}
-
- void RunAnalyzeTest(const std::string& test_name, float contents_scale) {
- scoped_refptr<PicturePileImpl> pile = FakePicturePileImpl::CreateFilledPile(
- gfx::Size(kTileSize, kTileSize), gfx::Size(kLayerSize, kLayerSize));
- // Content rect that will align with top-left tile at scale 1.0.
- gfx::Rect content_rect(0, 0, kTileSize, kTileSize);
-
- RasterSource::SolidColorAnalysis analysis;
- timer_.Reset();
- do {
- pile->PerformSolidColorAnalysis(content_rect, contents_scale, &analysis);
- timer_.NextLap();
- } while (!timer_.HasTimeLimitExpired());
-
- perf_test::PrintResult(
- "analyze", "", test_name, timer_.LapsPerSecond(), "runs/s", true);
- }
-
- void RunRasterTest(const std::string& test_name, float contents_scale) {
- scoped_refptr<PicturePileImpl> pile = FakePicturePileImpl::CreateFilledPile(
- gfx::Size(kTileSize, kTileSize), gfx::Size(kLayerSize, kLayerSize));
- // Content rect that will align with top-left tile at scale 1.0.
- gfx::Rect content_rect(0, 0, kTileSize, kTileSize);
-
- SkBitmap bitmap;
- bitmap.allocN32Pixels(1, 1);
- SkCanvas canvas(bitmap);
-
- timer_.Reset();
- do {
- pile->PlaybackToCanvas(&canvas, content_rect, content_rect,
- contents_scale);
- timer_.NextLap();
- } while (!timer_.HasTimeLimitExpired());
-
- perf_test::PrintResult(
- "raster", "", test_name, timer_.LapsPerSecond(), "runs/s", true);
- }
-
- private:
- LapTimer timer_;
-};
-
-TEST_F(PicturePileImplPerfTest, Analyze) {
- RunAnalyzeTest("1", 1.0f);
- RunAnalyzeTest("4", 0.5f);
- RunAnalyzeTest("100", 0.1f);
-}
-
-TEST_F(PicturePileImplPerfTest, Raster) {
- RunRasterTest("1", 1.0f);
- RunRasterTest("4", 0.5f);
- RunRasterTest("100", 0.1f);
-}
-
-} // namespace
-} // namespace cc
diff --git a/chromium/cc/playback/picture_pile_impl_unittest.cc b/chromium/cc/playback/picture_pile_impl_unittest.cc
deleted file mode 100644
index 81c2aec4713..00000000000
--- a/chromium/cc/playback/picture_pile_impl_unittest.cc
+++ /dev/null
@@ -1,550 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/memory/scoped_ptr.h"
-#include "cc/test/fake_picture_pile_impl.h"
-#include "cc/test/skia_common.h"
-#include "skia/ext/refptr.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/skia/include/core/SkPixelRef.h"
-#include "third_party/skia/include/core/SkShader.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/geometry/size_conversions.h"
-
-namespace cc {
-namespace {
-
-TEST(PicturePileImplTest, AnalyzeIsSolidUnscaled) {
- gfx::Size tile_size(100, 100);
- gfx::Size layer_bounds(400, 400);
-
- scoped_ptr<FakePicturePile> recording_source =
- FakePicturePile::CreateFilledPile(tile_size, layer_bounds);
-
- SkPaint solid_paint;
- SkColor solid_color = SkColorSetARGB(255, 12, 23, 34);
- solid_paint.setColor(solid_color);
-
- SkColor non_solid_color = SkColorSetARGB(128, 45, 56, 67);
- SkPaint non_solid_paint;
- non_solid_paint.setColor(non_solid_color);
-
- recording_source->add_draw_rect_with_paint(gfx::Rect(0, 0, 400, 400),
- solid_paint);
- recording_source->Rerecord();
-
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFromPile(recording_source.get(), nullptr);
-
- // Ensure everything is solid.
- for (int y = 0; y <= 300; y += 100) {
- for (int x = 0; x <= 300; x += 100) {
- RasterSource::SolidColorAnalysis analysis;
- gfx::Rect rect(x, y, 100, 100);
- pile->PerformSolidColorAnalysis(rect, 1.0, &analysis);
- EXPECT_TRUE(analysis.is_solid_color) << rect.ToString();
- EXPECT_EQ(analysis.solid_color, solid_color) << rect.ToString();
- }
- }
-
- // Add one non-solid pixel and recreate the raster source.
- recording_source->add_draw_rect_with_paint(gfx::Rect(50, 50, 1, 1),
- non_solid_paint);
- recording_source->Rerecord();
- pile = FakePicturePileImpl::CreateFromPile(recording_source.get(), nullptr);
-
- RasterSource::SolidColorAnalysis analysis;
- pile->PerformSolidColorAnalysis(gfx::Rect(0, 0, 100, 100), 1.0, &analysis);
- EXPECT_FALSE(analysis.is_solid_color);
-
- pile->PerformSolidColorAnalysis(gfx::Rect(100, 0, 100, 100), 1.0, &analysis);
- EXPECT_TRUE(analysis.is_solid_color);
- EXPECT_EQ(analysis.solid_color, solid_color);
-
- // Boundaries should be clipped.
- analysis.is_solid_color = false;
- pile->PerformSolidColorAnalysis(gfx::Rect(350, 0, 100, 100), 1.0, &analysis);
- EXPECT_TRUE(analysis.is_solid_color);
- EXPECT_EQ(analysis.solid_color, solid_color);
-
- analysis.is_solid_color = false;
- pile->PerformSolidColorAnalysis(gfx::Rect(0, 350, 100, 100), 1.0, &analysis);
- EXPECT_TRUE(analysis.is_solid_color);
- EXPECT_EQ(analysis.solid_color, solid_color);
-
- analysis.is_solid_color = false;
- pile->PerformSolidColorAnalysis(gfx::Rect(350, 350, 100, 100), 1.0,
- &analysis);
- EXPECT_TRUE(analysis.is_solid_color);
- EXPECT_EQ(analysis.solid_color, solid_color);
-}
-
-TEST(PicturePileImplTest, AnalyzeIsSolidScaled) {
- gfx::Size tile_size(100, 100);
- gfx::Size layer_bounds(400, 400);
-
- scoped_ptr<FakePicturePile> recording_source =
- FakePicturePile::CreateFilledPile(tile_size, layer_bounds);
-
- SkColor solid_color = SkColorSetARGB(255, 12, 23, 34);
- SkPaint solid_paint;
- solid_paint.setColor(solid_color);
-
- SkColor non_solid_color = SkColorSetARGB(128, 45, 56, 67);
- SkPaint non_solid_paint;
- non_solid_paint.setColor(non_solid_color);
-
- recording_source->add_draw_rect_with_paint(gfx::Rect(0, 0, 400, 400),
- solid_paint);
- recording_source->Rerecord();
-
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFromPile(recording_source.get(), nullptr);
-
- // Ensure everything is solid.
- for (int y = 0; y <= 30; y += 10) {
- for (int x = 0; x <= 30; x += 10) {
- RasterSource::SolidColorAnalysis analysis;
- gfx::Rect rect(x, y, 10, 10);
- pile->PerformSolidColorAnalysis(rect, 0.1f, &analysis);
- EXPECT_TRUE(analysis.is_solid_color) << rect.ToString();
- EXPECT_EQ(analysis.solid_color, solid_color) << rect.ToString();
- }
- }
-
- // Add one non-solid pixel and recreate the raster source.
- recording_source->add_draw_rect_with_paint(gfx::Rect(50, 50, 1, 1),
- non_solid_paint);
- recording_source->Rerecord();
- pile = FakePicturePileImpl::CreateFromPile(recording_source.get(), nullptr);
-
- RasterSource::SolidColorAnalysis analysis;
- pile->PerformSolidColorAnalysis(gfx::Rect(0, 0, 10, 10), 0.1f, &analysis);
- EXPECT_FALSE(analysis.is_solid_color);
-
- pile->PerformSolidColorAnalysis(gfx::Rect(10, 0, 10, 10), 0.1f, &analysis);
- EXPECT_TRUE(analysis.is_solid_color);
- EXPECT_EQ(analysis.solid_color, solid_color);
-
- // Boundaries should be clipped.
- analysis.is_solid_color = false;
- pile->PerformSolidColorAnalysis(gfx::Rect(35, 0, 10, 10), 0.1f, &analysis);
- EXPECT_TRUE(analysis.is_solid_color);
- EXPECT_EQ(analysis.solid_color, solid_color);
-
- analysis.is_solid_color = false;
- pile->PerformSolidColorAnalysis(gfx::Rect(0, 35, 10, 10), 0.1f, &analysis);
- EXPECT_TRUE(analysis.is_solid_color);
- EXPECT_EQ(analysis.solid_color, solid_color);
-
- analysis.is_solid_color = false;
- pile->PerformSolidColorAnalysis(gfx::Rect(35, 35, 10, 10), 0.1f, &analysis);
- EXPECT_TRUE(analysis.is_solid_color);
- EXPECT_EQ(analysis.solid_color, solid_color);
-}
-
-TEST(PicturePileImplTest, AnalyzeIsSolidEmpty) {
- gfx::Size tile_size(100, 100);
- gfx::Size layer_bounds(400, 400);
-
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- RasterSource::SolidColorAnalysis analysis;
- EXPECT_FALSE(analysis.is_solid_color);
-
- pile->PerformSolidColorAnalysis(gfx::Rect(0, 0, 400, 400), 1.f, &analysis);
-
- EXPECT_TRUE(analysis.is_solid_color);
- EXPECT_EQ(analysis.solid_color, SkColorSetARGB(0, 0, 0, 0));
-}
-
-TEST(PicturePileImplTest, PixelRefIteratorDiscardableRefsOneTile) {
- gfx::Size tile_size(256, 256);
- gfx::Size layer_bounds(512, 512);
-
- scoped_ptr<FakePicturePile> recording_source =
- FakePicturePile::CreateFilledPile(tile_size, layer_bounds);
-
- SkBitmap discardable_bitmap[2][2];
- CreateBitmap(gfx::Size(32, 32), "discardable", &discardable_bitmap[0][0]);
- CreateBitmap(gfx::Size(32, 32), "discardable", &discardable_bitmap[0][1]);
- CreateBitmap(gfx::Size(32, 32), "discardable", &discardable_bitmap[1][1]);
-
- // Discardable pixel refs are found in the following cells:
- // |---|---|
- // | x | x |
- // |---|---|
- // | | x |
- // |---|---|
- recording_source->add_draw_bitmap(discardable_bitmap[0][0], gfx::Point(0, 0));
- recording_source->add_draw_bitmap(discardable_bitmap[0][1],
- gfx::Point(260, 0));
- recording_source->add_draw_bitmap(discardable_bitmap[1][1],
- gfx::Point(260, 260));
- recording_source->SetGatherPixelRefs(true);
- recording_source->Rerecord();
-
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFromPile(recording_source.get(), nullptr);
-
- // Tile sized iterators. These should find only one pixel ref.
- {
- PicturePileImpl::PixelRefIterator iterator(
- gfx::Rect(0, 0, 256, 256), 1.0, pile.get());
- EXPECT_TRUE(iterator);
- EXPECT_TRUE(*iterator == discardable_bitmap[0][0].pixelRef());
- EXPECT_FALSE(++iterator);
- }
- {
- PicturePileImpl::PixelRefIterator iterator(
- gfx::Rect(0, 0, 512, 512), 2.0, pile.get());
- EXPECT_TRUE(iterator);
- EXPECT_TRUE(*iterator == discardable_bitmap[0][0].pixelRef());
- EXPECT_FALSE(++iterator);
- }
- {
- PicturePileImpl::PixelRefIterator iterator(
- gfx::Rect(0, 0, 128, 128), 0.5, pile.get());
- EXPECT_TRUE(iterator);
- EXPECT_TRUE(*iterator == discardable_bitmap[0][0].pixelRef());
- EXPECT_FALSE(++iterator);
- }
- // Shifted tile sized iterators. These should find only one pixel ref.
- {
- PicturePileImpl::PixelRefIterator iterator(
- gfx::Rect(260, 260, 256, 256), 1.0, pile.get());
- EXPECT_TRUE(iterator);
- EXPECT_TRUE(*iterator == discardable_bitmap[1][1].pixelRef());
- EXPECT_FALSE(++iterator);
- }
- {
- PicturePileImpl::PixelRefIterator iterator(
- gfx::Rect(520, 520, 512, 512), 2.0, pile.get());
- EXPECT_TRUE(iterator);
- EXPECT_TRUE(*iterator == discardable_bitmap[1][1].pixelRef());
- EXPECT_FALSE(++iterator);
- }
- {
- PicturePileImpl::PixelRefIterator iterator(
- gfx::Rect(130, 130, 128, 128), 0.5, pile.get());
- EXPECT_TRUE(iterator);
- EXPECT_TRUE(*iterator == discardable_bitmap[1][1].pixelRef());
- EXPECT_FALSE(++iterator);
- }
- // Ensure there's no discardable pixel refs in the empty cell
- {
- PicturePileImpl::PixelRefIterator iterator(
- gfx::Rect(0, 256, 256, 256), 1.0, pile.get());
- EXPECT_FALSE(iterator);
- }
- // Layer sized iterators. These should find three pixel ref.
- {
- PicturePileImpl::PixelRefIterator iterator(
- gfx::Rect(0, 0, 512, 512), 1.0, pile.get());
- EXPECT_TRUE(iterator);
- EXPECT_TRUE(*iterator == discardable_bitmap[0][0].pixelRef());
- EXPECT_TRUE(++iterator);
- EXPECT_TRUE(*iterator == discardable_bitmap[0][1].pixelRef());
- EXPECT_TRUE(++iterator);
- EXPECT_TRUE(*iterator == discardable_bitmap[1][1].pixelRef());
- EXPECT_FALSE(++iterator);
- }
- {
- PicturePileImpl::PixelRefIterator iterator(
- gfx::Rect(0, 0, 1024, 1024), 2.0, pile.get());
- EXPECT_TRUE(iterator);
- EXPECT_TRUE(*iterator == discardable_bitmap[0][0].pixelRef());
- EXPECT_TRUE(++iterator);
- EXPECT_TRUE(*iterator == discardable_bitmap[0][1].pixelRef());
- EXPECT_TRUE(++iterator);
- EXPECT_TRUE(*iterator == discardable_bitmap[1][1].pixelRef());
- EXPECT_FALSE(++iterator);
- }
- {
- PicturePileImpl::PixelRefIterator iterator(
- gfx::Rect(0, 0, 256, 256), 0.5, pile.get());
- EXPECT_TRUE(iterator);
- EXPECT_TRUE(*iterator == discardable_bitmap[0][0].pixelRef());
- EXPECT_TRUE(++iterator);
- EXPECT_TRUE(*iterator == discardable_bitmap[0][1].pixelRef());
- EXPECT_TRUE(++iterator);
- EXPECT_TRUE(*iterator == discardable_bitmap[1][1].pixelRef());
- EXPECT_FALSE(++iterator);
- }
-
- // Copy test.
- PicturePileImpl::PixelRefIterator iterator(
- gfx::Rect(0, 0, 512, 512), 1.0, pile.get());
- EXPECT_TRUE(iterator);
- EXPECT_TRUE(*iterator == discardable_bitmap[0][0].pixelRef());
- EXPECT_TRUE(++iterator);
- EXPECT_TRUE(*iterator == discardable_bitmap[0][1].pixelRef());
-
- // copy now points to the same spot as iterator,
- // but both can be incremented independently.
- PicturePileImpl::PixelRefIterator copy = iterator;
- EXPECT_TRUE(++iterator);
- EXPECT_TRUE(*iterator == discardable_bitmap[1][1].pixelRef());
- EXPECT_FALSE(++iterator);
-
- EXPECT_TRUE(copy);
- EXPECT_TRUE(*copy == discardable_bitmap[0][1].pixelRef());
- EXPECT_TRUE(++copy);
- EXPECT_TRUE(*copy == discardable_bitmap[1][1].pixelRef());
- EXPECT_FALSE(++copy);
-}
-
-TEST(PicturePileImplTest, RasterFullContents) {
- gfx::Size tile_size(1000, 1000);
- gfx::Size layer_bounds(3, 5);
- float contents_scale = 1.5f;
- float raster_divisions = 2.f;
-
- scoped_ptr<FakePicturePile> recording_source =
- FakePicturePile::CreateFilledPile(tile_size, layer_bounds);
- recording_source->SetBackgroundColor(SK_ColorBLACK);
- recording_source->SetIsSolidColor(false);
- recording_source->SetRequiresClear(false);
- recording_source->SetClearCanvasWithDebugColor(false);
-
- // Because the caller sets content opaque, it also promises that it
- // has at least filled in layer_bounds opaquely.
- SkPaint white_paint;
- white_paint.setColor(SK_ColorWHITE);
- recording_source->add_draw_rect_with_paint(gfx::Rect(layer_bounds),
- white_paint);
-
- recording_source->SetMinContentsScale(contents_scale);
- recording_source->Rerecord();
-
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFromPile(recording_source.get(), nullptr);
-
- gfx::Size content_bounds(
- gfx::ToCeiledSize(gfx::ScaleSize(layer_bounds, contents_scale)));
-
- // Simulate drawing into different tiles at different offsets.
- int step_x = std::ceil(content_bounds.width() / raster_divisions);
- int step_y = std::ceil(content_bounds.height() / raster_divisions);
- for (int offset_x = 0; offset_x < content_bounds.width();
- offset_x += step_x) {
- for (int offset_y = 0; offset_y < content_bounds.height();
- offset_y += step_y) {
- gfx::Rect content_rect(offset_x, offset_y, step_x, step_y);
- content_rect.Intersect(gfx::Rect(content_bounds));
-
- // Simulate a canvas rect larger than the content rect. Every pixel
- // up to one pixel outside the content rect is guaranteed to be opaque.
- // Outside of that is undefined.
- gfx::Rect canvas_rect(content_rect);
- canvas_rect.Inset(0, 0, -1, -1);
-
- SkBitmap bitmap;
- bitmap.allocN32Pixels(canvas_rect.width(), canvas_rect.height());
- SkCanvas canvas(bitmap);
- canvas.clear(SK_ColorTRANSPARENT);
-
- pile->PlaybackToCanvas(&canvas, canvas_rect, canvas_rect, contents_scale);
-
- SkColor* pixels = reinterpret_cast<SkColor*>(bitmap.getPixels());
- int num_pixels = bitmap.width() * bitmap.height();
- bool all_white = true;
- for (int i = 0; i < num_pixels; ++i) {
- EXPECT_EQ(SkColorGetA(pixels[i]), 255u);
- all_white &= (SkColorGetR(pixels[i]) == 255);
- all_white &= (SkColorGetG(pixels[i]) == 255);
- all_white &= (SkColorGetB(pixels[i]) == 255);
- }
-
- // If the canvas doesn't extend past the edge of the content,
- // it should be entirely white. Otherwise, the edge of the content
- // will be non-white.
- EXPECT_EQ(all_white, gfx::Rect(content_bounds).Contains(canvas_rect));
- }
- }
-}
-
-TEST(PicturePileImpl, RasterContentsTransparent) {
- gfx::Size tile_size(1000, 1000);
- gfx::Size layer_bounds(5, 3);
- float contents_scale = 0.5f;
-
- scoped_ptr<FakePicturePile> recording_source =
- FakePicturePile::CreateFilledPile(tile_size, layer_bounds);
- recording_source->SetBackgroundColor(SK_ColorTRANSPARENT);
- recording_source->SetRequiresClear(true);
- recording_source->SetMinContentsScale(contents_scale);
- recording_source->SetClearCanvasWithDebugColor(false);
- recording_source->Rerecord();
-
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFromPile(recording_source.get(), nullptr);
- gfx::Size content_bounds(
- gfx::ToCeiledSize(gfx::ScaleSize(layer_bounds, contents_scale)));
-
- gfx::Rect canvas_rect(content_bounds);
- canvas_rect.Inset(0, 0, -1, -1);
-
- SkBitmap bitmap;
- bitmap.allocN32Pixels(canvas_rect.width(), canvas_rect.height());
- SkCanvas canvas(bitmap);
-
- pile->PlaybackToCanvas(&canvas, canvas_rect, canvas_rect, contents_scale);
-
- SkColor* pixels = reinterpret_cast<SkColor*>(bitmap.getPixels());
- int num_pixels = bitmap.width() * bitmap.height();
- for (int i = 0; i < num_pixels; ++i) {
- EXPECT_EQ(SkColorGetA(pixels[i]), 0u);
- }
-}
-
-class OverlapTest : public ::testing::TestWithParam<float> {
- public:
- static float MinContentsScale() { return 1.f / 4.f; }
-};
-
-TEST_P(OverlapTest, NoOverlap) {
- gfx::Size tile_size(10, 10);
- gfx::Size layer_bounds(30, 30);
- gfx::Size bigger_than_layer_bounds(300, 300);
- float contents_scale = GetParam();
- // Pick an opaque color to not have to deal with premultiplication off-by-one.
- SkColor test_color = SkColorSetARGB(255, 45, 56, 67);
-
- scoped_ptr<FakePicturePile> recording_source =
- FakePicturePile::CreateFilledPile(tile_size, layer_bounds);
- recording_source->SetBackgroundColor(SK_ColorTRANSPARENT);
- recording_source->SetRequiresClear(true);
- recording_source->SetMinContentsScale(MinContentsScale());
- recording_source->SetClearCanvasWithDebugColor(true);
-
- SkPaint color_paint;
- color_paint.setColor(test_color);
- // Additive paint, so that if two paints overlap, the color will change.
- color_paint.setXfermodeMode(SkXfermode::kPlus_Mode);
- // Paint outside the layer to make sure that blending works.
- recording_source->add_draw_rect_with_paint(
- gfx::RectF(bigger_than_layer_bounds), color_paint);
- recording_source->Rerecord();
-
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFromPile(recording_source.get(), nullptr);
- gfx::Size content_bounds(
- gfx::ToCeiledSize(gfx::ScaleSize(layer_bounds, contents_scale)));
-
- SkBitmap bitmap;
- bitmap.allocN32Pixels(content_bounds.width(), content_bounds.height());
- SkCanvas canvas(bitmap);
-
- pile->PlaybackToCanvas(&canvas, gfx::Rect(content_bounds),
- gfx::Rect(content_bounds), contents_scale);
-
- for (int y = 0; y < bitmap.height(); y++) {
- for (int x = 0; x < bitmap.width(); x++) {
- SkColor color = bitmap.getColor(x, y);
- EXPECT_EQ(SkColorGetR(test_color), SkColorGetR(color)) << "x: " << x
- << ", y: " << y;
- EXPECT_EQ(SkColorGetG(test_color), SkColorGetG(color)) << "x: " << x
- << ", y: " << y;
- EXPECT_EQ(SkColorGetB(test_color), SkColorGetB(color)) << "x: " << x
- << ", y: " << y;
- EXPECT_EQ(SkColorGetA(test_color), SkColorGetA(color)) << "x: " << x
- << ", y: " << y;
- if (test_color != color)
- break;
- }
- }
-}
-
-INSTANTIATE_TEST_CASE_P(PicturePileImpl,
- OverlapTest,
- ::testing::Values(1.f, 0.873f, 1.f / 4.f, 4.f));
-
-TEST(PicturePileImplTest, PixelRefIteratorBorders) {
- // 3 tile width / 1 tile height pile
- gfx::Size tile_size(128, 128);
- gfx::Size layer_bounds(320, 128);
-
- // Fake picture pile uses a tile grid the size of the tile. So,
- // any iteration that intersects with a tile will return all pixel refs
- // inside of it.
- scoped_ptr<FakePicturePile> recording_source =
- FakePicturePile::CreateFilledPile(tile_size, layer_bounds);
- recording_source->SetMinContentsScale(0.5f);
-
- // Bitmaps 0-2 are exactly on tiles 0-2, so that they overlap the borders
- // of adjacent tiles.
- gfx::Rect bitmap_rects[] = {
- recording_source->tiling().TileBounds(0, 0),
- recording_source->tiling().TileBounds(1, 0),
- recording_source->tiling().TileBounds(2, 0),
- };
- SkBitmap discardable_bitmap[arraysize(bitmap_rects)];
-
- for (size_t i = 0; i < arraysize(bitmap_rects); ++i) {
- CreateBitmap(bitmap_rects[i].size(), "discardable", &discardable_bitmap[i]);
- recording_source->add_draw_bitmap(discardable_bitmap[i],
- bitmap_rects[i].origin());
- }
-
- recording_source->SetGatherPixelRefs(true);
- recording_source->Rerecord();
-
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFromPile(recording_source.get(), nullptr);
-
- // Sanity check that bitmaps 0-2 intersect the borders of their adjacent
- // tiles, but not the actual tiles.
- EXPECT_TRUE(
- bitmap_rects[0].Intersects(pile->tiling().TileBoundsWithBorder(1, 0)));
- EXPECT_FALSE(bitmap_rects[0].Intersects(pile->tiling().TileBounds(1, 0)));
- EXPECT_TRUE(
- bitmap_rects[1].Intersects(pile->tiling().TileBoundsWithBorder(0, 0)));
- EXPECT_FALSE(bitmap_rects[1].Intersects(pile->tiling().TileBounds(0, 0)));
- EXPECT_TRUE(
- bitmap_rects[1].Intersects(pile->tiling().TileBoundsWithBorder(2, 0)));
- EXPECT_FALSE(bitmap_rects[1].Intersects(pile->tiling().TileBounds(2, 0)));
- EXPECT_TRUE(
- bitmap_rects[2].Intersects(pile->tiling().TileBoundsWithBorder(1, 0)));
- EXPECT_FALSE(bitmap_rects[2].Intersects(pile->tiling().TileBounds(1, 0)));
-
- // Tile-sized iterators.
- {
- // Because tile 0's borders extend onto tile 1, it will include both
- // bitmap 0 and 1. However, it should *not* include bitmap 2.
- PicturePileImpl::PixelRefIterator iterator(
- pile->tiling().TileBounds(0, 0), 1.f, pile.get());
- EXPECT_TRUE(iterator);
- EXPECT_TRUE(*iterator == discardable_bitmap[0].pixelRef());
- EXPECT_TRUE(++iterator);
- EXPECT_TRUE(*iterator == discardable_bitmap[1].pixelRef());
- EXPECT_FALSE(++iterator);
- }
- {
- // Tile 1 + borders hits all bitmaps.
- PicturePileImpl::PixelRefIterator iterator(
- pile->tiling().TileBounds(1, 0), 1.f, pile.get());
- EXPECT_TRUE(iterator);
- EXPECT_TRUE(*iterator == discardable_bitmap[0].pixelRef());
- EXPECT_TRUE(++iterator);
- EXPECT_TRUE(*iterator == discardable_bitmap[1].pixelRef());
- EXPECT_TRUE(++iterator);
- EXPECT_TRUE(*iterator == discardable_bitmap[2].pixelRef());
- EXPECT_FALSE(++iterator);
- }
- {
- // Tile 2 should not include bitmap 0, which is only on tile 0 and the
- // borders of tile 1.
- PicturePileImpl::PixelRefIterator iterator(
- pile->tiling().TileBounds(2, 0), 1.f, pile.get());
- EXPECT_TRUE(iterator);
- EXPECT_TRUE(*iterator == discardable_bitmap[1].pixelRef());
- EXPECT_TRUE(++iterator);
- EXPECT_TRUE(*iterator == discardable_bitmap[2].pixelRef());
- EXPECT_FALSE(++iterator);
- }
-}
-
-} // namespace
-} // namespace cc
diff --git a/chromium/cc/playback/picture_pile_unittest.cc b/chromium/cc/playback/picture_pile_unittest.cc
deleted file mode 100644
index f929aeffb0a..00000000000
--- a/chromium/cc/playback/picture_pile_unittest.cc
+++ /dev/null
@@ -1,1345 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <map>
-#include <utility>
-
-#include "cc/playback/picture_pile.h"
-#include "cc/test/fake_content_layer_client.h"
-#include "cc/test/fake_picture_pile.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/gfx/geometry/rect_conversions.h"
-#include "ui/gfx/geometry/size_conversions.h"
-
-namespace cc {
-namespace {
-
-class PicturePileTestBase {
- public:
- PicturePileTestBase()
- : min_scale_(0.125),
- pile_(min_scale_, gfx::Size(1000, 1000)),
- frame_number_(0) {}
-
- void InitializeData() {
- pile_.SetTileGridSize(gfx::Size(1000, 1000));
- pile_.SetMinContentsScale(min_scale_);
- client_ = FakeContentLayerClient();
- SetTilingSize(pile_.tiling().max_texture_size());
- }
-
- void SetTilingSize(const gfx::Size& tiling_size) {
- Region invalidation;
- gfx::Rect viewport_rect(tiling_size);
- UpdateAndExpandInvalidation(&invalidation, tiling_size, viewport_rect);
- }
-
- gfx::Size tiling_size() const { return pile_.GetSize(); }
- gfx::Rect tiling_rect() const { return gfx::Rect(pile_.GetSize()); }
-
- bool UpdateAndExpandInvalidation(Region* invalidation,
- const gfx::Size& layer_size,
- const gfx::Rect& visible_layer_rect) {
- frame_number_++;
- return pile_.UpdateAndExpandInvalidation(&client_, invalidation, layer_size,
- visible_layer_rect, frame_number_,
- RecordingSource::RECORD_NORMALLY);
- }
-
- bool UpdateWholePile() {
- Region invalidation = tiling_rect();
- bool result = UpdateAndExpandInvalidation(&invalidation, tiling_size(),
- tiling_rect());
- EXPECT_EQ(tiling_rect().ToString(), invalidation.ToString());
- return result;
- }
-
- FakeContentLayerClient client_;
- float min_scale_;
- FakePicturePile pile_;
- int frame_number_;
-};
-
-class PicturePileTest : public PicturePileTestBase, public testing::Test {
- public:
- void SetUp() override { InitializeData(); }
-};
-
-TEST_F(PicturePileTest, InvalidationOnTileBorderOutsideInterestRect) {
- // Don't expand the interest rect past what we invalidate.
- pile_.SetPixelRecordDistance(0);
-
- gfx::Size tile_size(100, 100);
- pile_.tiling().SetMaxTextureSize(tile_size);
-
- gfx::Size pile_size(400, 400);
- SetTilingSize(pile_size);
-
- // We have multiple tiles.
- EXPECT_GT(pile_.tiling().num_tiles_x(), 2);
- EXPECT_GT(pile_.tiling().num_tiles_y(), 2);
-
- // Record everything.
- Region invalidation(tiling_rect());
- UpdateAndExpandInvalidation(&invalidation, tiling_size(), tiling_rect());
-
- // +----------+-----------------+-----------+
- // | | VVVV 1,0| |
- // | | VVVV | |
- // | | VVVV | |
- // | ...|.................|... |
- // | ...|.................|... |
- // +----------+-----------------+-----------+
- // | ...| |... |
- // | ...| |... |
- // | ...| |... |
- // | ...| |... |
- // | ...| 1,1|... |
- // +----------+-----------------+-----------+
- // | ...|.................|... |
- // | ...|.................|... |
- // +----------+-----------------+-----------+
- //
- // .. = border pixels for tile 1,1
- // VV = interest rect (what we will record)
- //
- // The first invalidation is inside VV, so it does not touch border pixels of
- // tile 1,1.
- //
- // The second invalidation goes below VV into the .. border pixels of 1,1.
-
- // This is the VV interest rect which will be entirely inside 1,0 and not
- // touch the border of 1,1.
- gfx::Rect interest_rect(
- pile_.tiling().TilePositionX(1) + pile_.tiling().border_texels(),
- 0,
- 10,
- pile_.tiling().TileSizeY(0) - pile_.tiling().border_texels());
-
- // Invalidate tile 1,0 only. This is a rect that avoids the borders of any
- // other tiles.
- gfx::Rect invalidate_tile = interest_rect;
- // This should cause the tile 1,0 to be invalidated and re-recorded. The
- // invalidation did not need to be expanded.
- invalidation = invalidate_tile;
- UpdateAndExpandInvalidation(&invalidation, tiling_size(), interest_rect);
- EXPECT_EQ(invalidate_tile, invalidation);
-
- // Invalidate tile 1,0 and 1,1 by invalidating something that only touches the
- // border of 1,1 (and is inside the tile bounds of 1,0). This is a 10px wide
- // strip from the top of the tiling onto the border pixels of tile 1,1 that
- // avoids border pixels of any other tiles.
- gfx::Rect invalidate_border = interest_rect;
- invalidate_border.Inset(0, 0, 0, -1);
- // This should cause the tile 1,0 and 1,1 to be invalidated. The 1,1 tile will
- // not be re-recorded since it does not touch the interest rect, so the
- // invalidation should be expanded to cover all of 1,1.
- invalidation = invalidate_border;
- UpdateAndExpandInvalidation(&invalidation, tiling_size(), interest_rect);
- Region expected_invalidation = invalidate_border;
- expected_invalidation.Union(pile_.tiling().TileBounds(1, 1));
- EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
-}
-
-TEST_F(PicturePileTest, SmallInvalidateInflated) {
- // Invalidate something inside a tile.
- Region invalidate_rect(gfx::Rect(50, 50, 1, 1));
- UpdateAndExpandInvalidation(&invalidate_rect, tiling_size(), tiling_rect());
- EXPECT_EQ(gfx::Rect(50, 50, 1, 1).ToString(), invalidate_rect.ToString());
-
- EXPECT_EQ(1, pile_.tiling().num_tiles_x());
- EXPECT_EQ(1, pile_.tiling().num_tiles_y());
-
- PicturePile::PictureMapKey key = FakePicturePile::PictureMapKey(0, 0);
- PicturePile::PictureMap::iterator it = pile_.picture_map().find(key);
- EXPECT_TRUE(it != pile_.picture_map().end());
- const Picture* picture = it->second.get();
- EXPECT_TRUE(picture);
-
- gfx::Rect picture_rect =
- gfx::ScaleToEnclosedRect(picture->LayerRect(), min_scale_);
-
- // The the picture should be large enough that scaling it never makes a rect
- // smaller than 1 px wide or tall.
- EXPECT_FALSE(picture_rect.IsEmpty()) << "Picture rect "
- << picture_rect.ToString();
-}
-
-TEST_F(PicturePileTest, LargeInvalidateInflated) {
- // Invalidate something inside a tile.
- Region invalidate_rect(gfx::Rect(50, 50, 100, 100));
- UpdateAndExpandInvalidation(&invalidate_rect, tiling_size(), tiling_rect());
- EXPECT_EQ(gfx::Rect(50, 50, 100, 100).ToString(), invalidate_rect.ToString());
-
- EXPECT_EQ(1, pile_.tiling().num_tiles_x());
- EXPECT_EQ(1, pile_.tiling().num_tiles_y());
-
- PicturePile::PictureMapKey key = FakePicturePile::PictureMapKey(0, 0);
- PicturePile::PictureMap::iterator it = pile_.picture_map().find(key);
- EXPECT_TRUE(it != pile_.picture_map().end());
- const Picture* picture = it->second.get();
- EXPECT_TRUE(picture);
-
- int expected_inflation = pile_.buffer_pixels();
-
- gfx::Rect base_picture_rect(tiling_size());
- base_picture_rect.Inset(-expected_inflation, -expected_inflation);
- EXPECT_EQ(base_picture_rect.ToString(), picture->LayerRect().ToString());
-}
-
-TEST_F(PicturePileTest, ClearingInvalidatesRecordedRect) {
- gfx::Rect rect(0, 0, 5, 5);
- EXPECT_TRUE(pile_.CanRasterLayerRect(rect));
- EXPECT_TRUE(pile_.CanRasterSlowTileCheck(rect));
-
- pile_.Clear();
-
- // Make sure both the cache-aware check (using recorded region) and the normal
- // check are both false after clearing.
- EXPECT_FALSE(pile_.CanRasterLayerRect(rect));
- EXPECT_FALSE(pile_.CanRasterSlowTileCheck(rect));
-}
-
-TEST_F(PicturePileTest, NoInvalidationValidViewport) {
- // This test validates that the recorded_viewport cache of full tiles
- // is still valid for some use cases. If it's not, it's a performance
- // issue because CanRaster checks will go down the slow path.
- EXPECT_TRUE(!pile_.recorded_viewport().IsEmpty());
-
- // No invalidation, same viewport.
- Region invalidation;
- UpdateAndExpandInvalidation(&invalidation, tiling_size(), tiling_rect());
- EXPECT_TRUE(!pile_.recorded_viewport().IsEmpty());
- EXPECT_EQ(Region().ToString(), invalidation.ToString());
-
- // Partial invalidation, same viewport.
- invalidation = gfx::Rect(0, 0, 1, 1);
- UpdateAndExpandInvalidation(&invalidation, tiling_size(), tiling_rect());
- EXPECT_TRUE(!pile_.recorded_viewport().IsEmpty());
- EXPECT_EQ(gfx::Rect(0, 0, 1, 1).ToString(), invalidation.ToString());
-
- // No invalidation, changing viewport.
- invalidation = Region();
- UpdateAndExpandInvalidation(&invalidation, tiling_size(),
- gfx::Rect(5, 5, 5, 5));
- EXPECT_TRUE(!pile_.recorded_viewport().IsEmpty());
- EXPECT_EQ(Region().ToString(), invalidation.ToString());
-}
-
-TEST_F(PicturePileTest, BigFullLayerInvalidation) {
- gfx::Size huge_layer_size(100000000, 100000000);
- gfx::Rect viewport(300000, 400000, 5000, 6000);
-
- // Resize the pile.
- Region invalidation;
- UpdateAndExpandInvalidation(&invalidation, huge_layer_size, viewport);
-
- // Invalidating a huge layer should be fast.
- base::TimeTicks start = base::TimeTicks::Now();
- invalidation = gfx::Rect(huge_layer_size);
- UpdateAndExpandInvalidation(&invalidation, huge_layer_size, viewport);
- base::TimeTicks end = base::TimeTicks::Now();
- base::TimeDelta length = end - start;
- // This is verrrry generous to avoid flake.
- EXPECT_LT(length.InSeconds(), 5);
-}
-
-TEST_F(PicturePileTest, BigFullLayerInvalidationWithResizeGrow) {
- gfx::Size huge_layer_size(100000000, 100000000);
- gfx::Rect viewport(300000, 400000, 5000, 6000);
-
- // Resize the pile.
- Region invalidation;
- UpdateAndExpandInvalidation(&invalidation, huge_layer_size, viewport);
-
- // Resize the pile even larger, while invalidating everything in the old size.
- // Invalidating the whole thing should be fast.
- base::TimeTicks start = base::TimeTicks::Now();
- gfx::Size bigger_layer_size(huge_layer_size.width() * 2,
- huge_layer_size.height() * 2);
- invalidation = gfx::Rect(huge_layer_size);
- UpdateAndExpandInvalidation(&invalidation, bigger_layer_size, viewport);
- base::TimeTicks end = base::TimeTicks::Now();
- base::TimeDelta length = end - start;
- // This is verrrry generous to avoid flake.
- EXPECT_LT(length.InSeconds(), 5);
-}
-
-TEST_F(PicturePileTest, BigFullLayerInvalidationWithResizeShrink) {
- gfx::Size huge_layer_size(100000000, 100000000);
- gfx::Rect viewport(300000, 400000, 5000, 6000);
-
- // Resize the pile.
- Region invalidation;
- UpdateAndExpandInvalidation(&invalidation, huge_layer_size, viewport);
-
- // Resize the pile smaller, while invalidating everything in the new size.
- // Invalidating the whole thing should be fast.
- base::TimeTicks start = base::TimeTicks::Now();
- gfx::Size smaller_layer_size(huge_layer_size.width() - 1000,
- huge_layer_size.height() - 1000);
- invalidation = gfx::Rect(smaller_layer_size);
- UpdateAndExpandInvalidation(&invalidation, smaller_layer_size, viewport);
- base::TimeTicks end = base::TimeTicks::Now();
- base::TimeDelta length = end - start;
- // This is verrrry generous to avoid flake.
- EXPECT_LT(length.InSeconds(), 5);
-}
-
-TEST_F(PicturePileTest, InvalidationOutsideRecordingRect) {
- gfx::Size huge_layer_size(10000000, 20000000);
- gfx::Rect viewport(300000, 400000, 5000, 6000);
-
- // Resize the pile and set up the interest rect.
- Region invalidation;
- UpdateAndExpandInvalidation(&invalidation, huge_layer_size, viewport);
-
- // Invalidation inside the recording rect does not need to be expanded.
- invalidation = viewport;
- UpdateAndExpandInvalidation(&invalidation, huge_layer_size, viewport);
- EXPECT_EQ(viewport.ToString(), invalidation.ToString());
-
- // Invalidation outside the recording rect should expand to the tiles it
- // covers.
- gfx::Rect recorded_over_tiles =
- pile_.tiling().ExpandRectToTileBounds(pile_.recorded_viewport());
- gfx::Rect invalidation_outside(
- recorded_over_tiles.right(), recorded_over_tiles.y(), 30, 30);
- invalidation = invalidation_outside;
- UpdateAndExpandInvalidation(&invalidation, huge_layer_size, viewport);
- gfx::Rect expanded_recorded_viewport =
- pile_.tiling().ExpandRectToTileBounds(pile_.recorded_viewport());
- Region expected_invalidation =
- pile_.tiling().ExpandRectToTileBounds(invalidation_outside);
- EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
-}
-
-enum Corner {
- TOP_LEFT,
- TOP_RIGHT,
- BOTTOM_LEFT,
- BOTTOM_RIGHT,
-};
-
-class PicturePileResizeCornerTest : public PicturePileTestBase,
- public testing::TestWithParam<Corner> {
- protected:
- void SetUp() override { InitializeData(); }
-
- static gfx::Rect CornerSinglePixelRect(Corner corner, const gfx::Size& s) {
- switch (corner) {
- case TOP_LEFT:
- return gfx::Rect(0, 0, 1, 1);
- case TOP_RIGHT:
- return gfx::Rect(s.width() - 1, 0, 1, 1);
- case BOTTOM_LEFT:
- return gfx::Rect(0, s.height() - 1, 1, 1);
- case BOTTOM_RIGHT:
- return gfx::Rect(s.width() - 1, s.height() - 1, 1, 1);
- }
- NOTREACHED();
- return gfx::Rect();
- }
-};
-
-TEST_P(PicturePileResizeCornerTest, ResizePileOutsideInterestRect) {
- Corner corner = GetParam();
-
- // This size chosen to be larger than the interest rect size, which is
- // at least kPixelDistanceToRecord * 2 in each dimension.
- int tile_size = 100000;
- // The small number subtracted keeps the last tile in each axis larger than
- // the interest rect also.
- int offset = -100;
- gfx::Size base_tiling_size(6 * tile_size + offset, 6 * tile_size + offset);
- gfx::Size grow_down_tiling_size(6 * tile_size + offset,
- 8 * tile_size + offset);
- gfx::Size grow_right_tiling_size(8 * tile_size + offset,
- 6 * tile_size + offset);
- gfx::Size grow_both_tiling_size(8 * tile_size + offset,
- 8 * tile_size + offset);
-
- Region invalidation;
- Region expected_invalidation;
-
- pile_.tiling().SetMaxTextureSize(gfx::Size(tile_size, tile_size));
- SetTilingSize(base_tiling_size);
-
- // We should have a recording for every tile.
- EXPECT_EQ(6, pile_.tiling().num_tiles_x());
- EXPECT_EQ(6, pile_.tiling().num_tiles_y());
- for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
- for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
- FakePicturePile::PictureMapKey key(i, j);
- FakePicturePile::PictureMap& map = pile_.picture_map();
- FakePicturePile::PictureMap::iterator it = map.find(key);
- EXPECT_TRUE(it != map.end() && it->second.get());
- }
- }
-
- UpdateAndExpandInvalidation(
- &invalidation,
- grow_down_tiling_size,
- CornerSinglePixelRect(corner, grow_down_tiling_size));
-
- // We should have lost all of the recordings in the bottom row as none of them
- // are in the current interest rect (which is either the above or below it).
- EXPECT_EQ(6, pile_.tiling().num_tiles_x());
- EXPECT_EQ(8, pile_.tiling().num_tiles_y());
- for (int i = 0; i < 6; ++i) {
- for (int j = 0; j < 6; ++j) {
- FakePicturePile::PictureMapKey key(i, j);
- FakePicturePile::PictureMap& map = pile_.picture_map();
- FakePicturePile::PictureMap::iterator it = map.find(key);
- EXPECT_EQ(j < 5, it != map.end() && it->second.get());
- }
- }
-
- // We invalidated all new pixels in the recording.
- expected_invalidation = SubtractRegions(gfx::Rect(grow_down_tiling_size),
- gfx::Rect(base_tiling_size));
- // But the new pixels don't cover the whole bottom row.
- gfx::Rect bottom_row = gfx::UnionRects(pile_.tiling().TileBounds(0, 5),
- pile_.tiling().TileBounds(5, 5));
- EXPECT_FALSE(expected_invalidation.Contains(bottom_row));
- // We invalidated the entire old bottom row.
- expected_invalidation.Union(bottom_row);
- EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
- invalidation.Clear();
-
- UpdateWholePile();
- UpdateAndExpandInvalidation(&invalidation,
- base_tiling_size,
- CornerSinglePixelRect(corner, base_tiling_size));
-
- // When shrinking, we should have lost all the recordings in the bottom row
- // not touching the interest rect.
- EXPECT_EQ(6, pile_.tiling().num_tiles_x());
- EXPECT_EQ(6, pile_.tiling().num_tiles_y());
- for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
- for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
- FakePicturePile::PictureMapKey key(i, j);
- FakePicturePile::PictureMap& map = pile_.picture_map();
- FakePicturePile::PictureMap::iterator it = map.find(key);
- bool expect_tile;
- switch (corner) {
- case TOP_LEFT:
- case TOP_RIGHT:
- expect_tile = j < 5;
- break;
- case BOTTOM_LEFT:
- // The interest rect in the bottom left tile means we'll record it.
- expect_tile = j < 5 || (j == 5 && i == 0);
- break;
- case BOTTOM_RIGHT:
- // The interest rect in the bottom right tile means we'll record it.
- expect_tile = j < 5 || (j == 5 && i == 5);
- break;
- }
- EXPECT_EQ(expect_tile, it != map.end() && it->second.get());
- }
- }
-
- // When shrinking, the previously exposed region is invalidated.
- expected_invalidation = SubtractRegions(gfx::Rect(grow_down_tiling_size),
- gfx::Rect(base_tiling_size));
- // The whole bottom row of tiles (except any with the interest rect) are
- // dropped.
- gfx::Rect bottom_row_minus_existing_corner = gfx::UnionRects(
- pile_.tiling().TileBounds(0, 5), pile_.tiling().TileBounds(5, 5));
- switch (corner) {
- case TOP_LEFT:
- case TOP_RIGHT:
- // No tiles are kept in the changed region because it doesn't
- // intersect with the interest rect.
- break;
- case BOTTOM_LEFT:
- bottom_row_minus_existing_corner.Subtract(
- pile_.tiling().TileBounds(0, 5));
- break;
- case BOTTOM_RIGHT:
- bottom_row_minus_existing_corner.Subtract(
- pile_.tiling().TileBounds(5, 5));
- break;
- }
-
- expected_invalidation.Union(bottom_row_minus_existing_corner);
- EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
- invalidation.Clear();
-
- UpdateWholePile();
- UpdateAndExpandInvalidation(
- &invalidation,
- grow_right_tiling_size,
- CornerSinglePixelRect(corner, grow_right_tiling_size));
-
- // We should have lost all of the recordings in the right column as none of
- // them are in the current interest rect (which is either entirely left or
- // right of it).
- EXPECT_EQ(8, pile_.tiling().num_tiles_x());
- EXPECT_EQ(6, pile_.tiling().num_tiles_y());
- for (int i = 0; i < 6; ++i) {
- for (int j = 0; j < 6; ++j) {
- FakePicturePile::PictureMapKey key(i, j);
- FakePicturePile::PictureMap& map = pile_.picture_map();
- FakePicturePile::PictureMap::iterator it = map.find(key);
- EXPECT_EQ(i < 5, it != map.end() && it->second.get());
- }
- }
-
- // We invalidated all new pixels in the recording.
- expected_invalidation = SubtractRegions(gfx::Rect(grow_right_tiling_size),
- gfx::Rect(base_tiling_size));
- // But the new pixels don't cover the whole right_column.
- gfx::Rect right_column = gfx::UnionRects(pile_.tiling().TileBounds(5, 0),
- pile_.tiling().TileBounds(5, 5));
- EXPECT_FALSE(expected_invalidation.Contains(right_column));
- // We invalidated the entire old right column.
- expected_invalidation.Union(right_column);
- EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
- invalidation.Clear();
-
- UpdateWholePile();
- UpdateAndExpandInvalidation(&invalidation,
- base_tiling_size,
- CornerSinglePixelRect(corner, base_tiling_size));
-
- // When shrinking, we should have lost all the recordings in the right column
- // not touching the interest rect.
- EXPECT_EQ(6, pile_.tiling().num_tiles_x());
- EXPECT_EQ(6, pile_.tiling().num_tiles_y());
- for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
- for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
- FakePicturePile::PictureMapKey key(i, j);
- FakePicturePile::PictureMap& map = pile_.picture_map();
- FakePicturePile::PictureMap::iterator it = map.find(key);
- bool expect_tile;
- switch (corner) {
- case TOP_LEFT:
- case BOTTOM_LEFT:
- // No tiles are kept in the changed region because it doesn't
- // intersect with the interest rect.
- expect_tile = i < 5;
- break;
- case TOP_RIGHT:
- // The interest rect in the top right tile means we'll record it.
- expect_tile = i < 5 || (j == 0 && i == 5);
- break;
- case BOTTOM_RIGHT:
- // The interest rect in the bottom right tile means we'll record it.
- expect_tile = i < 5 || (j == 5 && i == 5);
- break;
- }
- EXPECT_EQ(expect_tile, it != map.end() && it->second.get());
- }
- }
-
- // When shrinking, the previously exposed region is invalidated.
- expected_invalidation = SubtractRegions(gfx::Rect(grow_right_tiling_size),
- gfx::Rect(base_tiling_size));
- // The whole right column of tiles (except for ones with the interest rect)
- // are dropped.
- gfx::Rect right_column_minus_existing_corner = gfx::UnionRects(
- pile_.tiling().TileBounds(5, 0), pile_.tiling().TileBounds(5, 5));
- switch (corner) {
- case TOP_LEFT:
- case BOTTOM_LEFT:
- break;
- case TOP_RIGHT:
- right_column_minus_existing_corner.Subtract(
- pile_.tiling().TileBounds(5, 0));
- break;
- case BOTTOM_RIGHT:
- right_column_minus_existing_corner.Subtract(
- pile_.tiling().TileBounds(5, 5));
- break;
- }
- expected_invalidation.Union(right_column_minus_existing_corner);
- EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
- invalidation.Clear();
-
- UpdateWholePile();
- UpdateAndExpandInvalidation(
- &invalidation,
- grow_both_tiling_size,
- CornerSinglePixelRect(corner, grow_both_tiling_size));
-
- // We should have lost the recordings in the right column and bottom row.
- EXPECT_EQ(8, pile_.tiling().num_tiles_x());
- EXPECT_EQ(8, pile_.tiling().num_tiles_y());
- for (int i = 0; i < 6; ++i) {
- for (int j = 0; j < 6; ++j) {
- FakePicturePile::PictureMapKey key(i, j);
- FakePicturePile::PictureMap& map = pile_.picture_map();
- FakePicturePile::PictureMap::iterator it = map.find(key);
- EXPECT_EQ(i < 5 && j < 5, it != map.end() && it->second.get());
- }
- }
-
- // We invalidated all new pixels in the recording.
- expected_invalidation = SubtractRegions(gfx::Rect(grow_both_tiling_size),
- gfx::Rect(base_tiling_size));
- // But the new pixels don't cover the whole right column or bottom row.
- Region right_column_and_bottom_row =
- UnionRegions(gfx::UnionRects(pile_.tiling().TileBounds(5, 0),
- pile_.tiling().TileBounds(5, 5)),
- gfx::UnionRects(pile_.tiling().TileBounds(0, 5),
- pile_.tiling().TileBounds(5, 5)));
- EXPECT_FALSE(expected_invalidation.Contains(right_column_and_bottom_row));
- // We invalidated the entire old right column and the old bottom row.
- expected_invalidation.Union(right_column_and_bottom_row);
- EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
- invalidation.Clear();
-
- UpdateWholePile();
- UpdateAndExpandInvalidation(&invalidation, base_tiling_size,
- CornerSinglePixelRect(corner, base_tiling_size));
-
- // We should have lost the recordings in the right column and bottom row,
- // except where it intersects the interest rect.
- EXPECT_EQ(6, pile_.tiling().num_tiles_x());
- EXPECT_EQ(6, pile_.tiling().num_tiles_y());
- for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
- for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
- FakePicturePile::PictureMapKey key(i, j);
- FakePicturePile::PictureMap& map = pile_.picture_map();
- FakePicturePile::PictureMap::iterator it = map.find(key);
- bool expect_tile;
- switch (corner) {
- case TOP_LEFT:
- expect_tile = i < 5 && j < 5;
- break;
- case TOP_RIGHT:
- // The interest rect in the top right tile means we'll record it.
- expect_tile = (i < 5 && j < 5) || (j == 0 && i == 5);
- break;
- case BOTTOM_LEFT:
- // The interest rect in the bottom left tile means we'll record it.
- expect_tile = (i < 5 && j < 5) || (j == 5 && i == 0);
- break;
- case BOTTOM_RIGHT:
- // The interest rect in the bottom right tile means we'll record it.
- expect_tile = (i < 5 && j < 5) || (j == 5 && i == 5);
- break;
- }
- EXPECT_EQ(expect_tile, it != map.end() && it->second.get()) << i << ","
- << j;
- }
- }
-
- // We invalidated all previous pixels in the recording.
- expected_invalidation = SubtractRegions(gfx::Rect(grow_both_tiling_size),
- gfx::Rect(base_tiling_size));
- // The whole right column and bottom row of tiles (except for ones with the
- // interest rect) are dropped.
- Region right_column_and_bottom_row_minus_existing_corner =
- right_column_and_bottom_row;
- switch (corner) {
- case TOP_LEFT:
- break;
- case BOTTOM_LEFT:
- right_column_and_bottom_row_minus_existing_corner.Subtract(
- pile_.tiling().TileBounds(0, 5));
- break;
- case TOP_RIGHT:
- right_column_and_bottom_row_minus_existing_corner.Subtract(
- pile_.tiling().TileBounds(5, 0));
- break;
- case BOTTOM_RIGHT:
- right_column_and_bottom_row_minus_existing_corner.Subtract(
- pile_.tiling().TileBounds(5, 5));
- break;
- }
- expected_invalidation.Union(
- right_column_and_bottom_row_minus_existing_corner);
- EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
- invalidation.Clear();
-}
-
-TEST_P(PicturePileResizeCornerTest, SmallResizePileOutsideInterestRect) {
- Corner corner = GetParam();
-
- // This size chosen to be larger than the interest rect size, which is
- // at least kPixelDistanceToRecord * 2 in each dimension.
- int tile_size = 100000;
- // The small number subtracted keeps the last tile in each axis larger than
- // the interest rect also.
- int offset = -100;
- gfx::Size base_tiling_size(6 * tile_size + offset, 6 * tile_size + offset);
- gfx::Size grow_down_tiling_size(6 * tile_size + offset,
- 6 * tile_size + offset + 5);
- gfx::Size grow_right_tiling_size(6 * tile_size + offset + 5,
- 6 * tile_size + offset);
- gfx::Size grow_both_tiling_size(6 * tile_size + offset + 5,
- 6 * tile_size + offset + 5);
-
- Region invalidation;
- Region expected_invalidation;
-
- pile_.tiling().SetMaxTextureSize(gfx::Size(tile_size, tile_size));
- SetTilingSize(base_tiling_size);
-
- // We should have a recording for every tile.
- EXPECT_EQ(6, pile_.tiling().num_tiles_x());
- EXPECT_EQ(6, pile_.tiling().num_tiles_y());
- for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
- for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
- FakePicturePile::PictureMapKey key(i, j);
- FakePicturePile::PictureMap& map = pile_.picture_map();
- FakePicturePile::PictureMap::iterator it = map.find(key);
- EXPECT_TRUE(it != map.end() && it->second.get());
- }
- }
-
- // In this test (unlike the large resize test), as all growing and shrinking
- // happens within tiles, the resulting invalidation is symmetrical, so use
- // this enum to repeat the test both ways.
- enum ChangeDirection { GROW, SHRINK, LAST_DIRECTION = SHRINK };
-
- // Grow downward.
- for (int dir = 0; dir <= LAST_DIRECTION; ++dir) {
- gfx::Size new_tiling_size =
- dir == GROW ? grow_down_tiling_size : base_tiling_size;
- UpdateWholePile();
- UpdateAndExpandInvalidation(&invalidation, new_tiling_size,
- CornerSinglePixelRect(corner, new_tiling_size));
-
- // We should have lost the recordings in the bottom row that do not
- // intersect the interest rect.
- EXPECT_EQ(6, pile_.tiling().num_tiles_x());
- EXPECT_EQ(6, pile_.tiling().num_tiles_y());
- for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
- for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
- FakePicturePile::PictureMapKey key(i, j);
- FakePicturePile::PictureMap& map = pile_.picture_map();
- FakePicturePile::PictureMap::iterator it = map.find(key);
- bool expect_tile;
- switch (corner) {
- case TOP_LEFT:
- case TOP_RIGHT:
- expect_tile = j < 5;
- break;
- case BOTTOM_LEFT:
- // The interest rect in the bottom left tile means we'll record it.
- expect_tile = j < 5 || (j == 5 && i == 0);
- break;
- case BOTTOM_RIGHT:
- // The interest rect in the bottom right tile means we'll record it.
- expect_tile = j < 5 || (j == 5 && i == 5);
- break;
- }
- EXPECT_EQ(expect_tile, it != map.end() && it->second.get());
- }
- }
-
- // We invalidated the bottom row outside the new interest rect. The tile
- // that insects the interest rect in invalidated only on its newly
- // exposed or previously exposed pixels.
- if (dir == GROW) {
- // Only calculate the expected invalidation while growing, as the tile
- // bounds post-growing is the newly exposed / previously exposed sizes.
- // Post-shrinking, the tile bounds are smaller, so can't be used.
- switch (corner) {
- case TOP_LEFT:
- case TOP_RIGHT:
- expected_invalidation = gfx::UnionRects(
- pile_.tiling().TileBounds(0, 5), pile_.tiling().TileBounds(5, 5));
- break;
- case BOTTOM_LEFT:
- expected_invalidation = gfx::UnionRects(
- pile_.tiling().TileBounds(1, 5), pile_.tiling().TileBounds(5, 5));
- expected_invalidation.Union(SubtractRects(
- pile_.tiling().TileBounds(0, 5), gfx::Rect(base_tiling_size)));
- break;
- case BOTTOM_RIGHT:
- expected_invalidation = gfx::UnionRects(
- pile_.tiling().TileBounds(0, 5), pile_.tiling().TileBounds(4, 5));
- expected_invalidation.Union(SubtractRects(
- pile_.tiling().TileBounds(5, 5), gfx::Rect(base_tiling_size)));
- break;
- }
- }
- EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
- invalidation.Clear();
- }
-
- // Grow right.
- for (int dir = 0; dir <= LAST_DIRECTION; ++dir) {
- gfx::Size new_tiling_size =
- dir == GROW ? grow_right_tiling_size : base_tiling_size;
- UpdateWholePile();
- UpdateAndExpandInvalidation(&invalidation, new_tiling_size,
- CornerSinglePixelRect(corner, new_tiling_size));
-
- // We should have lost the recordings in the right column.
- EXPECT_EQ(6, pile_.tiling().num_tiles_x());
- EXPECT_EQ(6, pile_.tiling().num_tiles_y());
- for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
- for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
- FakePicturePile::PictureMapKey key(i, j);
- FakePicturePile::PictureMap& map = pile_.picture_map();
- FakePicturePile::PictureMap::iterator it = map.find(key);
- bool expect_tile;
- switch (corner) {
- case TOP_LEFT:
- case BOTTOM_LEFT:
- expect_tile = i < 5;
- break;
- case TOP_RIGHT:
- // The interest rect in the top right tile means we'll record it.
- expect_tile = i < 5 || (j == 0 && i == 5);
- break;
- case BOTTOM_RIGHT:
- // The interest rect in the bottom right tile means we'll record it.
- expect_tile = i < 5 || (j == 5 && i == 5);
- break;
- }
- EXPECT_EQ(expect_tile, it != map.end() && it->second.get());
- }
- }
-
- // We invalidated the right column outside the new interest rect. The tile
- // that insects the interest rect in invalidated only on its new or
- // previously exposed pixels.
- if (dir == GROW) {
- // Calculate the expected invalidation the first time through the loop.
- switch (corner) {
- case TOP_LEFT:
- case BOTTOM_LEFT:
- expected_invalidation = gfx::UnionRects(
- pile_.tiling().TileBounds(5, 0), pile_.tiling().TileBounds(5, 5));
- break;
- case TOP_RIGHT:
- expected_invalidation = gfx::UnionRects(
- pile_.tiling().TileBounds(5, 1), pile_.tiling().TileBounds(5, 5));
- expected_invalidation.Union(SubtractRects(
- pile_.tiling().TileBounds(5, 0), gfx::Rect(base_tiling_size)));
- break;
- case BOTTOM_RIGHT:
- expected_invalidation = gfx::UnionRects(
- pile_.tiling().TileBounds(5, 0), pile_.tiling().TileBounds(5, 4));
- expected_invalidation.Union(SubtractRects(
- pile_.tiling().TileBounds(5, 5), gfx::Rect(base_tiling_size)));
- break;
- }
- }
- EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
- invalidation.Clear();
- }
-
- // Grow both.
- for (int dir = 0; dir <= LAST_DIRECTION; ++dir) {
- gfx::Size new_tiling_size =
- dir == GROW ? grow_both_tiling_size : base_tiling_size;
- UpdateWholePile();
- UpdateAndExpandInvalidation(&invalidation, new_tiling_size,
- CornerSinglePixelRect(corner, new_tiling_size));
-
- // We should have lost the recordings in the right column and bottom row.
- // The tile that insects the interest rect in invalidated only on its new
- // or previously exposed pixels.
- EXPECT_EQ(6, pile_.tiling().num_tiles_x());
- EXPECT_EQ(6, pile_.tiling().num_tiles_y());
- for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
- for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
- FakePicturePile::PictureMapKey key(i, j);
- FakePicturePile::PictureMap& map = pile_.picture_map();
- FakePicturePile::PictureMap::iterator it = map.find(key);
- bool expect_tile;
- switch (corner) {
- case TOP_LEFT:
- expect_tile = i < 5 && j < 5;
- break;
- case TOP_RIGHT:
- // The interest rect in the top right tile means we'll record it.
- expect_tile = (i < 5 && j < 5) || (j == 0 && i == 5);
- break;
- case BOTTOM_LEFT:
- // The interest rect in the bottom left tile means we'll record it.
- expect_tile = (i < 5 && j < 5) || (j == 5 && i == 0);
- break;
- case BOTTOM_RIGHT:
- // The interest rect in the bottom right tile means we'll record it.
- expect_tile = (i < 5 && j < 5) || (j == 5 && i == 5);
- break;
- }
- EXPECT_EQ(expect_tile, it != map.end() && it->second.get()) << i << ","
- << j;
- }
- }
-
- // We invalidated the right column and the bottom row outside the new
- // interest rect. The tile that insects the interest rect in invalidated
- // only on its new or previous exposed pixels.
- if (dir == GROW) {
- // Calculate the expected invalidation the first time through the loop.
- switch (corner) {
- case TOP_LEFT:
- expected_invalidation = gfx::UnionRects(
- pile_.tiling().TileBounds(5, 0), pile_.tiling().TileBounds(5, 5));
- expected_invalidation.Union(
- gfx::UnionRects(pile_.tiling().TileBounds(0, 5),
- pile_.tiling().TileBounds(5, 5)));
- break;
- case TOP_RIGHT:
- expected_invalidation = gfx::UnionRects(
- pile_.tiling().TileBounds(5, 1), pile_.tiling().TileBounds(5, 5));
- expected_invalidation.Union(
- gfx::UnionRects(pile_.tiling().TileBounds(0, 5),
- pile_.tiling().TileBounds(5, 5)));
- expected_invalidation.Union(SubtractRects(
- pile_.tiling().TileBounds(5, 0), gfx::Rect(base_tiling_size)));
- break;
- case BOTTOM_LEFT:
- expected_invalidation = gfx::UnionRects(
- pile_.tiling().TileBounds(5, 0), pile_.tiling().TileBounds(5, 5));
- expected_invalidation.Union(
- gfx::UnionRects(pile_.tiling().TileBounds(1, 5),
- pile_.tiling().TileBounds(5, 5)));
- expected_invalidation.Union(SubtractRects(
- pile_.tiling().TileBounds(0, 5), gfx::Rect(base_tiling_size)));
- break;
- case BOTTOM_RIGHT:
- expected_invalidation = gfx::UnionRects(
- pile_.tiling().TileBounds(5, 0), pile_.tiling().TileBounds(5, 4));
- expected_invalidation.Union(
- gfx::UnionRects(pile_.tiling().TileBounds(0, 5),
- pile_.tiling().TileBounds(4, 5)));
- expected_invalidation.Union(SubtractRegions(
- pile_.tiling().TileBounds(5, 5), gfx::Rect(base_tiling_size)));
- break;
- }
- }
- EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
- invalidation.Clear();
- }
-}
-
-INSTANTIATE_TEST_CASE_P(
- PicturePileResizeCornerTests,
- PicturePileResizeCornerTest,
- ::testing::Values(TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT));
-
-TEST_F(PicturePileTest, ResizePileInsideInterestRect) {
- // This size chosen to be small enough that all the rects below fit inside the
- // the interest rect, so they are smaller than kPixelDistanceToRecord in each
- // dimension.
- int tile_size = 100;
- gfx::Size base_tiling_size(5 * tile_size, 5 * tile_size);
- gfx::Size grow_down_tiling_size(5 * tile_size, 7 * tile_size);
- gfx::Size grow_right_tiling_size(7 * tile_size, 5 * tile_size);
- gfx::Size grow_both_tiling_size(7 * tile_size, 7 * tile_size);
-
- Region invalidation;
- Region expected_invalidation;
-
- pile_.tiling().SetMaxTextureSize(gfx::Size(tile_size, tile_size));
- SetTilingSize(base_tiling_size);
-
- // We should have a recording for every tile.
- EXPECT_EQ(6, pile_.tiling().num_tiles_x());
- EXPECT_EQ(6, pile_.tiling().num_tiles_y());
- for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
- for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
- FakePicturePile::PictureMapKey key(i, j);
- FakePicturePile::PictureMap& map = pile_.picture_map();
- FakePicturePile::PictureMap::iterator it = map.find(key);
- EXPECT_TRUE(it != map.end() && it->second.get());
- }
- }
-
- UpdateAndExpandInvalidation(
- &invalidation, grow_down_tiling_size, gfx::Rect(1, 1));
-
- // We should have a recording for every tile.
- EXPECT_EQ(6, pile_.tiling().num_tiles_x());
- EXPECT_EQ(8, pile_.tiling().num_tiles_y());
- for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
- for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
- FakePicturePile::PictureMapKey key(i, j);
- FakePicturePile::PictureMap& map = pile_.picture_map();
- FakePicturePile::PictureMap::iterator it = map.find(key);
- EXPECT_TRUE(it != map.end() && it->second.get());
- }
- }
-
- // We invalidated the newly exposed pixels on the bottom row of tiles.
- expected_invalidation = SubtractRegions(gfx::Rect(grow_down_tiling_size),
- gfx::Rect(base_tiling_size));
- Region bottom_row_new_pixels =
- SubtractRegions(gfx::UnionRects(pile_.tiling().TileBounds(0, 5),
- pile_.tiling().TileBounds(5, 5)),
- gfx::Rect(base_tiling_size));
- EXPECT_TRUE(expected_invalidation.Contains(bottom_row_new_pixels));
- EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
- invalidation.Clear();
-
- UpdateWholePile();
- UpdateAndExpandInvalidation(&invalidation, base_tiling_size, gfx::Rect(1, 1));
-
- // We should have a recording for every tile.
- EXPECT_EQ(6, pile_.tiling().num_tiles_x());
- EXPECT_EQ(6, pile_.tiling().num_tiles_y());
- for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
- for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
- FakePicturePile::PictureMapKey key(i, j);
- FakePicturePile::PictureMap& map = pile_.picture_map();
- FakePicturePile::PictureMap::iterator it = map.find(key);
- EXPECT_TRUE(it != map.end() && it->second.get());
- }
- }
-
- // We invalidated the previously exposed pixels on the bottom row of tiles.
- expected_invalidation = SubtractRegions(gfx::Rect(grow_down_tiling_size),
- gfx::Rect(base_tiling_size));
- EXPECT_TRUE(expected_invalidation.Contains(bottom_row_new_pixels));
- EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
- invalidation.Clear();
-
- UpdateWholePile();
- UpdateAndExpandInvalidation(
- &invalidation, grow_right_tiling_size, gfx::Rect(1, 1));
-
- // We should have a recording for every tile.
- EXPECT_EQ(8, pile_.tiling().num_tiles_x());
- EXPECT_EQ(6, pile_.tiling().num_tiles_y());
- for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
- for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
- FakePicturePile::PictureMapKey key(i, j);
- FakePicturePile::PictureMap& map = pile_.picture_map();
- FakePicturePile::PictureMap::iterator it = map.find(key);
- EXPECT_TRUE(it != map.end() && it->second.get());
- }
- }
-
- // We invalidated the newly exposed pixels on the right column of tiles.
- expected_invalidation = SubtractRegions(gfx::Rect(grow_right_tiling_size),
- gfx::Rect(base_tiling_size));
- Region right_column_new_pixels =
- SubtractRegions(gfx::UnionRects(pile_.tiling().TileBounds(5, 0),
- pile_.tiling().TileBounds(5, 5)),
- gfx::Rect(base_tiling_size));
- EXPECT_TRUE(expected_invalidation.Contains(right_column_new_pixels));
- EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
- invalidation.Clear();
-
- UpdateWholePile();
- UpdateAndExpandInvalidation(&invalidation, base_tiling_size, gfx::Rect(1, 1));
-
- // We should have lost the recordings that are now outside the tiling only.
- EXPECT_EQ(6, pile_.tiling().num_tiles_x());
- EXPECT_EQ(6, pile_.tiling().num_tiles_y());
- for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
- for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
- FakePicturePile::PictureMapKey key(i, j);
- FakePicturePile::PictureMap& map = pile_.picture_map();
- FakePicturePile::PictureMap::iterator it = map.find(key);
- EXPECT_TRUE(it != map.end() && it->second.get());
- }
- }
-
- // We invalidated the previously exposed pixels on the right column of tiles.
- expected_invalidation = SubtractRegions(gfx::Rect(grow_right_tiling_size),
- gfx::Rect(base_tiling_size));
- EXPECT_TRUE(expected_invalidation.Contains(right_column_new_pixels));
- EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
- invalidation.Clear();
-
- UpdateWholePile();
- UpdateAndExpandInvalidation(
- &invalidation, grow_both_tiling_size, gfx::Rect(1, 1));
-
- // We should have a recording for every tile.
- EXPECT_EQ(8, pile_.tiling().num_tiles_x());
- EXPECT_EQ(8, pile_.tiling().num_tiles_y());
- for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
- for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
- FakePicturePile::PictureMapKey key(i, j);
- FakePicturePile::PictureMap& map = pile_.picture_map();
- FakePicturePile::PictureMap::iterator it = map.find(key);
- EXPECT_TRUE(it != map.end() && it->second.get());
- }
- }
-
- // We invalidated the newly exposed pixels on the bottom row and right column
- // of tiles.
- expected_invalidation = SubtractRegions(gfx::Rect(grow_both_tiling_size),
- gfx::Rect(base_tiling_size));
- Region bottom_row_and_right_column_new_pixels = SubtractRegions(
- UnionRegions(gfx::UnionRects(pile_.tiling().TileBounds(0, 5),
- pile_.tiling().TileBounds(5, 5)),
- gfx::UnionRects(pile_.tiling().TileBounds(5, 0),
- pile_.tiling().TileBounds(5, 5))),
- gfx::Rect(base_tiling_size));
- EXPECT_TRUE(
- expected_invalidation.Contains(bottom_row_and_right_column_new_pixels));
- EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
- invalidation.Clear();
-
- UpdateWholePile();
- UpdateAndExpandInvalidation(&invalidation, base_tiling_size, gfx::Rect());
-
- // We should have lost the recordings that are now outside the tiling only.
- EXPECT_EQ(6, pile_.tiling().num_tiles_x());
- EXPECT_EQ(6, pile_.tiling().num_tiles_y());
- for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
- for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
- FakePicturePile::PictureMapKey key(i, j);
- FakePicturePile::PictureMap& map = pile_.picture_map();
- FakePicturePile::PictureMap::iterator it = map.find(key);
- EXPECT_TRUE(it != map.end() && it->second.get());
- }
- }
-
- // We invalidated the previously exposed pixels on the bottom row and right
- // column of tiles.
- expected_invalidation = SubtractRegions(gfx::Rect(grow_both_tiling_size),
- gfx::Rect(base_tiling_size));
- EXPECT_TRUE(
- expected_invalidation.Contains(bottom_row_and_right_column_new_pixels));
- EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
- invalidation.Clear();
-}
-
-TEST_F(PicturePileTest, SmallResizePileInsideInterestRect) {
- // This size chosen to be small enough that all the rects below fit inside the
- // the interest rect, so they are smaller than kPixelDistanceToRecord in each
- // dimension.
- int tile_size = 100;
- gfx::Size base_tiling_size(5 * tile_size, 5 * tile_size);
- gfx::Size grow_down_tiling_size(5 * tile_size, 5 * tile_size + 5);
- gfx::Size grow_right_tiling_size(5 * tile_size + 5, 5 * tile_size);
- gfx::Size grow_both_tiling_size(5 * tile_size + 5, 5 * tile_size + 5);
-
- Region invalidation;
- Region expected_invalidation;
-
- pile_.tiling().SetMaxTextureSize(gfx::Size(tile_size, tile_size));
- SetTilingSize(base_tiling_size);
-
- // We should have a recording for every tile.
- EXPECT_EQ(6, pile_.tiling().num_tiles_x());
- EXPECT_EQ(6, pile_.tiling().num_tiles_y());
- for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
- for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
- FakePicturePile::PictureMapKey key(i, j);
- FakePicturePile::PictureMap& map = pile_.picture_map();
- FakePicturePile::PictureMap::iterator it = map.find(key);
- EXPECT_TRUE(it != map.end() && it->second.get());
- }
- }
-
- UpdateAndExpandInvalidation(
- &invalidation, grow_down_tiling_size, gfx::Rect(1, 1));
-
- // We should have a recording for every tile.
- EXPECT_EQ(6, pile_.tiling().num_tiles_x());
- EXPECT_EQ(6, pile_.tiling().num_tiles_y());
- for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
- for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
- FakePicturePile::PictureMapKey key(i, j);
- FakePicturePile::PictureMap& map = pile_.picture_map();
- FakePicturePile::PictureMap::iterator it = map.find(key);
- EXPECT_TRUE(it != map.end() && it->second.get());
- }
- }
-
- // We invalidated the newly exposed pixels.
- expected_invalidation = SubtractRegions(gfx::Rect(grow_down_tiling_size),
- gfx::Rect(base_tiling_size));
- EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
- invalidation.Clear();
-
- UpdateWholePile();
- UpdateAndExpandInvalidation(&invalidation, base_tiling_size, gfx::Rect(1, 1));
-
- // We should have a recording for every tile.
- EXPECT_EQ(6, pile_.tiling().num_tiles_x());
- EXPECT_EQ(6, pile_.tiling().num_tiles_y());
- for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
- for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
- FakePicturePile::PictureMapKey key(i, j);
- FakePicturePile::PictureMap& map = pile_.picture_map();
- FakePicturePile::PictureMap::iterator it = map.find(key);
- EXPECT_TRUE(it != map.end() && it->second.get());
- }
- }
-
- // We invalidated the previously exposed pixels.
- expected_invalidation = SubtractRegions(gfx::Rect(grow_down_tiling_size),
- gfx::Rect(base_tiling_size));
- EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
- invalidation.Clear();
-
- UpdateWholePile();
- UpdateAndExpandInvalidation(
- &invalidation, grow_right_tiling_size, gfx::Rect(1, 1));
-
- // We should have a recording for every tile.
- EXPECT_EQ(6, pile_.tiling().num_tiles_x());
- EXPECT_EQ(6, pile_.tiling().num_tiles_y());
- for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
- for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
- FakePicturePile::PictureMapKey key(i, j);
- FakePicturePile::PictureMap& map = pile_.picture_map();
- FakePicturePile::PictureMap::iterator it = map.find(key);
- EXPECT_TRUE(it != map.end() && it->second.get());
- }
- }
-
- // We invalidated the newly exposed pixels.
- expected_invalidation = SubtractRegions(gfx::Rect(grow_right_tiling_size),
- gfx::Rect(base_tiling_size));
- EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
- invalidation.Clear();
-
- UpdateWholePile();
- UpdateAndExpandInvalidation(&invalidation, base_tiling_size, gfx::Rect(1, 1));
-
- // We should have lost the recordings that are now outside the tiling only.
- EXPECT_EQ(6, pile_.tiling().num_tiles_x());
- EXPECT_EQ(6, pile_.tiling().num_tiles_y());
- for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
- for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
- FakePicturePile::PictureMapKey key(i, j);
- FakePicturePile::PictureMap& map = pile_.picture_map();
- FakePicturePile::PictureMap::iterator it = map.find(key);
- EXPECT_TRUE(it != map.end() && it->second.get());
- }
- }
-
- // We invalidated the previously exposed pixels.
- expected_invalidation = SubtractRegions(gfx::Rect(grow_right_tiling_size),
- gfx::Rect(base_tiling_size));
- EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
- invalidation.Clear();
-
- UpdateWholePile();
- UpdateAndExpandInvalidation(
- &invalidation, grow_both_tiling_size, gfx::Rect(1, 1));
-
- // We should have a recording for every tile.
- EXPECT_EQ(6, pile_.tiling().num_tiles_x());
- EXPECT_EQ(6, pile_.tiling().num_tiles_y());
- for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
- for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
- FakePicturePile::PictureMapKey key(i, j);
- FakePicturePile::PictureMap& map = pile_.picture_map();
- FakePicturePile::PictureMap::iterator it = map.find(key);
- EXPECT_TRUE(it != map.end() && it->second.get());
- }
- }
-
- // We invalidated the newly exposed pixels.
- expected_invalidation = SubtractRegions(gfx::Rect(grow_both_tiling_size),
- gfx::Rect(base_tiling_size));
- EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
- invalidation.Clear();
-
- UpdateWholePile();
- UpdateAndExpandInvalidation(&invalidation, base_tiling_size, gfx::Rect());
-
- // We should have lost the recordings that are now outside the tiling only.
- EXPECT_EQ(6, pile_.tiling().num_tiles_x());
- EXPECT_EQ(6, pile_.tiling().num_tiles_y());
- for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
- for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
- FakePicturePile::PictureMapKey key(i, j);
- FakePicturePile::PictureMap& map = pile_.picture_map();
- FakePicturePile::PictureMap::iterator it = map.find(key);
- EXPECT_TRUE(it != map.end() && it->second.get());
- }
- }
-
- // We invalidated the previously exposed pixels.
- expected_invalidation = SubtractRegions(gfx::Rect(grow_both_tiling_size),
- gfx::Rect(base_tiling_size));
- EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
- invalidation.Clear();
-}
-
-TEST_F(PicturePileTest, SolidRectangleIsSolid) {
- // If the client has no contents, the solid state will be true.
- Region invalidation1(tiling_rect());
- UpdateAndExpandInvalidation(&invalidation1, tiling_size(), tiling_rect());
- EXPECT_TRUE(pile_.is_solid_color());
- EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), pile_.solid_color());
-
- // If there is a single rect that covers the view, the solid
- // state will be true.
- SkPaint paint;
- paint.setColor(SK_ColorCYAN);
- client_.add_draw_rect(tiling_rect(), paint);
- Region invalidation2(tiling_rect());
- UpdateAndExpandInvalidation(&invalidation2, tiling_size(), tiling_rect());
- EXPECT_TRUE(pile_.is_solid_color());
- EXPECT_EQ(SK_ColorCYAN, pile_.solid_color());
-
- // If a second smaller rect is draw that doesn't cover the viewport
- // completely, the solid state will be false.
- gfx::Rect smallRect = tiling_rect();
- smallRect.Inset(10, 10, 10, 10);
- client_.add_draw_rect(smallRect, paint);
- Region invalidation3(tiling_rect());
- UpdateAndExpandInvalidation(&invalidation3, tiling_size(), tiling_rect());
- EXPECT_FALSE(pile_.is_solid_color());
-
- // If a third rect is drawn over everything, we should be solid again.
- paint.setColor(SK_ColorRED);
- client_.add_draw_rect(tiling_rect(), paint);
- Region invalidation4(tiling_rect());
- UpdateAndExpandInvalidation(&invalidation4, tiling_size(), tiling_rect());
- EXPECT_TRUE(pile_.is_solid_color());
- EXPECT_EQ(SK_ColorRED, pile_.solid_color());
-
- // If we draw too many, we don't bother doing the analysis and we should no
- // longer be in a solid state. There are 8 rects, two clips and a translate.
- client_.add_draw_rect(tiling_rect(), paint);
- client_.add_draw_rect(tiling_rect(), paint);
- client_.add_draw_rect(tiling_rect(), paint);
- client_.add_draw_rect(tiling_rect(), paint);
- client_.add_draw_rect(tiling_rect(), paint);
- Region invalidation5(tiling_rect());
- UpdateAndExpandInvalidation(&invalidation5, tiling_size(), tiling_rect());
- EXPECT_FALSE(pile_.is_solid_color());
-}
-
-TEST_F(PicturePileTest, NonSolidRectangleOnOffsettedLayerIsNonSolid) {
- gfx::Rect visible_rect(tiling_rect());
- visible_rect.Offset(gfx::Vector2d(1000, 1000));
- // The picture pile requires that the tiling completely encompass the viewport
- // to make this test work correctly since the recorded viewport is an
- // intersection of the tile size and viewport rect. This is possibly a flaw
- // in |PicturePile|.
- gfx::Size tiling_size(visible_rect.right(), visible_rect.bottom());
- // |Setup()| will create pictures here that mess with the test, clear it!
- pile_.Clear();
-
- SkPaint paint;
- paint.setColor(SK_ColorCYAN);
-
- // Add a rect that doesn't cover the viewport completely, the solid state
- // will be false.
- gfx::Rect smallRect = visible_rect;
- smallRect.Inset(10, 10, 10, 10);
- client_.add_draw_rect(smallRect, paint);
- Region invalidation(visible_rect);
- UpdateAndExpandInvalidation(&invalidation, tiling_size, visible_rect);
- EXPECT_FALSE(pile_.is_solid_color());
-}
-
-TEST_F(PicturePileTest, SetEmptyBounds) {
- EXPECT_TRUE(pile_.is_solid_color());
- EXPECT_FALSE(pile_.GetSize().IsEmpty());
- EXPECT_FALSE(pile_.picture_map().empty());
- EXPECT_TRUE(pile_.HasRecordings());
- pile_.SetEmptyBounds();
- EXPECT_FALSE(pile_.is_solid_color());
- EXPECT_TRUE(pile_.GetSize().IsEmpty());
- EXPECT_TRUE(pile_.picture_map().empty());
- EXPECT_FALSE(pile_.HasRecordings());
-}
-
-} // namespace
-} // namespace cc
diff --git a/chromium/cc/playback/picture_unittest.cc b/chromium/cc/playback/picture_unittest.cc
deleted file mode 100644
index 53310e37c81..00000000000
--- a/chromium/cc/playback/picture_unittest.cc
+++ /dev/null
@@ -1,181 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cc/playback/picture.h"
-
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/values.h"
-#include "cc/test/fake_content_layer_client.h"
-#include "cc/test/skia_common.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/skia/include/core/SkGraphics.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/skia_util.h"
-
-namespace cc {
-namespace {
-
-TEST(PictureTest, AsBase64String) {
- SkGraphics::Init();
-
- gfx::Rect layer_rect(100, 100);
-
- gfx::Size tile_grid_size(100, 100);
-
- FakeContentLayerClient content_layer_client;
-
- scoped_ptr<base::Value> tmp;
-
- SkPaint red_paint;
- red_paint.setColor(SkColorSetARGB(255, 255, 0, 0));
- SkPaint green_paint;
- green_paint.setColor(SkColorSetARGB(255, 0, 255, 0));
-
- // Invalid picture (not a dict).
- tmp.reset(new base::StringValue("abc!@#$%"));
- scoped_refptr<Picture> invalid_picture =
- Picture::CreateFromValue(tmp.get());
- EXPECT_FALSE(invalid_picture.get());
-
- // Single full-size rect picture.
- content_layer_client.add_draw_rect(layer_rect, red_paint);
-
- scoped_refptr<Picture> one_rect_picture =
- Picture::Create(layer_rect, &content_layer_client, tile_grid_size, false,
- RecordingSource::RECORD_NORMALLY);
- scoped_ptr<base::Value> serialized_one_rect(one_rect_picture->AsValue());
-
- // Reconstruct the picture.
- scoped_refptr<Picture> one_rect_picture_check =
- Picture::CreateFromValue(serialized_one_rect.get());
- EXPECT_TRUE(one_rect_picture_check);
-
- // Check for equivalence.
- unsigned char one_rect_buffer[4 * 100 * 100] = {0};
- DrawPicture(one_rect_buffer, layer_rect, one_rect_picture);
- unsigned char one_rect_buffer_check[4 * 100 * 100] = {0};
- DrawPicture(one_rect_buffer_check, layer_rect, one_rect_picture_check);
-
- EXPECT_EQ(one_rect_picture->LayerRect(), one_rect_picture_check->LayerRect());
- EXPECT_EQ(0, memcmp(one_rect_buffer, one_rect_buffer_check, 4 * 100 * 100));
-
- // Two rect picture.
- content_layer_client.add_draw_rect(gfx::Rect(25, 25, 50, 50), green_paint);
-
- scoped_refptr<Picture> two_rect_picture =
- Picture::Create(layer_rect, &content_layer_client, tile_grid_size, false,
- RecordingSource::RECORD_NORMALLY);
-
- scoped_ptr<base::Value> serialized_two_rect(two_rect_picture->AsValue());
-
- // Reconstruct the picture.
- scoped_refptr<Picture> two_rect_picture_check =
- Picture::CreateFromValue(serialized_two_rect.get());
- EXPECT_TRUE(two_rect_picture_check);
-
- // Check for equivalence.
- unsigned char two_rect_buffer[4 * 100 * 100] = {0};
- DrawPicture(two_rect_buffer, layer_rect, two_rect_picture);
- unsigned char two_rect_buffer_check[4 * 100 * 100] = {0};
- DrawPicture(two_rect_buffer_check, layer_rect, two_rect_picture_check);
-
- EXPECT_EQ(two_rect_picture->LayerRect(), two_rect_picture_check->LayerRect());
- EXPECT_EQ(0, memcmp(two_rect_buffer, two_rect_buffer_check, 4 * 100 * 100));
-}
-
-TEST(PictureTest, CreateFromSkpValue) {
- SkGraphics::Init();
-
- gfx::Rect layer_rect(100, 200);
-
- gfx::Size tile_grid_size(100, 200);
-
- FakeContentLayerClient content_layer_client;
-
- scoped_ptr<base::Value> tmp;
-
- SkPaint red_paint;
- red_paint.setColor(SkColorSetARGB(255, 255, 0, 0));
- SkPaint green_paint;
- green_paint.setColor(SkColorSetARGB(255, 0, 255, 0));
-
- // Invalid picture (not a dict).
- tmp.reset(new base::StringValue("abc!@#$%"));
- scoped_refptr<Picture> invalid_picture =
- Picture::CreateFromSkpValue(tmp.get());
- EXPECT_TRUE(!invalid_picture.get());
-
- // Single full-size rect picture.
- content_layer_client.add_draw_rect(layer_rect, red_paint);
- scoped_refptr<Picture> one_rect_picture =
- Picture::Create(layer_rect, &content_layer_client, tile_grid_size, false,
- RecordingSource::RECORD_NORMALLY);
- scoped_ptr<base::Value> serialized_one_rect(
- one_rect_picture->AsValue());
-
- const base::DictionaryValue* value = NULL;
- EXPECT_TRUE(serialized_one_rect->GetAsDictionary(&value));
-
- // Decode the picture from base64.
- const base::Value* skp_value;
- EXPECT_TRUE(value->Get("skp64", &skp_value));
-
- // Reconstruct the picture.
- scoped_refptr<Picture> one_rect_picture_check =
- Picture::CreateFromSkpValue(skp_value);
- EXPECT_TRUE(one_rect_picture_check);
-
- EXPECT_EQ(100, one_rect_picture_check->LayerRect().width());
- EXPECT_EQ(200, one_rect_picture_check->LayerRect().height());
-}
-
-TEST(PictureTest, RecordingModes) {
- SkGraphics::Init();
-
- gfx::Rect layer_rect(100, 200);
-
- gfx::Size tile_grid_size(100, 200);
-
- FakeContentLayerClient content_layer_client;
- EXPECT_EQ(NULL, content_layer_client.last_canvas());
-
- scoped_refptr<Picture> picture =
- Picture::Create(layer_rect, &content_layer_client, tile_grid_size, false,
- RecordingSource::RECORD_NORMALLY);
- EXPECT_TRUE(content_layer_client.last_canvas() != NULL);
- EXPECT_EQ(ContentLayerClient::PAINTING_BEHAVIOR_NORMAL,
- content_layer_client.last_painting_control());
- EXPECT_TRUE(picture.get());
-
- picture = Picture::Create(layer_rect, &content_layer_client, tile_grid_size,
- false, RecordingSource::RECORD_WITH_SK_NULL_CANVAS);
- EXPECT_TRUE(content_layer_client.last_canvas() != NULL);
- EXPECT_EQ(ContentLayerClient::PAINTING_BEHAVIOR_NORMAL,
- content_layer_client.last_painting_control());
- EXPECT_TRUE(picture.get());
-
- picture =
- Picture::Create(layer_rect, &content_layer_client, tile_grid_size, false,
- RecordingSource::RECORD_WITH_PAINTING_DISABLED);
- EXPECT_TRUE(content_layer_client.last_canvas() != NULL);
- EXPECT_EQ(ContentLayerClient::DISPLAY_LIST_PAINTING_DISABLED,
- content_layer_client.last_painting_control());
- EXPECT_TRUE(picture.get());
-
- picture =
- Picture::Create(layer_rect, &content_layer_client, tile_grid_size, false,
- RecordingSource::RECORD_WITH_CACHING_DISABLED);
- EXPECT_TRUE(content_layer_client.last_canvas() != NULL);
- EXPECT_EQ(ContentLayerClient::DISPLAY_LIST_CACHING_DISABLED,
- content_layer_client.last_painting_control());
- EXPECT_TRUE(picture.get());
-
- // RECORD_WITH_CONSTRUCTION_DISABLED is not supported for Picture.
-
- EXPECT_EQ(5, RecordingSource::RECORDING_MODE_COUNT);
-}
-
-} // namespace
-} // namespace cc
diff --git a/chromium/cc/playback/pixel_ref_map.cc b/chromium/cc/playback/pixel_ref_map.cc
deleted file mode 100644
index a5c8f05f453..00000000000
--- a/chromium/cc/playback/pixel_ref_map.cc
+++ /dev/null
@@ -1,174 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cc/playback/pixel_ref_map.h"
-
-#include <algorithm>
-#include <limits>
-
-#include "cc/base/math_util.h"
-#include "cc/playback/display_item_list.h"
-#include "cc/playback/picture.h"
-#include "skia/ext/pixel_ref_utils.h"
-
-namespace cc {
-
-PixelRefMap::PixelRefMap(const gfx::Size& cell_size) : cell_size_(cell_size) {
- DCHECK(!cell_size.IsEmpty());
-}
-
-PixelRefMap::~PixelRefMap() {
-}
-
-void PixelRefMap::GatherPixelRefsFromPicture(SkPicture* picture) {
- DCHECK(picture);
-
- int min_x = std::numeric_limits<int>::max();
- int min_y = std::numeric_limits<int>::max();
- int max_x = 0;
- int max_y = 0;
-
- skia::DiscardablePixelRefList pixel_refs;
- skia::PixelRefUtils::GatherDiscardablePixelRefs(picture, &pixel_refs);
- for (skia::DiscardablePixelRefList::const_iterator it = pixel_refs.begin();
- it != pixel_refs.end(); ++it) {
- gfx::Point min(MathUtil::RoundDown(static_cast<int>(it->pixel_ref_rect.x()),
- cell_size_.width()),
- MathUtil::RoundDown(static_cast<int>(it->pixel_ref_rect.y()),
- cell_size_.height()));
- gfx::Point max(MathUtil::RoundDown(
- static_cast<int>(std::ceil(it->pixel_ref_rect.right())),
- cell_size_.width()),
- MathUtil::RoundDown(
- static_cast<int>(std::ceil(it->pixel_ref_rect.bottom())),
- cell_size_.height()));
-
- for (int y = min.y(); y <= max.y(); y += cell_size_.height()) {
- for (int x = min.x(); x <= max.x(); x += cell_size_.width()) {
- PixelRefMapKey key(x, y);
- data_hash_map_[key].push_back(it->pixel_ref);
- }
- }
-
- min_x = std::min(min_x, min.x());
- min_y = std::min(min_y, min.y());
- max_x = std::max(max_x, max.x());
- max_y = std::max(max_y, max.y());
- }
-
- min_pixel_cell_ = gfx::Point(min_x, min_y);
- max_pixel_cell_ = gfx::Point(max_x, max_y);
-}
-
-base::LazyInstance<PixelRefs> PixelRefMap::Iterator::empty_pixel_refs_;
-
-PixelRefMap::Iterator::Iterator()
- : target_pixel_ref_map_(NULL),
- current_pixel_refs_(empty_pixel_refs_.Pointer()),
- current_index_(0),
- min_point_(-1, -1),
- max_point_(-1, -1),
- current_x_(0),
- current_y_(0) {
-}
-
-PixelRefMap::Iterator::Iterator(const gfx::Rect& rect, const Picture* picture)
- : target_pixel_ref_map_(&(picture->pixel_refs_)),
- current_pixel_refs_(empty_pixel_refs_.Pointer()),
- current_index_(0) {
- map_layer_rect_ = picture->layer_rect_;
- PointToFirstPixelRef(rect);
-}
-
-PixelRefMap::Iterator::Iterator(const gfx::Rect& rect,
- const DisplayItemList* display_list)
- : target_pixel_ref_map_(display_list->pixel_refs_.get()),
- current_pixel_refs_(empty_pixel_refs_.Pointer()),
- current_index_(0) {
- map_layer_rect_ = display_list->layer_rect_;
- PointToFirstPixelRef(rect);
-}
-
-PixelRefMap::Iterator::~Iterator() {
-}
-
-PixelRefMap::Iterator& PixelRefMap::Iterator::operator++() {
- ++current_index_;
- // If we're not at the end of the list, then we have the next item.
- if (current_index_ < current_pixel_refs_->size())
- return *this;
-
- DCHECK(current_y_ <= max_point_.y());
- while (true) {
- gfx::Size cell_size = target_pixel_ref_map_->cell_size_;
-
- // Advance the current grid cell.
- current_x_ += cell_size.width();
- if (current_x_ > max_point_.x()) {
- current_y_ += cell_size.height();
- current_x_ = min_point_.x();
- if (current_y_ > max_point_.y()) {
- current_pixel_refs_ = empty_pixel_refs_.Pointer();
- current_index_ = 0;
- break;
- }
- }
-
- // If there are no pixel refs at this grid cell, keep incrementing.
- PixelRefMapKey key(current_x_, current_y_);
- PixelRefHashmap::const_iterator iter =
- target_pixel_ref_map_->data_hash_map_.find(key);
- if (iter == target_pixel_ref_map_->data_hash_map_.end())
- continue;
-
- // We found a non-empty list: store it and get the first pixel ref.
- current_pixel_refs_ = &iter->second;
- current_index_ = 0;
- break;
- }
- return *this;
-}
-
-void PixelRefMap::Iterator::PointToFirstPixelRef(const gfx::Rect& rect) {
- gfx::Rect query_rect(rect);
- // Early out if the query rect doesn't intersect this picture.
- if (!query_rect.Intersects(map_layer_rect_) || !target_pixel_ref_map_) {
- min_point_ = gfx::Point(0, 0);
- max_point_ = gfx::Point(0, 0);
- current_x_ = 1;
- current_y_ = 1;
- return;
- }
-
- // First, subtract the layer origin as cells are stored in layer space.
- query_rect.Offset(-map_layer_rect_.OffsetFromOrigin());
-
- DCHECK(!target_pixel_ref_map_->cell_size_.IsEmpty());
- gfx::Size cell_size(target_pixel_ref_map_->cell_size_);
- // We have to find a cell_size aligned point that corresponds to
- // query_rect. Point is a multiple of cell_size.
- min_point_ =
- gfx::Point(MathUtil::RoundDown(query_rect.x(), cell_size.width()),
- MathUtil::RoundDown(query_rect.y(), cell_size.height()));
- max_point_ = gfx::Point(
- MathUtil::RoundDown(query_rect.right() - 1, cell_size.width()),
- MathUtil::RoundDown(query_rect.bottom() - 1, cell_size.height()));
-
- // Limit the points to known pixel ref boundaries.
- min_point_ = gfx::Point(
- std::max(min_point_.x(), target_pixel_ref_map_->min_pixel_cell_.x()),
- std::max(min_point_.y(), target_pixel_ref_map_->min_pixel_cell_.y()));
- max_point_ = gfx::Point(
- std::min(max_point_.x(), target_pixel_ref_map_->max_pixel_cell_.x()),
- std::min(max_point_.y(), target_pixel_ref_map_->max_pixel_cell_.y()));
-
- // Make the current x be cell_size.width() less than min point, so that
- // the first increment will point at min_point_.
- current_x_ = min_point_.x() - cell_size.width();
- current_y_ = min_point_.y();
- if (current_y_ <= max_point_.y())
- ++(*this);
-}
-
-} // namespace cc
diff --git a/chromium/cc/playback/pixel_ref_map.h b/chromium/cc/playback/pixel_ref_map.h
deleted file mode 100644
index e1545217836..00000000000
--- a/chromium/cc/playback/pixel_ref_map.h
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CC_PLAYBACK_PIXEL_REF_MAP_H_
-#define CC_PLAYBACK_PIXEL_REF_MAP_H_
-
-#include <utility>
-#include <vector>
-
-#include "base/containers/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "cc/base/cc_export.h"
-#include "third_party/skia/include/core/SkPicture.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/geometry/size.h"
-
-class SkPixelRef;
-
-namespace cc {
-
-class Picture;
-class DisplayItemList;
-
-typedef std::pair<int, int> PixelRefMapKey;
-typedef std::vector<SkPixelRef*> PixelRefs;
-typedef base::hash_map<PixelRefMapKey, PixelRefs> PixelRefHashmap;
-
-// This class is used and owned by cc Picture class. It is used to gather pixel
-// refs which would happen after record. It takes in |cell_size| to decide how
-// big each grid cell should be.
-class CC_EXPORT PixelRefMap {
- public:
- explicit PixelRefMap(const gfx::Size& cell_size);
- ~PixelRefMap();
- void GatherPixelRefsFromPicture(SkPicture* picture);
-
- bool empty() const { return data_hash_map_.empty(); }
-
- // This iterator imprecisely returns the set of pixel refs that are needed to
- // raster this layer rect from this picture. Internally, pixel refs are
- // clumped into tile grid buckets, so there may be false positives.
- class CC_EXPORT Iterator {
- public:
- // Default iterator constructor that is used as place holder for invalid
- // Iterator.
- Iterator();
- Iterator(const gfx::Rect& layer_rect, const Picture* picture);
- Iterator(const gfx::Rect& layer_rect, const DisplayItemList* picture);
- ~Iterator();
-
- SkPixelRef* operator->() const {
- DCHECK_LT(current_index_, current_pixel_refs_->size());
- return (*current_pixel_refs_)[current_index_];
- }
-
- SkPixelRef* operator*() const {
- DCHECK_LT(current_index_, current_pixel_refs_->size());
- return (*current_pixel_refs_)[current_index_];
- }
-
- Iterator& operator++();
- operator bool() const {
- return current_index_ < current_pixel_refs_->size();
- }
-
- private:
- void PointToFirstPixelRef(const gfx::Rect& query_rect);
-
- static base::LazyInstance<PixelRefs> empty_pixel_refs_;
- const PixelRefMap* target_pixel_ref_map_;
- const PixelRefs* current_pixel_refs_;
- unsigned current_index_;
-
- gfx::Rect map_layer_rect_;
-
- gfx::Point min_point_;
- gfx::Point max_point_;
- int current_x_;
- int current_y_;
- };
-
- private:
- gfx::Point min_pixel_cell_;
- gfx::Point max_pixel_cell_;
- gfx::Size cell_size_;
-
- PixelRefHashmap data_hash_map_;
-};
-
-} // namespace cc
-
-#endif // CC_PLAYBACK_PIXEL_REF_MAP_H_
diff --git a/chromium/cc/playback/pixel_ref_map_unittest.cc b/chromium/cc/playback/pixel_ref_map_unittest.cc
deleted file mode 100644
index af88b44c873..00000000000
--- a/chromium/cc/playback/pixel_ref_map_unittest.cc
+++ /dev/null
@@ -1,292 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cc/playback/pixel_ref_map.h"
-
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/values.h"
-#include "cc/playback/picture.h"
-#include "cc/test/fake_content_layer_client.h"
-#include "cc/test/skia_common.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/skia/include/core/SkGraphics.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/skia_util.h"
-
-namespace cc {
-namespace {
-
-TEST(PixelRefMapTest, PixelRefMapIterator) {
- gfx::Rect layer_rect(2048, 2048);
-
- gfx::Size tile_grid_size(512, 512);
-
- FakeContentLayerClient content_layer_client;
-
- // Discardable pixel refs are found in the following grids:
- // |---|---|---|---|
- // | | x | | x |
- // |---|---|---|---|
- // | x | | x | |
- // |---|---|---|---|
- // | | x | | x |
- // |---|---|---|---|
- // | x | | x | |
- // |---|---|---|---|
- SkBitmap discardable_bitmap[4][4];
- for (int y = 0; y < 4; ++y) {
- for (int x = 0; x < 4; ++x) {
- if ((x + y) & 1) {
- CreateBitmap(gfx::Size(500, 500), "discardable",
- &discardable_bitmap[y][x]);
- SkPaint paint;
- content_layer_client.add_draw_bitmap(
- discardable_bitmap[y][x], gfx::Point(x * 512 + 6, y * 512 + 6),
- paint);
- }
- }
- }
-
- scoped_refptr<Picture> picture =
- Picture::Create(layer_rect, &content_layer_client, tile_grid_size, true,
- RecordingSource::RECORD_NORMALLY);
-
- // Default iterator does not have any pixel refs.
- {
- PixelRefMap::Iterator iterator;
- EXPECT_FALSE(iterator);
- }
-
- for (int y = 0; y < 4; ++y) {
- for (int x = 0; x < 4; ++x) {
- PixelRefMap::Iterator iterator(gfx::Rect(x * 512, y * 512, 500, 500),
- picture.get());
- if ((x + y) & 1) {
- EXPECT_TRUE(iterator) << x << " " << y;
- EXPECT_TRUE(*iterator == discardable_bitmap[y][x].pixelRef())
- << x << " " << y;
- EXPECT_FALSE(++iterator) << x << " " << y;
- } else {
- EXPECT_FALSE(iterator) << x << " " << y;
- }
- }
- }
- // Capture 4 pixel refs.
- {
- PixelRefMap::Iterator iterator(gfx::Rect(512, 512, 2048, 2048),
- picture.get());
- EXPECT_TRUE(iterator);
- EXPECT_TRUE(*iterator == discardable_bitmap[1][2].pixelRef());
- EXPECT_TRUE(++iterator);
- EXPECT_TRUE(*iterator == discardable_bitmap[2][1].pixelRef());
- EXPECT_TRUE(++iterator);
- EXPECT_TRUE(*iterator == discardable_bitmap[2][3].pixelRef());
- EXPECT_TRUE(++iterator);
- EXPECT_TRUE(*iterator == discardable_bitmap[3][2].pixelRef());
- EXPECT_FALSE(++iterator);
- }
-
- // Copy test.
- PixelRefMap::Iterator iterator(gfx::Rect(512, 512, 2048, 2048),
- picture.get());
- EXPECT_TRUE(iterator);
- EXPECT_TRUE(*iterator == discardable_bitmap[1][2].pixelRef());
- EXPECT_TRUE(++iterator);
- EXPECT_TRUE(*iterator == discardable_bitmap[2][1].pixelRef());
-
- // copy now points to the same spot as iterator,
- // but both can be incremented independently.
- PixelRefMap::Iterator copy = iterator;
- EXPECT_TRUE(++iterator);
- EXPECT_TRUE(*iterator == discardable_bitmap[2][3].pixelRef());
- EXPECT_TRUE(++iterator);
- EXPECT_TRUE(*iterator == discardable_bitmap[3][2].pixelRef());
- EXPECT_FALSE(++iterator);
-
- EXPECT_TRUE(copy);
- EXPECT_TRUE(*copy == discardable_bitmap[2][1].pixelRef());
- EXPECT_TRUE(++copy);
- EXPECT_TRUE(*copy == discardable_bitmap[2][3].pixelRef());
- EXPECT_TRUE(++copy);
- EXPECT_TRUE(*copy == discardable_bitmap[3][2].pixelRef());
- EXPECT_FALSE(++copy);
-}
-
-TEST(PixelRefMapTest, PixelRefMapIteratorNonZeroLayer) {
- gfx::Rect layer_rect(1024, 0, 2048, 2048);
-
- gfx::Size tile_grid_size(512, 512);
-
- FakeContentLayerClient content_layer_client;
-
- // Discardable pixel refs are found in the following grids:
- // |---|---|---|---|
- // | | x | | x |
- // |---|---|---|---|
- // | x | | x | |
- // |---|---|---|---|
- // | | x | | x |
- // |---|---|---|---|
- // | x | | x | |
- // |---|---|---|---|
- SkBitmap discardable_bitmap[4][4];
- for (int y = 0; y < 4; ++y) {
- for (int x = 0; x < 4; ++x) {
- if ((x + y) & 1) {
- CreateBitmap(gfx::Size(500, 500), "discardable",
- &discardable_bitmap[y][x]);
- SkPaint paint;
- content_layer_client.add_draw_bitmap(
- discardable_bitmap[y][x],
- gfx::Point(1024 + x * 512 + 6, y * 512 + 6), paint);
- }
- }
- }
-
- scoped_refptr<Picture> picture =
- Picture::Create(layer_rect, &content_layer_client, tile_grid_size, true,
- RecordingSource::RECORD_NORMALLY);
-
- // Default iterator does not have any pixel refs.
- {
- PixelRefMap::Iterator iterator;
- EXPECT_FALSE(iterator);
- }
-
- for (int y = 0; y < 4; ++y) {
- for (int x = 0; x < 4; ++x) {
- PixelRefMap::Iterator iterator(
- gfx::Rect(1024 + x * 512, y * 512, 500, 500), picture.get());
- if ((x + y) & 1) {
- EXPECT_TRUE(iterator) << x << " " << y;
- EXPECT_TRUE(*iterator == discardable_bitmap[y][x].pixelRef());
- EXPECT_FALSE(++iterator) << x << " " << y;
- } else {
- EXPECT_FALSE(iterator) << x << " " << y;
- }
- }
- }
- // Capture 4 pixel refs.
- {
- PixelRefMap::Iterator iterator(gfx::Rect(1024 + 512, 512, 2048, 2048),
- picture.get());
- EXPECT_TRUE(iterator);
- EXPECT_TRUE(*iterator == discardable_bitmap[1][2].pixelRef());
- EXPECT_TRUE(++iterator);
- EXPECT_TRUE(*iterator == discardable_bitmap[2][1].pixelRef());
- EXPECT_TRUE(++iterator);
- EXPECT_TRUE(*iterator == discardable_bitmap[2][3].pixelRef());
- EXPECT_TRUE(++iterator);
- EXPECT_TRUE(*iterator == discardable_bitmap[3][2].pixelRef());
- EXPECT_FALSE(++iterator);
- }
-
- // Copy test.
- {
- PixelRefMap::Iterator iterator(gfx::Rect(1024 + 512, 512, 2048, 2048),
- picture.get());
- EXPECT_TRUE(iterator);
- EXPECT_TRUE(*iterator == discardable_bitmap[1][2].pixelRef());
- EXPECT_TRUE(++iterator);
- EXPECT_TRUE(*iterator == discardable_bitmap[2][1].pixelRef());
-
- // copy now points to the same spot as iterator,
- // but both can be incremented independently.
- PixelRefMap::Iterator copy = iterator;
- EXPECT_TRUE(++iterator);
- EXPECT_TRUE(*iterator == discardable_bitmap[2][3].pixelRef());
- EXPECT_TRUE(++iterator);
- EXPECT_TRUE(*iterator == discardable_bitmap[3][2].pixelRef());
- EXPECT_FALSE(++iterator);
-
- EXPECT_TRUE(copy);
- EXPECT_TRUE(*copy == discardable_bitmap[2][1].pixelRef());
- EXPECT_TRUE(++copy);
- EXPECT_TRUE(*copy == discardable_bitmap[2][3].pixelRef());
- EXPECT_TRUE(++copy);
- EXPECT_TRUE(*copy == discardable_bitmap[3][2].pixelRef());
- EXPECT_FALSE(++copy);
- }
-
- // Non intersecting rects
- {
- PixelRefMap::Iterator iterator(gfx::Rect(0, 0, 1000, 1000), picture.get());
- EXPECT_FALSE(iterator);
- }
- {
- PixelRefMap::Iterator iterator(gfx::Rect(3500, 0, 1000, 1000),
- picture.get());
- EXPECT_FALSE(iterator);
- }
- {
- PixelRefMap::Iterator iterator(gfx::Rect(0, 1100, 1000, 1000),
- picture.get());
- EXPECT_FALSE(iterator);
- }
- {
- PixelRefMap::Iterator iterator(gfx::Rect(3500, 1100, 1000, 1000),
- picture.get());
- EXPECT_FALSE(iterator);
- }
-}
-
-TEST(PixelRefMapTest, PixelRefMapIteratorOnePixelQuery) {
- gfx::Rect layer_rect(2048, 2048);
-
- gfx::Size tile_grid_size(512, 512);
-
- FakeContentLayerClient content_layer_client;
-
- // Discardable pixel refs are found in the following grids:
- // |---|---|---|---|
- // | | x | | x |
- // |---|---|---|---|
- // | x | | x | |
- // |---|---|---|---|
- // | | x | | x |
- // |---|---|---|---|
- // | x | | x | |
- // |---|---|---|---|
- SkBitmap discardable_bitmap[4][4];
- for (int y = 0; y < 4; ++y) {
- for (int x = 0; x < 4; ++x) {
- if ((x + y) & 1) {
- CreateBitmap(gfx::Size(500, 500), "discardable",
- &discardable_bitmap[y][x]);
- SkPaint paint;
- content_layer_client.add_draw_bitmap(
- discardable_bitmap[y][x], gfx::Point(x * 512 + 6, y * 512 + 6),
- paint);
- }
- }
- }
-
- scoped_refptr<Picture> picture =
- Picture::Create(layer_rect, &content_layer_client, tile_grid_size, true,
- RecordingSource::RECORD_NORMALLY);
-
- // Default iterator does not have any pixel refs.
- {
- PixelRefMap::Iterator iterator;
- EXPECT_FALSE(iterator);
- }
-
- for (int y = 0; y < 4; ++y) {
- for (int x = 0; x < 4; ++x) {
- PixelRefMap::Iterator iterator(gfx::Rect(x * 512, y * 512 + 256, 1, 1),
- picture.get());
- if ((x + y) & 1) {
- EXPECT_TRUE(iterator) << x << " " << y;
- EXPECT_TRUE(*iterator == discardable_bitmap[y][x].pixelRef());
- EXPECT_FALSE(++iterator) << x << " " << y;
- } else {
- EXPECT_FALSE(iterator) << x << " " << y;
- }
- }
- }
-}
-
-} // namespace
-} // namespace cc
diff --git a/chromium/cc/playback/position_image.h b/chromium/cc/playback/position_image.h
new file mode 100644
index 00000000000..662a30ae074
--- /dev/null
+++ b/chromium/cc/playback/position_image.h
@@ -0,0 +1,33 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_PLAYBACK_POSITION_IMAGE_H_
+#define CC_PLAYBACK_POSITION_IMAGE_H_
+
+#include "third_party/skia/include/core/SkFilterQuality.h"
+#include "third_party/skia/include/core/SkImage.h"
+#include "third_party/skia/include/core/SkMatrix.h"
+#include "third_party/skia/include/core/SkRect.h"
+
+namespace cc {
+
+struct PositionImage {
+ PositionImage(const SkImage* image,
+ const SkRect& image_rect,
+ const SkMatrix& matrix,
+ SkFilterQuality filter_quality)
+ : image(image),
+ image_rect(image_rect),
+ matrix(matrix),
+ filter_quality(filter_quality) {}
+
+ const SkImage* image;
+ SkRect image_rect;
+ SkMatrix matrix;
+ SkFilterQuality filter_quality;
+};
+
+} // namespace cc
+
+#endif // CC_PLAYBACK_POSITION_IMAGE_H_
diff --git a/chromium/cc/playback/raster_source.h b/chromium/cc/playback/raster_source.h
index 8d0356fae38..4d0a6f96bf3 100644
--- a/chromium/cc/playback/raster_source.h
+++ b/chromium/cc/playback/raster_source.h
@@ -10,9 +10,9 @@
#include "base/memory/ref_counted.h"
#include "cc/base/cc_export.h"
#include "cc/debug/traced_value.h"
+#include "cc/playback/discardable_image_map.h"
#include "skia/ext/refptr.h"
#include "third_party/skia/include/core/SkColor.h"
-#include "third_party/skia/include/core/SkPixelRef.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
@@ -21,8 +21,6 @@ class SkPicture;
namespace cc {
-class Picture;
-
class CC_EXPORT RasterSource : public base::RefCountedThreadSafe<RasterSource> {
public:
struct CC_EXPORT SolidColorAnalysis {
@@ -69,20 +67,22 @@ class CC_EXPORT RasterSource : public base::RefCountedThreadSafe<RasterSource> {
// Returns the size of this raster source.
virtual gfx::Size GetSize() const = 0;
- // Populate the given list with all SkPixelRefs that may overlap the given
- // rect at given scale.
- virtual void GatherPixelRefs(const gfx::Rect& content_rect,
- float contents_scale,
- std::vector<SkPixelRef*>* pixel_refs) const = 0;
+ // Populate the given list with all images that may overlap the given
+ // rect in layer space.
+ virtual void GetDiscardableImagesInRect(
+ const gfx::Rect& layer_rect,
+ std::vector<PositionImage>* images) const = 0;
- // Return true iff this raster source can raster the given rect at given
- // scale.
- virtual bool CoversRect(const gfx::Rect& content_rect,
- float contents_scale) const = 0;
+ // Return true iff this raster source can raster the given rect in layer
+ // space.
+ virtual bool CoversRect(const gfx::Rect& layer_rect) const = 0;
// Returns true if this raster source has anything to rasterize.
virtual bool HasRecordings() const = 0;
+ // Valid rectangle in which everything is recorded and can be rastered from.
+ virtual gfx::Rect RecordedViewport() const = 0;
+
// Informs the raster source that it should attempt to use distance field text
// during rasterization.
virtual void SetShouldAttemptToUseDistanceFieldText() = 0;
diff --git a/chromium/cc/playback/raster_source_helper.cc b/chromium/cc/playback/raster_source_helper.cc
index bd5edda07c3..3655ba3cb9e 100644
--- a/chromium/cc/playback/raster_source_helper.cc
+++ b/chromium/cc/playback/raster_source_helper.cc
@@ -60,7 +60,7 @@ void RasterSourceHelper::PrepareForPlaybackToCanvas(
// texel (since the recording won't cover it) and outside the last texel
// (due to linear filtering when using this texture).
gfx::Rect content_rect =
- gfx::ToEnclosingRect(gfx::ScaleRect(source_rect, contents_scale));
+ gfx::ScaleToEnclosingRect(source_rect, contents_scale);
// The final texel of content may only be partially covered by a
// rasterization; this rect represents the content rect that is fully
diff --git a/chromium/cc/playback/recording_source.h b/chromium/cc/playback/recording_source.h
index cf8c7c466f5..7d4aba1a43d 100644
--- a/chromium/cc/playback/recording_source.h
+++ b/chromium/cc/playback/recording_source.h
@@ -48,14 +48,10 @@ class CC_EXPORT RecordingSource {
virtual gfx::Size GetSize() const = 0;
virtual void SetEmptyBounds() = 0;
virtual void SetSlowdownRasterScaleFactor(int factor) = 0;
- virtual void SetGatherPixelRefs(bool gather_pixel_refs) = 0;
+ virtual void SetGenerateDiscardableImagesMetadata(bool generate_metadata) = 0;
virtual void SetBackgroundColor(SkColor background_color) = 0;
virtual void SetRequiresClear(bool requires_clear) = 0;
virtual bool IsSuitableForGpuRasterization() const = 0;
-
- // TODO(hendrikw): Figure out how to remove this.
- virtual void SetUnsuitableForGpuRasterizationForTesting() = 0;
- virtual gfx::Size GetTileGridSizeForTesting() const = 0;
};
} // namespace cc
diff --git a/chromium/cc/playback/recording_source_unittest.cc b/chromium/cc/playback/recording_source_unittest.cc
deleted file mode 100644
index f1506e32ec8..00000000000
--- a/chromium/cc/playback/recording_source_unittest.cc
+++ /dev/null
@@ -1,471 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <vector>
-
-#include "cc/playback/display_list_raster_source.h"
-#include "cc/test/fake_display_list_recording_source.h"
-#include "cc/test/fake_picture_pile.h"
-#include "cc/test/fake_picture_pile_impl.h"
-#include "cc/test/skia_common.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace cc {
-namespace {
-
-template <class T>
-scoped_ptr<T> CreateRecordingSource(const gfx::Rect& viewport,
- const gfx::Size& grid_cell_size);
-
-template <>
-scoped_ptr<FakePicturePile> CreateRecordingSource<FakePicturePile>(
- const gfx::Rect& viewport,
- const gfx::Size& grid_cell_size) {
- return FakePicturePile::CreateFilledPile(grid_cell_size, viewport.size());
-}
-
-template <>
-scoped_ptr<FakeDisplayListRecordingSource> CreateRecordingSource<
- FakeDisplayListRecordingSource>(const gfx::Rect& viewport,
- const gfx::Size& grid_cell_size) {
- gfx::Rect layer_rect(viewport.right(), viewport.bottom());
- scoped_ptr<FakeDisplayListRecordingSource> recording_source =
- FakeDisplayListRecordingSource::CreateRecordingSource(viewport,
- layer_rect.size());
- recording_source->SetGridCellSize(grid_cell_size);
-
- return recording_source.Pass();
-}
-
-template <class T>
-scoped_refptr<RasterSource> CreateRasterSource(T* recording_source);
-
-template <>
-scoped_refptr<RasterSource> CreateRasterSource(
- FakePicturePile* recording_source) {
- return FakePicturePileImpl::CreateFromPile(recording_source, nullptr);
-}
-
-template <>
-scoped_refptr<RasterSource> CreateRasterSource(
- FakeDisplayListRecordingSource* recording_source) {
- bool can_use_lcd_text = true;
- return DisplayListRasterSource::CreateFromDisplayListRecordingSource(
- recording_source, can_use_lcd_text);
-}
-
-template <typename T>
-class RecordingSourceTest : public testing::Test {};
-
-using testing::Types;
-
-typedef Types<FakePicturePile, FakeDisplayListRecordingSource>
- RecordingSourceImplementations;
-
-TYPED_TEST_CASE(RecordingSourceTest, RecordingSourceImplementations);
-
-TYPED_TEST(RecordingSourceTest, NoGatherPixelRefEmptyPixelRefs) {
- gfx::Size grid_cell_size(128, 128);
- gfx::Rect recorded_viewport(0, 0, 256, 256);
-
- scoped_ptr<TypeParam> recording_source =
- CreateRecordingSource<TypeParam>(recorded_viewport, grid_cell_size);
- recording_source->SetGatherPixelRefs(false);
- recording_source->Rerecord();
-
- scoped_refptr<RasterSource> raster_source =
- CreateRasterSource<TypeParam>(recording_source.get());
-
- // If recording source do not gather pixel ref, raster source is not going to
- // get pixel refs.
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(recorded_viewport, 1.0, &pixel_refs);
- EXPECT_TRUE(pixel_refs.empty());
- }
-}
-
-TYPED_TEST(RecordingSourceTest, EmptyPixelRefs) {
- gfx::Size grid_cell_size(128, 128);
- gfx::Rect recorded_viewport(0, 0, 256, 256);
-
- scoped_ptr<TypeParam> recording_source =
- CreateRecordingSource<TypeParam>(recorded_viewport, grid_cell_size);
- recording_source->SetGatherPixelRefs(true);
- recording_source->Rerecord();
-
- scoped_refptr<RasterSource> raster_source =
- CreateRasterSource<TypeParam>(recording_source.get());
-
- // Tile sized iterators.
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(0, 0, 128, 128), 1.0, &pixel_refs);
- EXPECT_TRUE(pixel_refs.empty());
- }
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(0, 0, 256, 256), 2.0, &pixel_refs);
- EXPECT_TRUE(pixel_refs.empty());
- }
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(0, 0, 64, 64), 0.5, &pixel_refs);
- EXPECT_TRUE(pixel_refs.empty());
- }
- // Shifted tile sized iterators.
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(140, 140, 128, 128), 1.0,
- &pixel_refs);
- EXPECT_TRUE(pixel_refs.empty());
- }
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(280, 280, 256, 256), 2.0,
- &pixel_refs);
- EXPECT_TRUE(pixel_refs.empty());
- }
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(70, 70, 64, 64), 0.5, &pixel_refs);
- EXPECT_TRUE(pixel_refs.empty());
- }
- // Layer sized iterators.
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(0, 0, 256, 256), 1.0, &pixel_refs);
- EXPECT_TRUE(pixel_refs.empty());
- }
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(0, 0, 512, 512), 2.0, &pixel_refs);
- EXPECT_TRUE(pixel_refs.empty());
- }
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(0, 0, 128, 128), 0.5, &pixel_refs);
- EXPECT_TRUE(pixel_refs.empty());
- }
-}
-
-TYPED_TEST(RecordingSourceTest, NoDiscardablePixelRefs) {
- gfx::Size grid_cell_size(128, 128);
- gfx::Rect recorded_viewport(0, 0, 256, 256);
-
- scoped_ptr<TypeParam> recording_source =
- CreateRecordingSource<TypeParam>(recorded_viewport, grid_cell_size);
-
- SkPaint simple_paint;
- simple_paint.setColor(SkColorSetARGB(255, 12, 23, 34));
-
- SkBitmap non_discardable_bitmap;
- CreateBitmap(gfx::Size(128, 128), "notdiscardable", &non_discardable_bitmap);
-
- recording_source->add_draw_rect_with_paint(gfx::Rect(0, 0, 256, 256),
- simple_paint);
- recording_source->add_draw_rect_with_paint(gfx::Rect(128, 128, 512, 512),
- simple_paint);
- recording_source->add_draw_rect_with_paint(gfx::Rect(512, 0, 256, 256),
- simple_paint);
- recording_source->add_draw_rect_with_paint(gfx::Rect(0, 512, 256, 256),
- simple_paint);
- recording_source->add_draw_bitmap(non_discardable_bitmap, gfx::Point(128, 0));
- recording_source->add_draw_bitmap(non_discardable_bitmap, gfx::Point(0, 128));
- recording_source->add_draw_bitmap(non_discardable_bitmap,
- gfx::Point(150, 150));
- recording_source->SetGatherPixelRefs(true);
- recording_source->Rerecord();
-
- scoped_refptr<RasterSource> raster_source =
- CreateRasterSource<TypeParam>(recording_source.get());
-
- // Tile sized iterators.
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(0, 0, 128, 128), 1.0, &pixel_refs);
- EXPECT_TRUE(pixel_refs.empty());
- }
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(0, 0, 256, 256), 2.0, &pixel_refs);
- EXPECT_TRUE(pixel_refs.empty());
- }
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(0, 0, 64, 64), 0.5, &pixel_refs);
- EXPECT_TRUE(pixel_refs.empty());
- }
- // Shifted tile sized iterators.
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(140, 140, 128, 128), 1.0,
- &pixel_refs);
- EXPECT_TRUE(pixel_refs.empty());
- }
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(280, 280, 256, 256), 2.0,
- &pixel_refs);
- EXPECT_TRUE(pixel_refs.empty());
- }
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(70, 70, 64, 64), 0.5, &pixel_refs);
- EXPECT_TRUE(pixel_refs.empty());
- }
- // Layer sized iterators.
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(0, 0, 256, 256), 1.0, &pixel_refs);
- EXPECT_TRUE(pixel_refs.empty());
- }
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(0, 0, 512, 512), 2.0, &pixel_refs);
- EXPECT_TRUE(pixel_refs.empty());
- }
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(0, 0, 128, 128), 0.5, &pixel_refs);
- EXPECT_TRUE(pixel_refs.empty());
- }
-}
-
-TYPED_TEST(RecordingSourceTest, DiscardablePixelRefs) {
- gfx::Size grid_cell_size(128, 128);
- gfx::Rect recorded_viewport(0, 0, 256, 256);
-
- scoped_ptr<TypeParam> recording_source =
- CreateRecordingSource<TypeParam>(recorded_viewport, grid_cell_size);
-
- SkBitmap discardable_bitmap[2][2];
- CreateBitmap(gfx::Size(32, 32), "discardable", &discardable_bitmap[0][0]);
- CreateBitmap(gfx::Size(32, 32), "discardable", &discardable_bitmap[1][0]);
- CreateBitmap(gfx::Size(32, 32), "discardable", &discardable_bitmap[1][1]);
-
- // Discardable pixel refs are found in the following cells:
- // |---|---|
- // | x | |
- // |---|---|
- // | x | x |
- // |---|---|
- recording_source->add_draw_bitmap(discardable_bitmap[0][0], gfx::Point(0, 0));
- recording_source->add_draw_bitmap(discardable_bitmap[1][0],
- gfx::Point(0, 130));
- recording_source->add_draw_bitmap(discardable_bitmap[1][1],
- gfx::Point(140, 140));
- recording_source->SetGatherPixelRefs(true);
- recording_source->Rerecord();
-
- scoped_refptr<RasterSource> raster_source =
- CreateRasterSource<TypeParam>(recording_source.get());
-
- // Tile sized iterators. These should find only one pixel ref.
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(0, 0, 128, 128), 1.0, &pixel_refs);
- EXPECT_FALSE(pixel_refs.empty());
- EXPECT_TRUE(pixel_refs[0] == discardable_bitmap[0][0].pixelRef());
- EXPECT_EQ(1u, pixel_refs.size());
- }
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(0, 0, 256, 256), 2.0, &pixel_refs);
- EXPECT_FALSE(pixel_refs.empty());
- EXPECT_TRUE(pixel_refs[0] == discardable_bitmap[0][0].pixelRef());
- EXPECT_EQ(1u, pixel_refs.size());
- }
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(0, 0, 64, 64), 0.5, &pixel_refs);
- EXPECT_FALSE(pixel_refs.empty());
- EXPECT_TRUE(pixel_refs[0] == discardable_bitmap[0][0].pixelRef());
- EXPECT_EQ(1u, pixel_refs.size());
- }
-
- // Shifted tile sized iterators. These should find only one pixel ref.
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(140, 140, 128, 128), 1.0,
- &pixel_refs);
- EXPECT_FALSE(pixel_refs.empty());
- EXPECT_TRUE(pixel_refs[0] == discardable_bitmap[1][1].pixelRef());
- EXPECT_EQ(1u, pixel_refs.size());
- }
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(280, 280, 256, 256), 2.0,
- &pixel_refs);
- EXPECT_FALSE(pixel_refs.empty());
- EXPECT_TRUE(pixel_refs[0] == discardable_bitmap[1][1].pixelRef());
- EXPECT_EQ(1u, pixel_refs.size());
- }
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(70, 70, 64, 64), 0.5, &pixel_refs);
- EXPECT_FALSE(pixel_refs.empty());
- EXPECT_TRUE(pixel_refs[0] == discardable_bitmap[1][1].pixelRef());
- EXPECT_EQ(1u, pixel_refs.size());
- }
-
- // Ensure there's no discardable pixel refs in the empty cell
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(140, 0, 128, 128), 1.0,
- &pixel_refs);
- EXPECT_TRUE(pixel_refs.empty());
- }
-
- // Layer sized iterators. These should find all 3 pixel refs.
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(0, 0, 256, 256), 1.0, &pixel_refs);
- EXPECT_FALSE(pixel_refs.empty());
- EXPECT_TRUE(pixel_refs[0] == discardable_bitmap[0][0].pixelRef());
- EXPECT_TRUE(pixel_refs[1] == discardable_bitmap[1][0].pixelRef());
- EXPECT_TRUE(pixel_refs[2] == discardable_bitmap[1][1].pixelRef());
- EXPECT_EQ(3u, pixel_refs.size());
- }
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(0, 0, 512, 512), 2.0, &pixel_refs);
- EXPECT_FALSE(pixel_refs.empty());
- EXPECT_TRUE(pixel_refs[0] == discardable_bitmap[0][0].pixelRef());
- EXPECT_TRUE(pixel_refs[1] == discardable_bitmap[1][0].pixelRef());
- EXPECT_TRUE(pixel_refs[2] == discardable_bitmap[1][1].pixelRef());
- EXPECT_EQ(3u, pixel_refs.size());
- }
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(0, 0, 128, 128), 0.5, &pixel_refs);
- EXPECT_FALSE(pixel_refs.empty());
- EXPECT_TRUE(pixel_refs[0] == discardable_bitmap[0][0].pixelRef());
- EXPECT_TRUE(pixel_refs[1] == discardable_bitmap[1][0].pixelRef());
- EXPECT_TRUE(pixel_refs[2] == discardable_bitmap[1][1].pixelRef());
- EXPECT_EQ(3u, pixel_refs.size());
- }
-}
-
-TYPED_TEST(RecordingSourceTest, DiscardablePixelRefsBaseNonDiscardable) {
- gfx::Size grid_cell_size(256, 256);
- gfx::Rect recorded_viewport(0, 0, 512, 512);
-
- scoped_ptr<TypeParam> recording_source =
- CreateRecordingSource<TypeParam>(recorded_viewport, grid_cell_size);
-
- SkBitmap non_discardable_bitmap;
- CreateBitmap(gfx::Size(512, 512), "notdiscardable", &non_discardable_bitmap);
-
- SkBitmap discardable_bitmap[2][2];
- CreateBitmap(gfx::Size(128, 128), "discardable", &discardable_bitmap[0][0]);
- CreateBitmap(gfx::Size(128, 128), "discardable", &discardable_bitmap[0][1]);
- CreateBitmap(gfx::Size(128, 128), "discardable", &discardable_bitmap[1][1]);
-
- // One large non-discardable bitmap covers the whole grid.
- // Discardable pixel refs are found in the following cells:
- // |---|---|
- // | x | x |
- // |---|---|
- // | | x |
- // |---|---|
- recording_source->add_draw_bitmap(non_discardable_bitmap, gfx::Point(0, 0));
- recording_source->add_draw_bitmap(discardable_bitmap[0][0], gfx::Point(0, 0));
- recording_source->add_draw_bitmap(discardable_bitmap[0][1],
- gfx::Point(260, 0));
- recording_source->add_draw_bitmap(discardable_bitmap[1][1],
- gfx::Point(260, 260));
- recording_source->SetGatherPixelRefs(true);
- recording_source->Rerecord();
-
- scoped_refptr<RasterSource> raster_source =
- CreateRasterSource<TypeParam>(recording_source.get());
-
- // Tile sized iterators. These should find only one pixel ref.
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(0, 0, 256, 256), 1.0, &pixel_refs);
- EXPECT_FALSE(pixel_refs.empty());
- EXPECT_TRUE(pixel_refs[0] == discardable_bitmap[0][0].pixelRef());
- EXPECT_EQ(1u, pixel_refs.size());
- }
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(0, 0, 512, 512), 2.0, &pixel_refs);
- EXPECT_FALSE(pixel_refs.empty());
- EXPECT_TRUE(pixel_refs[0] == discardable_bitmap[0][0].pixelRef());
- EXPECT_EQ(1u, pixel_refs.size());
- }
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(0, 0, 128, 128), 0.5, &pixel_refs);
- EXPECT_FALSE(pixel_refs.empty());
- EXPECT_TRUE(pixel_refs[0] == discardable_bitmap[0][0].pixelRef());
- EXPECT_EQ(1u, pixel_refs.size());
- }
- // Shifted tile sized iterators. These should find only one pixel ref.
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(260, 260, 256, 256), 1.0,
- &pixel_refs);
- EXPECT_FALSE(pixel_refs.empty());
- EXPECT_TRUE(pixel_refs[0] == discardable_bitmap[1][1].pixelRef());
- EXPECT_EQ(1u, pixel_refs.size());
- }
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(520, 520, 512, 512), 2.0,
- &pixel_refs);
- EXPECT_FALSE(pixel_refs.empty());
- EXPECT_TRUE(pixel_refs[0] == discardable_bitmap[1][1].pixelRef());
- EXPECT_EQ(1u, pixel_refs.size());
- }
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(130, 130, 128, 128), 0.5,
- &pixel_refs);
- EXPECT_FALSE(pixel_refs.empty());
- EXPECT_TRUE(pixel_refs[0] == discardable_bitmap[1][1].pixelRef());
- EXPECT_EQ(1u, pixel_refs.size());
- }
- // Ensure there's no discardable pixel refs in the empty cell
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(0, 256, 256, 256), 1.0,
- &pixel_refs);
- EXPECT_TRUE(pixel_refs.empty());
- }
- // Layer sized iterators. These should find three pixel ref.
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(0, 0, 512, 512), 1.0, &pixel_refs);
- EXPECT_FALSE(pixel_refs.empty());
- EXPECT_TRUE(pixel_refs[0] == discardable_bitmap[0][0].pixelRef());
- EXPECT_TRUE(pixel_refs[1] == discardable_bitmap[0][1].pixelRef());
- EXPECT_TRUE(pixel_refs[2] == discardable_bitmap[1][1].pixelRef());
- EXPECT_EQ(3u, pixel_refs.size());
- }
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(0, 0, 1024, 1024), 2.0,
- &pixel_refs);
- EXPECT_FALSE(pixel_refs.empty());
- EXPECT_TRUE(pixel_refs[0] == discardable_bitmap[0][0].pixelRef());
- EXPECT_TRUE(pixel_refs[1] == discardable_bitmap[0][1].pixelRef());
- EXPECT_TRUE(pixel_refs[2] == discardable_bitmap[1][1].pixelRef());
- EXPECT_EQ(3u, pixel_refs.size());
- }
- {
- std::vector<SkPixelRef*> pixel_refs;
- raster_source->GatherPixelRefs(gfx::Rect(0, 0, 256, 256), 0.5, &pixel_refs);
- EXPECT_FALSE(pixel_refs.empty());
- EXPECT_TRUE(pixel_refs[0] == discardable_bitmap[0][0].pixelRef());
- EXPECT_TRUE(pixel_refs[1] == discardable_bitmap[0][1].pixelRef());
- EXPECT_TRUE(pixel_refs[2] == discardable_bitmap[1][1].pixelRef());
- EXPECT_EQ(3u, pixel_refs.size());
- }
-}
-
-} // namespace
-} // namespace cc
diff --git a/chromium/cc/playback/transform_display_item.cc b/chromium/cc/playback/transform_display_item.cc
index df7ca1b8e56..b52f138a538 100644
--- a/chromium/cc/playback/transform_display_item.cc
+++ b/chromium/cc/playback/transform_display_item.cc
@@ -32,6 +32,13 @@ void TransformDisplayItem::Raster(SkCanvas* canvas,
canvas->concat(transform_.matrix());
}
+void TransformDisplayItem::ProcessForBounds(
+ DisplayItemListBoundsCalculator* calculator) const {
+ calculator->AddStartingDisplayItem();
+ calculator->Save();
+ calculator->matrix()->postConcat(transform_.matrix());
+}
+
void TransformDisplayItem::AsValueInto(
base::trace_event::TracedValue* array) const {
array->AppendString(base::StringPrintf("TransformDisplayItem transform: [%s]",
@@ -53,6 +60,12 @@ void EndTransformDisplayItem::Raster(
canvas->restore();
}
+void EndTransformDisplayItem::ProcessForBounds(
+ DisplayItemListBoundsCalculator* calculator) const {
+ calculator->Restore();
+ calculator->AddEndingDisplayItem();
+}
+
void EndTransformDisplayItem::AsValueInto(
base::trace_event::TracedValue* array) const {
array->AppendString("EndTransformDisplayItem");
diff --git a/chromium/cc/playback/transform_display_item.h b/chromium/cc/playback/transform_display_item.h
index 9d3f9c6da46..1bd69cca3f2 100644
--- a/chromium/cc/playback/transform_display_item.h
+++ b/chromium/cc/playback/transform_display_item.h
@@ -25,6 +25,8 @@ class CC_EXPORT TransformDisplayItem : public DisplayItem {
const gfx::Rect& canvas_target_playback_rect,
SkPicture::AbortCallback* callback) const override;
void AsValueInto(base::trace_event::TracedValue* array) const override;
+ void ProcessForBounds(
+ DisplayItemListBoundsCalculator* calculator) const override;
private:
gfx::Transform transform_;
@@ -43,6 +45,8 @@ class CC_EXPORT EndTransformDisplayItem : public DisplayItem {
const gfx::Rect& canvas_target_playback_rect,
SkPicture::AbortCallback* callback) const override;
void AsValueInto(base::trace_event::TracedValue* array) const override;
+ void ProcessForBounds(
+ DisplayItemListBoundsCalculator* calculator) const override;
};
} // namespace cc
diff --git a/chromium/cc/quads/checkerboard_draw_quad.cc b/chromium/cc/quads/checkerboard_draw_quad.cc
deleted file mode 100644
index 4cd3c2aa18b..00000000000
--- a/chromium/cc/quads/checkerboard_draw_quad.cc
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cc/quads/checkerboard_draw_quad.h"
-
-#include "base/logging.h"
-#include "base/trace_event/trace_event_argument.h"
-#include "base/values.h"
-
-namespace cc {
-
-CheckerboardDrawQuad::CheckerboardDrawQuad() : color(0), scale(0.f) {
-}
-
-void CheckerboardDrawQuad::SetNew(const SharedQuadState* shared_quad_state,
- const gfx::Rect& rect,
- const gfx::Rect& visible_rect,
- SkColor color,
- float scale) {
- gfx::Rect opaque_rect = SkColorGetA(color) == 255 ? rect : gfx::Rect();
- bool needs_blending = false;
- DrawQuad::SetAll(shared_quad_state, DrawQuad::CHECKERBOARD, rect, opaque_rect,
- visible_rect, needs_blending);
- this->color = color;
- this->scale = scale;
-}
-
-void CheckerboardDrawQuad::SetAll(const SharedQuadState* shared_quad_state,
- const gfx::Rect& rect,
- const gfx::Rect& opaque_rect,
- const gfx::Rect& visible_rect,
- bool needs_blending,
- SkColor color,
- float scale) {
- DrawQuad::SetAll(shared_quad_state, DrawQuad::CHECKERBOARD, rect, opaque_rect,
- visible_rect, needs_blending);
- this->color = color;
- this->scale = scale;
-}
-
-const CheckerboardDrawQuad* CheckerboardDrawQuad::MaterialCast(
- const DrawQuad* quad) {
- DCHECK(quad->material == DrawQuad::CHECKERBOARD);
- return static_cast<const CheckerboardDrawQuad*>(quad);
-}
-
-void CheckerboardDrawQuad::ExtendValue(
- base::trace_event::TracedValue* value) const {
- value->SetInteger("color", color);
- value->SetDouble("scale", scale);
-}
-
-} // namespace cc
diff --git a/chromium/cc/quads/checkerboard_draw_quad.h b/chromium/cc/quads/checkerboard_draw_quad.h
deleted file mode 100644
index fe793675a27..00000000000
--- a/chromium/cc/quads/checkerboard_draw_quad.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CC_QUADS_CHECKERBOARD_DRAW_QUAD_H_
-#define CC_QUADS_CHECKERBOARD_DRAW_QUAD_H_
-
-#include "base/memory/scoped_ptr.h"
-#include "cc/base/cc_export.h"
-#include "cc/quads/draw_quad.h"
-#include "third_party/skia/include/core/SkColor.h"
-
-namespace cc {
-
-class CC_EXPORT CheckerboardDrawQuad : public DrawQuad {
- public:
- CheckerboardDrawQuad();
-
- void SetNew(const SharedQuadState* shared_quad_state,
- const gfx::Rect& rect,
- const gfx::Rect& visible_rect,
- SkColor color,
- float scale);
-
- void SetAll(const SharedQuadState* shared_quad_state,
- const gfx::Rect& rect,
- const gfx::Rect& opaque_rect,
- const gfx::Rect& visible_rect,
- bool needs_blending,
- SkColor color,
- float scale);
-
- SkColor color;
- float scale;
-
- static const CheckerboardDrawQuad* MaterialCast(const DrawQuad*);
-
- private:
- void ExtendValue(base::trace_event::TracedValue* value) const override;
-};
-
-} // namespace cc
-
-#endif // CC_QUADS_CHECKERBOARD_DRAW_QUAD_H_
diff --git a/chromium/cc/quads/content_draw_quad_base.h b/chromium/cc/quads/content_draw_quad_base.h
index f80e06c2fcf..da8a472f008 100644
--- a/chromium/cc/quads/content_draw_quad_base.h
+++ b/chromium/cc/quads/content_draw_quad_base.h
@@ -8,9 +8,13 @@
#include "base/memory/scoped_ptr.h"
#include "cc/base/cc_export.h"
#include "cc/quads/draw_quad.h"
-#include "ui/gfx/geometry/point.h"
+#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/geometry/size.h"
+namespace gfx {
+class Rect;
+}
+
namespace cc {
class CC_EXPORT ContentDrawQuadBase : public DrawQuad {
diff --git a/chromium/cc/quads/draw_quad.cc b/chromium/cc/quads/draw_quad.cc
index 606d7ab6058..f9bf6fc5874 100644
--- a/chromium/cc/quads/draw_quad.cc
+++ b/chromium/cc/quads/draw_quad.cc
@@ -9,7 +9,6 @@
#include "base/values.h"
#include "cc/base/math_util.h"
#include "cc/debug/traced_value.h"
-#include "cc/quads/checkerboard_draw_quad.h"
#include "cc/quads/debug_border_draw_quad.h"
#include "cc/quads/io_surface_draw_quad.h"
#include "cc/quads/picture_draw_quad.h"
@@ -64,7 +63,7 @@ void DrawQuad::AsValueInto(base::trace_event::TracedValue* value) const {
bool rect_is_clipped;
gfx::QuadF rect_as_target_space_quad =
MathUtil::MapQuad(shared_quad_state->quad_to_target_transform,
- gfx::QuadF(rect), &rect_is_clipped);
+ gfx::QuadF(gfx::RectF(rect)), &rect_is_clipped);
MathUtil::AddToTracedValue("rect_as_target_space_quad",
rect_as_target_space_quad, value);
@@ -73,9 +72,9 @@ void DrawQuad::AsValueInto(base::trace_event::TracedValue* value) const {
MathUtil::AddToTracedValue("content_space_opaque_rect", opaque_rect, value);
bool opaque_rect_is_clipped;
- gfx::QuadF opaque_rect_as_target_space_quad =
- MathUtil::MapQuad(shared_quad_state->quad_to_target_transform,
- gfx::QuadF(opaque_rect), &opaque_rect_is_clipped);
+ gfx::QuadF opaque_rect_as_target_space_quad = MathUtil::MapQuad(
+ shared_quad_state->quad_to_target_transform,
+ gfx::QuadF(gfx::RectF(opaque_rect)), &opaque_rect_is_clipped);
MathUtil::AddToTracedValue("opaque_rect_as_target_space_quad",
opaque_rect_as_target_space_quad, value);
@@ -84,9 +83,9 @@ void DrawQuad::AsValueInto(base::trace_event::TracedValue* value) const {
MathUtil::AddToTracedValue("content_space_visible_rect", visible_rect, value);
bool visible_rect_is_clipped;
- gfx::QuadF visible_rect_as_target_space_quad =
- MathUtil::MapQuad(shared_quad_state->quad_to_target_transform,
- gfx::QuadF(visible_rect), &visible_rect_is_clipped);
+ gfx::QuadF visible_rect_as_target_space_quad = MathUtil::MapQuad(
+ shared_quad_state->quad_to_target_transform,
+ gfx::QuadF(gfx::RectF(visible_rect)), &visible_rect_is_clipped);
MathUtil::AddToTracedValue("visible_rect_as_target_space_quad",
visible_rect_as_target_space_quad, value);
diff --git a/chromium/cc/quads/draw_quad.h b/chromium/cc/quads/draw_quad.h
index df3bc1213f5..10b0e40d0f0 100644
--- a/chromium/cc/quads/draw_quad.h
+++ b/chromium/cc/quads/draw_quad.h
@@ -35,7 +35,6 @@ class CC_EXPORT DrawQuad {
public:
enum Material {
INVALID,
- CHECKERBOARD,
DEBUG_BORDER,
IO_SURFACE_CONTENT,
PICTURE_CONTENT,
diff --git a/chromium/cc/quads/draw_quad_unittest.cc b/chromium/cc/quads/draw_quad_unittest.cc
index 833f388aafb..a1d1a9042f7 100644
--- a/chromium/cc/quads/draw_quad_unittest.cc
+++ b/chromium/cc/quads/draw_quad_unittest.cc
@@ -10,7 +10,6 @@
#include "base/compiler_specific.h"
#include "cc/base/math_util.h"
#include "cc/output/filter_operations.h"
-#include "cc/quads/checkerboard_draw_quad.h"
#include "cc/quads/debug_border_draw_quad.h"
#include "cc/quads/io_surface_draw_quad.h"
#include "cc/quads/largest_draw_quad.h"
@@ -23,7 +22,7 @@
#include "cc/quads/texture_draw_quad.h"
#include "cc/quads/tile_draw_quad.h"
#include "cc/quads/yuv_video_draw_quad.h"
-#include "cc/test/fake_picture_pile_impl.h"
+#include "cc/test/fake_display_list_raster_source.h"
#include "cc/test/geometry_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/effects/SkBlurImageFilter.h"
@@ -361,24 +360,6 @@ void CompareDrawQuad(DrawQuad* quad,
} \
SETUP_AND_COPY_QUAD_NEW_RP(Type, quad_new, copy_a);
-TEST(DrawQuadTest, CopyCheckerboardDrawQuad) {
- gfx::Rect visible_rect(40, 50, 30, 20);
- SkColor color = 0xfabb0011;
- float scale = 2.3f;
- CREATE_SHARED_STATE();
-
- CREATE_QUAD_3_NEW(CheckerboardDrawQuad, visible_rect, color, scale);
- EXPECT_EQ(DrawQuad::CHECKERBOARD, copy_quad->material);
- EXPECT_EQ(visible_rect, copy_quad->visible_rect);
- EXPECT_EQ(color, copy_quad->color);
- EXPECT_EQ(scale, copy_quad->scale);
-
- CREATE_QUAD_2_ALL(CheckerboardDrawQuad, color, scale);
- EXPECT_EQ(DrawQuad::CHECKERBOARD, copy_quad->material);
- EXPECT_EQ(color, copy_quad->color);
- EXPECT_EQ(scale, copy_quad->scale);
-}
-
TEST(DrawQuadTest, CopyDebugBorderDrawQuad) {
gfx::Rect visible_rect(40, 50, 30, 20);
SkColor color = 0xfabb0011;
@@ -403,26 +384,34 @@ TEST(DrawQuadTest, CopyIOSurfaceDrawQuad) {
gfx::Size size(58, 95);
ResourceId resource_id = 72;
IOSurfaceDrawQuad::Orientation orientation = IOSurfaceDrawQuad::UNFLIPPED;
+ bool allow_overlay = true;
CREATE_SHARED_STATE();
- CREATE_QUAD_5_NEW(IOSurfaceDrawQuad,
+ CREATE_QUAD_6_NEW(IOSurfaceDrawQuad,
opaque_rect,
visible_rect,
size,
resource_id,
- orientation);
+ orientation,
+ allow_overlay);
EXPECT_EQ(DrawQuad::IO_SURFACE_CONTENT, copy_quad->material);
EXPECT_EQ(visible_rect, copy_quad->visible_rect);
EXPECT_EQ(opaque_rect, copy_quad->opaque_rect);
EXPECT_EQ(size, copy_quad->io_surface_size);
EXPECT_EQ(resource_id, copy_quad->io_surface_resource_id());
EXPECT_EQ(orientation, copy_quad->orientation);
+ EXPECT_EQ(allow_overlay, copy_quad->allow_overlay);
- CREATE_QUAD_3_ALL(IOSurfaceDrawQuad, size, resource_id, orientation);
+ CREATE_QUAD_4_ALL(IOSurfaceDrawQuad,
+ size,
+ resource_id,
+ orientation,
+ allow_overlay);
EXPECT_EQ(DrawQuad::IO_SURFACE_CONTENT, copy_quad->material);
EXPECT_EQ(size, copy_quad->io_surface_size);
EXPECT_EQ(resource_id, copy_quad->io_surface_resource_id());
EXPECT_EQ(orientation, copy_quad->orientation);
+ EXPECT_EQ(allow_overlay, copy_quad->allow_overlay);
}
TEST(DrawQuadTest, CopyRenderPassDrawQuad) {
@@ -695,8 +684,7 @@ TEST(DrawQuadTest, CopyPictureDrawQuad) {
gfx::Rect content_rect(30, 40, 20, 30);
float contents_scale = 3.141592f;
scoped_refptr<RasterSource> raster_source =
- FakePicturePileImpl::CreateEmptyPile(gfx::Size(100, 100),
- gfx::Size(100, 100));
+ FakeDisplayListRasterSource::CreateEmpty(gfx::Size(100, 100));
CREATE_SHARED_STATE();
CREATE_QUAD_9_NEW(PictureDrawQuad, opaque_rect, visible_rect, tex_coord_rect,
@@ -741,16 +729,6 @@ class DrawQuadIteratorTest : public testing::Test {
int num_resources_;
};
-TEST_F(DrawQuadIteratorTest, CheckerboardDrawQuad) {
- gfx::Rect visible_rect(40, 50, 30, 20);
- SkColor color = 0xfabb0011;
- float scale = 3.2f;
-
- CREATE_SHARED_STATE();
- CREATE_QUAD_3_NEW(CheckerboardDrawQuad, visible_rect, color, scale);
- EXPECT_EQ(0, IterateAndCount(quad_new));
-}
-
TEST_F(DrawQuadIteratorTest, DebugBorderDrawQuad) {
gfx::Rect visible_rect(40, 50, 30, 20);
SkColor color = 0xfabb0011;
@@ -767,17 +745,20 @@ TEST_F(DrawQuadIteratorTest, IOSurfaceDrawQuad) {
gfx::Size size(58, 95);
ResourceId resource_id = 72;
IOSurfaceDrawQuad::Orientation orientation = IOSurfaceDrawQuad::UNFLIPPED;
+ bool allow_overlay = true;
CREATE_SHARED_STATE();
- CREATE_QUAD_5_NEW(IOSurfaceDrawQuad,
+ CREATE_QUAD_6_NEW(IOSurfaceDrawQuad,
opaque_rect,
visible_rect,
size,
resource_id,
- orientation);
+ orientation,
+ allow_overlay);
EXPECT_EQ(resource_id, quad_new->io_surface_resource_id());
EXPECT_EQ(1, IterateAndCount(quad_new));
EXPECT_EQ(resource_id + 1, quad_new->io_surface_resource_id());
+ EXPECT_EQ(allow_overlay, copy_quad->allow_overlay);
}
TEST_F(DrawQuadIteratorTest, RenderPassDrawQuad) {
@@ -950,8 +931,7 @@ TEST_F(DrawQuadIteratorTest, DISABLED_PictureDrawQuad) {
gfx::Rect content_rect(30, 40, 20, 30);
float contents_scale = 3.141592f;
scoped_refptr<RasterSource> raster_source =
- FakePicturePileImpl::CreateEmptyPile(gfx::Size(100, 100),
- gfx::Size(100, 100));
+ FakeDisplayListRasterSource::CreateEmpty(gfx::Size(100, 100));
CREATE_SHARED_STATE();
CREATE_QUAD_9_NEW(PictureDrawQuad, opaque_rect, visible_rect, tex_coord_rect,
@@ -965,9 +945,6 @@ TEST(DrawQuadTest, LargestQuadType) {
for (int i = 0; i <= DrawQuad::MATERIAL_LAST; ++i) {
switch (static_cast<DrawQuad::Material>(i)) {
- case DrawQuad::CHECKERBOARD:
- largest = std::max(largest, sizeof(CheckerboardDrawQuad));
- break;
case DrawQuad::DEBUG_BORDER:
largest = std::max(largest, sizeof(DebugBorderDrawQuad));
break;
@@ -1012,9 +989,6 @@ TEST(DrawQuadTest, LargestQuadType) {
LOG(ERROR) << "kLargestDrawQuad " << LargestDrawQuadSize();
for (int i = 0; i <= DrawQuad::MATERIAL_LAST; ++i) {
switch (static_cast<DrawQuad::Material>(i)) {
- case DrawQuad::CHECKERBOARD:
- LOG(ERROR) << "CheckerboardDrawQuad " << sizeof(CheckerboardDrawQuad);
- break;
case DrawQuad::DEBUG_BORDER:
LOG(ERROR) << "DebugBorderDrawQuad " << sizeof(DebugBorderDrawQuad);
break;
diff --git a/chromium/cc/quads/io_surface_draw_quad.cc b/chromium/cc/quads/io_surface_draw_quad.cc
index 0ad70fcc6b8..32e2ffc42d4 100644
--- a/chromium/cc/quads/io_surface_draw_quad.cc
+++ b/chromium/cc/quads/io_surface_draw_quad.cc
@@ -11,7 +11,8 @@
namespace cc {
-IOSurfaceDrawQuad::IOSurfaceDrawQuad() : orientation(FLIPPED) {
+IOSurfaceDrawQuad::IOSurfaceDrawQuad()
+ : orientation(FLIPPED), allow_overlay(false) {
}
void IOSurfaceDrawQuad::SetNew(const SharedQuadState* shared_quad_state,
@@ -20,7 +21,8 @@ void IOSurfaceDrawQuad::SetNew(const SharedQuadState* shared_quad_state,
const gfx::Rect& visible_rect,
const gfx::Size& io_surface_size,
unsigned io_surface_resource_id,
- Orientation orientation) {
+ Orientation orientation,
+ bool allow_overlay) {
bool needs_blending = false;
DrawQuad::SetAll(shared_quad_state, DrawQuad::IO_SURFACE_CONTENT, rect,
opaque_rect, visible_rect, needs_blending);
@@ -28,6 +30,7 @@ void IOSurfaceDrawQuad::SetNew(const SharedQuadState* shared_quad_state,
resources.ids[kIOSurfaceResourceIdIndex] = io_surface_resource_id;
resources.count = 1;
this->orientation = orientation;
+ this->allow_overlay = allow_overlay;
}
void IOSurfaceDrawQuad::SetAll(const SharedQuadState* shared_quad_state,
@@ -37,13 +40,15 @@ void IOSurfaceDrawQuad::SetAll(const SharedQuadState* shared_quad_state,
bool needs_blending,
const gfx::Size& io_surface_size,
unsigned io_surface_resource_id,
- Orientation orientation) {
+ Orientation orientation,
+ bool allow_overlay) {
DrawQuad::SetAll(shared_quad_state, DrawQuad::IO_SURFACE_CONTENT, rect,
opaque_rect, visible_rect, needs_blending);
this->io_surface_size = io_surface_size;
resources.ids[kIOSurfaceResourceIdIndex] = io_surface_resource_id;
resources.count = 1;
this->orientation = orientation;
+ this->allow_overlay = allow_overlay;
}
const IOSurfaceDrawQuad* IOSurfaceDrawQuad::MaterialCast(
diff --git a/chromium/cc/quads/io_surface_draw_quad.h b/chromium/cc/quads/io_surface_draw_quad.h
index 4a8a072c61c..0374aa9ed1d 100644
--- a/chromium/cc/quads/io_surface_draw_quad.h
+++ b/chromium/cc/quads/io_surface_draw_quad.h
@@ -28,7 +28,8 @@ class CC_EXPORT IOSurfaceDrawQuad : public DrawQuad {
const gfx::Rect& visible_rect,
const gfx::Size& io_surface_size,
unsigned io_surface_resource_id,
- Orientation orientation);
+ Orientation orientation,
+ bool allow_overlay);
void SetAll(const SharedQuadState* shared_quad_state,
const gfx::Rect& rect,
@@ -37,10 +38,12 @@ class CC_EXPORT IOSurfaceDrawQuad : public DrawQuad {
bool needs_blending,
const gfx::Size& io_surface_size,
unsigned io_surface_resource_id,
- Orientation orientation);
+ Orientation orientation,
+ bool allow_overlay);
gfx::Size io_surface_size;
Orientation orientation;
+ bool allow_overlay;
ResourceId io_surface_resource_id() const {
return resources.ids[kIOSurfaceResourceIdIndex];
diff --git a/chromium/cc/quads/largest_draw_quad.cc b/chromium/cc/quads/largest_draw_quad.cc
index 894be0fdbe4..b6526384887 100644
--- a/chromium/cc/quads/largest_draw_quad.cc
+++ b/chromium/cc/quads/largest_draw_quad.cc
@@ -6,7 +6,6 @@
#include <algorithm>
-#include "cc/quads/checkerboard_draw_quad.h"
#include "cc/quads/debug_border_draw_quad.h"
#include "cc/quads/io_surface_draw_quad.h"
#include "cc/quads/picture_draw_quad.h"
@@ -33,9 +32,6 @@ size_t LargestDrawQuadSize() {
// Use compile assert to make sure largest is actually larger than all other
// type of draw quads.
- static_assert(sizeof(CheckerboardDrawQuad) <= kLargestDrawQuadSize,
- "Largest Draw Quad size needs update. CheckerboardDrawQuad is "
- "currently largest.");
static_assert(sizeof(DebugBorderDrawQuad) <= kLargestDrawQuadSize,
"Largest Draw Quad size needs update. DebugBorderDrawQuad is "
"currently largest.");
diff --git a/chromium/cc/quads/render_pass.cc b/chromium/cc/quads/render_pass.cc
index 5c4d98a33c9..dc79bb8baf4 100644
--- a/chromium/cc/quads/render_pass.cc
+++ b/chromium/cc/quads/render_pass.cc
@@ -12,7 +12,6 @@
#include "cc/base/math_util.h"
#include "cc/debug/traced_value.h"
#include "cc/output/copy_output_request.h"
-#include "cc/quads/checkerboard_draw_quad.h"
#include "cc/quads/debug_border_draw_quad.h"
#include "cc/quads/draw_quad.h"
#include "cc/quads/io_surface_draw_quad.h"
@@ -145,7 +144,7 @@ void RenderPass::SetNew(RenderPassId id,
const gfx::Rect& output_rect,
const gfx::Rect& damage_rect,
const gfx::Transform& transform_to_root_target) {
- DCHECK_GT(id.layer_id, 0);
+ DCHECK(id.IsValid());
DCHECK(damage_rect.IsEmpty() || output_rect.Contains(damage_rect))
<< "damage_rect: " << damage_rect.ToString()
<< " output_rect: " << output_rect.ToString();
@@ -164,7 +163,7 @@ void RenderPass::SetAll(RenderPassId id,
const gfx::Rect& damage_rect,
const gfx::Transform& transform_to_root_target,
bool has_transparent_background) {
- DCHECK_GT(id.layer_id, 0);
+ DCHECK(id.IsValid());
this->id = id;
this->output_rect = output_rect;
@@ -226,9 +225,6 @@ DrawQuad* RenderPass::CopyFromAndAppendDrawQuad(
const DrawQuad* quad,
const SharedQuadState* shared_quad_state) {
switch (quad->material) {
- case DrawQuad::CHECKERBOARD:
- CopyFromAndAppendTypedDrawQuad<CheckerboardDrawQuad>(quad);
- break;
case DrawQuad::DEBUG_BORDER:
CopyFromAndAppendTypedDrawQuad<DebugBorderDrawQuad>(quad);
break;
diff --git a/chromium/cc/quads/render_pass_draw_quad.cc b/chromium/cc/quads/render_pass_draw_quad.cc
index 47c976b96bc..a0070d6991f 100644
--- a/chromium/cc/quads/render_pass_draw_quad.cc
+++ b/chromium/cc/quads/render_pass_draw_quad.cc
@@ -28,7 +28,7 @@ void RenderPassDrawQuad::SetNew(const SharedQuadState* shared_quad_state,
const FilterOperations& filters,
const gfx::Vector2dF& filters_scale,
const FilterOperations& background_filters) {
- DCHECK_GT(render_pass_id.layer_id, 0);
+ DCHECK(render_pass_id.IsValid());
gfx::Rect opaque_rect;
bool needs_blending = false;
@@ -58,7 +58,7 @@ void RenderPassDrawQuad::SetAll(const SharedQuadState* shared_quad_state,
const FilterOperations& filters,
const gfx::Vector2dF& filters_scale,
const FilterOperations& background_filters) {
- DCHECK_GT(render_pass_id.layer_id, 0);
+ DCHECK(render_pass_id.IsValid());
DrawQuad::SetAll(shared_quad_state, DrawQuad::RENDER_PASS, rect, opaque_rect,
visible_rect, needs_blending);
diff --git a/chromium/cc/quads/render_pass_id.h b/chromium/cc/quads/render_pass_id.h
index ebf6387e73c..9c36f321dc6 100644
--- a/chromium/cc/quads/render_pass_id.h
+++ b/chromium/cc/quads/render_pass_id.h
@@ -20,6 +20,8 @@ class CC_EXPORT RenderPassId {
RenderPassId(int layer_id, size_t index) : layer_id(layer_id), index(index) {}
void* AsTracingId() const;
+ bool IsValid() const { return layer_id >= 0; }
+
bool operator==(const RenderPassId& other) const {
return layer_id == other.layer_id && index == other.index;
}
diff --git a/chromium/cc/quads/render_pass_unittest.cc b/chromium/cc/quads/render_pass_unittest.cc
index 5ab8c3170c3..dea89cc9248 100644
--- a/chromium/cc/quads/render_pass_unittest.cc
+++ b/chromium/cc/quads/render_pass_unittest.cc
@@ -7,16 +7,13 @@
#include "cc/base/math_util.h"
#include "cc/base/scoped_ptr_vector.h"
#include "cc/output/copy_output_request.h"
-#include "cc/quads/checkerboard_draw_quad.h"
#include "cc/quads/render_pass_draw_quad.h"
+#include "cc/quads/solid_color_draw_quad.h"
#include "cc/test/geometry_test_utils.h"
-#include "cc/test/render_pass_test_common.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/effects/SkBlurImageFilter.h"
#include "ui/gfx/transform.h"
-using cc::TestRenderPass;
-
namespace cc {
namespace {
@@ -73,7 +70,7 @@ TEST(RenderPassTest, CopyShouldBeIdenticalExceptIdAndQuads) {
gfx::Rect damage_rect(56, 123, 19, 43);
bool has_transparent_background = true;
- scoped_ptr<TestRenderPass> pass = TestRenderPass::Create();
+ scoped_ptr<RenderPass> pass = RenderPass::Create();
pass->SetAll(id,
output_rect,
damage_rect,
@@ -92,10 +89,10 @@ TEST(RenderPassTest, CopyShouldBeIdenticalExceptIdAndQuads) {
SkXfermode::kSrcOver_Mode,
0);
- CheckerboardDrawQuad* checkerboard_quad =
- pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
- checkerboard_quad->SetNew(pass->shared_quad_state_list.back(), gfx::Rect(),
- gfx::Rect(), SkColor(), 1.f);
+ SolidColorDrawQuad* color_quad =
+ pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
+ color_quad->SetNew(pass->shared_quad_state_list.back(), gfx::Rect(),
+ gfx::Rect(), SkColor(), false);
RenderPassId new_id(63, 4);
@@ -125,7 +122,7 @@ TEST(RenderPassTest, CopyAllShouldBeIdentical) {
gfx::Rect damage_rect(56, 123, 19, 43);
bool has_transparent_background = true;
- scoped_ptr<TestRenderPass> pass = TestRenderPass::Create();
+ scoped_ptr<RenderPass> pass = RenderPass::Create();
pass->SetAll(id,
output_rect,
damage_rect,
@@ -143,17 +140,17 @@ TEST(RenderPassTest, CopyAllShouldBeIdentical) {
SkXfermode::kSrcOver_Mode,
0);
- CheckerboardDrawQuad* checkerboard_quad1 =
- pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
- checkerboard_quad1->SetNew(pass->shared_quad_state_list.back(),
- gfx::Rect(1, 1, 1, 1), gfx::Rect(1, 1, 1, 1),
- SkColor(), 1.f);
+ SolidColorDrawQuad* color_quad1 =
+ pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
+ color_quad1->SetNew(pass->shared_quad_state_list.back(),
+ gfx::Rect(1, 1, 1, 1), gfx::Rect(1, 1, 1, 1), SkColor(),
+ false);
- CheckerboardDrawQuad* checkerboard_quad2 =
- pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
- checkerboard_quad2->SetNew(pass->shared_quad_state_list.back(),
- gfx::Rect(2, 2, 2, 2), gfx::Rect(2, 2, 2, 2),
- SkColor(), 1.f);
+ SolidColorDrawQuad* color_quad2 =
+ pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
+ color_quad2->SetNew(pass->shared_quad_state_list.back(),
+ gfx::Rect(2, 2, 2, 2), gfx::Rect(2, 2, 2, 2), SkColor(),
+ false);
// And two quads using another shared state.
SharedQuadState* shared_state2 = pass->CreateAndAppendSharedQuadState();
@@ -166,17 +163,17 @@ TEST(RenderPassTest, CopyAllShouldBeIdentical) {
SkXfermode::kSrcOver_Mode,
0);
- CheckerboardDrawQuad* checkerboard_quad3 =
- pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
- checkerboard_quad3->SetNew(pass->shared_quad_state_list.back(),
- gfx::Rect(3, 3, 3, 3), gfx::Rect(3, 3, 3, 3),
- SkColor(), 1.f);
+ SolidColorDrawQuad* color_quad3 =
+ pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
+ color_quad3->SetNew(pass->shared_quad_state_list.back(),
+ gfx::Rect(3, 3, 3, 3), gfx::Rect(3, 3, 3, 3), SkColor(),
+ false);
- CheckerboardDrawQuad* checkerboard_quad4 =
- pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
- checkerboard_quad4->SetNew(pass->shared_quad_state_list.back(),
- gfx::Rect(4, 4, 4, 4), gfx::Rect(4, 4, 4, 4),
- SkColor(), 1.f);
+ SolidColorDrawQuad* color_quad4 =
+ pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
+ color_quad4->SetNew(pass->shared_quad_state_list.back(),
+ gfx::Rect(4, 4, 4, 4), gfx::Rect(4, 4, 4, 4), SkColor(),
+ false);
// A second render pass with a quad.
RenderPassId contrib_id(4, 1);
@@ -186,7 +183,7 @@ TEST(RenderPassTest, CopyAllShouldBeIdentical) {
gfx::Rect contrib_damage_rect(11, 16, 10, 15);
bool contrib_has_transparent_background = true;
- scoped_ptr<TestRenderPass> contrib = TestRenderPass::Create();
+ scoped_ptr<RenderPass> contrib = RenderPass::Create();
contrib->SetAll(contrib_id,
contrib_output_rect,
contrib_damage_rect,
@@ -204,11 +201,11 @@ TEST(RenderPassTest, CopyAllShouldBeIdentical) {
SkXfermode::kSrcOver_Mode,
0);
- CheckerboardDrawQuad* contrib_quad =
- contrib->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
+ SolidColorDrawQuad* contrib_quad =
+ contrib->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
contrib_quad->SetNew(contrib->shared_quad_state_list.back(),
gfx::Rect(3, 3, 3, 3), gfx::Rect(3, 3, 3, 3), SkColor(),
- 1.f);
+ false);
// And a RenderPassDrawQuad for the contributing pass.
scoped_ptr<RenderPassDrawQuad> pass_quad =
@@ -244,7 +241,7 @@ TEST(RenderPassTest, CopyAllWithCulledQuads) {
gfx::Rect damage_rect(56, 123, 19, 43);
bool has_transparent_background = true;
- scoped_ptr<TestRenderPass> pass = TestRenderPass::Create();
+ scoped_ptr<RenderPass> pass = RenderPass::Create();
pass->SetAll(id,
output_rect,
damage_rect,
@@ -262,11 +259,11 @@ TEST(RenderPassTest, CopyAllWithCulledQuads) {
SkXfermode::kSrcOver_Mode,
0);
- CheckerboardDrawQuad* checkerboard_quad1 =
- pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
- checkerboard_quad1->SetNew(pass->shared_quad_state_list.back(),
- gfx::Rect(1, 1, 1, 1), gfx::Rect(1, 1, 1, 1),
- SkColor(), 1.f);
+ SolidColorDrawQuad* color_quad1 =
+ pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
+ color_quad1->SetNew(pass->shared_quad_state_list.back(),
+ gfx::Rect(1, 1, 1, 1), gfx::Rect(1, 1, 1, 1), SkColor(),
+ false);
// A shared state with no quads, they were culled.
SharedQuadState* shared_state2 = pass->CreateAndAppendSharedQuadState();
@@ -301,11 +298,11 @@ TEST(RenderPassTest, CopyAllWithCulledQuads) {
SkXfermode::kSrcOver_Mode,
0);
- CheckerboardDrawQuad* checkerboard_quad2 =
- pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
- checkerboard_quad2->SetNew(pass->shared_quad_state_list.back(),
- gfx::Rect(3, 3, 3, 3), gfx::Rect(3, 3, 3, 3),
- SkColor(), 1.f);
+ SolidColorDrawQuad* color_quad2 =
+ pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
+ color_quad2->SetNew(pass->shared_quad_state_list.back(),
+ gfx::Rect(3, 3, 3, 3), gfx::Rect(3, 3, 3, 3), SkColor(),
+ false);
pass_list.push_back(pass.Pass());
diff --git a/chromium/cc/quads/yuv_video_draw_quad.h b/chromium/cc/quads/yuv_video_draw_quad.h
index 53ef5710d20..3dfd85bb88b 100644
--- a/chromium/cc/quads/yuv_video_draw_quad.h
+++ b/chromium/cc/quads/yuv_video_draw_quad.h
@@ -9,6 +9,8 @@
#include "base/memory/scoped_ptr.h"
#include "cc/base/cc_export.h"
#include "cc/quads/draw_quad.h"
+#include "ui/gfx/geometry/rect_f.h"
+#include "ui/gfx/geometry/size.h"
namespace cc {
diff --git a/chromium/cc/raster/bitmap_tile_task_worker_pool.cc b/chromium/cc/raster/bitmap_tile_task_worker_pool.cc
index bd6af35215c..034ad0f087b 100644
--- a/chromium/cc/raster/bitmap_tile_task_worker_pool.cc
+++ b/chromium/cc/raster/bitmap_tile_task_worker_pool.cc
@@ -35,7 +35,8 @@ class RasterBufferImpl : public RasterBuffer {
const gfx::Rect& raster_full_rect,
const gfx::Rect& raster_dirty_rect,
uint64_t new_content_id,
- float scale) override {
+ float scale,
+ bool include_images) override {
gfx::Rect playback_rect = raster_full_rect;
if (resource_has_previous_content_) {
playback_rect.Intersect(raster_dirty_rect);
@@ -46,7 +47,8 @@ class RasterBufferImpl : public RasterBuffer {
size_t stride = 0u;
TileTaskWorkerPool::PlaybackToMemory(
lock_.sk_bitmap().getPixels(), resource_->format(), resource_->size(),
- stride, raster_source, raster_full_rect, playback_rect, scale);
+ stride, raster_source, raster_full_rect, playback_rect, scale,
+ include_images);
}
private:
@@ -173,18 +175,19 @@ void BitmapTileTaskWorkerPool::CheckForCompletedTasks() {
task->WillComplete();
task->CompleteOnOriginThread(this);
task->DidComplete();
-
- task->RunReplyOnOriginThread();
}
completed_tasks_.clear();
}
-ResourceFormat BitmapTileTaskWorkerPool::GetResourceFormat() const {
+ResourceFormat BitmapTileTaskWorkerPool::GetResourceFormat(
+ bool must_support_alpha) const {
return resource_provider_->best_texture_format();
}
-bool BitmapTileTaskWorkerPool::GetResourceRequiresSwizzle() const {
- return !PlatformColor::SameComponentOrder(GetResourceFormat());
+bool BitmapTileTaskWorkerPool::GetResourceRequiresSwizzle(
+ bool must_support_alpha) const {
+ return !PlatformColor::SameComponentOrder(
+ GetResourceFormat(must_support_alpha));
}
scoped_ptr<RasterBuffer> BitmapTileTaskWorkerPool::AcquireBufferForRaster(
diff --git a/chromium/cc/raster/bitmap_tile_task_worker_pool.h b/chromium/cc/raster/bitmap_tile_task_worker_pool.h
index 3df206a09bd..fe9c4e81087 100644
--- a/chromium/cc/raster/bitmap_tile_task_worker_pool.h
+++ b/chromium/cc/raster/bitmap_tile_task_worker_pool.h
@@ -38,8 +38,8 @@ class CC_EXPORT BitmapTileTaskWorkerPool : public TileTaskWorkerPool,
void Shutdown() override;
void ScheduleTasks(TileTaskQueue* queue) override;
void CheckForCompletedTasks() override;
- ResourceFormat GetResourceFormat() const override;
- bool GetResourceRequiresSwizzle() const override;
+ ResourceFormat GetResourceFormat(bool must_support_alpha) const override;
+ bool GetResourceRequiresSwizzle(bool must_support_alpha) const override;
// Overridden from TileTaskClient:
scoped_ptr<RasterBuffer> AcquireBufferForRaster(
diff --git a/chromium/cc/raster/gpu_tile_task_worker_pool.cc b/chromium/cc/raster/gpu_tile_task_worker_pool.cc
index 7c21177d527..e8dc102752f 100644
--- a/chromium/cc/raster/gpu_tile_task_worker_pool.cc
+++ b/chromium/cc/raster/gpu_tile_task_worker_pool.cc
@@ -38,18 +38,17 @@ class RasterBufferImpl : public RasterBuffer {
const gfx::Rect& raster_full_rect,
const gfx::Rect& raster_dirty_rect,
uint64_t new_content_id,
- float scale) override {
+ float scale,
+ bool include_images) override {
TRACE_EVENT0("cc", "RasterBufferImpl::Playback");
+ // GPU raster doesn't do low res tiles, so should always include images.
+ DCHECK(include_images);
ContextProvider* context_provider = rasterizer_->resource_provider()
->output_surface()
->worker_context_provider();
+ DCHECK(context_provider);
- // The context lock must be held while accessing the context on a
- // worker thread.
- base::AutoLock context_lock(*context_provider->GetLock());
-
- // Allow this worker thread to bind to context_provider.
- context_provider->DetachFromThread();
+ ContextProvider::ScopedContextLock scoped_context(context_provider);
gfx::Rect playback_rect = raster_full_rect;
if (resource_has_previous_content_) {
@@ -64,10 +63,7 @@ class RasterBufferImpl : public RasterBuffer {
playback_rect, scale);
// Barrier to sync worker context output to cc context.
- context_provider->ContextGL()->OrderingBarrierCHROMIUM();
-
- // Allow compositor thread to bind to context_provider.
- context_provider->DetachFromThread();
+ scoped_context.ContextGL()->OrderingBarrierCHROMIUM();
}
private:
@@ -205,24 +201,24 @@ void GpuTileTaskWorkerPool::CheckForCompletedTasks() {
completed_tasks_.clear();
}
-ResourceFormat GpuTileTaskWorkerPool::GetResourceFormat() const {
+ResourceFormat GpuTileTaskWorkerPool::GetResourceFormat(
+ bool must_support_alpha) const {
return rasterizer_->resource_provider()->best_render_buffer_format();
}
-bool GpuTileTaskWorkerPool::GetResourceRequiresSwizzle() const {
+bool GpuTileTaskWorkerPool::GetResourceRequiresSwizzle(
+ bool must_support_alpha) const {
// This doesn't require a swizzle because we rasterize to the correct format.
return false;
}
void GpuTileTaskWorkerPool::CompleteTasks(const Task::Vector& tasks) {
for (auto& task : tasks) {
- RasterTask* raster_task = static_cast<RasterTask*>(task.get());
-
- raster_task->WillComplete();
- raster_task->CompleteOnOriginThread(this);
- raster_task->DidComplete();
+ TileTask* tile_task = static_cast<TileTask*>(task.get());
- raster_task->RunReplyOnOriginThread();
+ tile_task->WillComplete();
+ tile_task->CompleteOnOriginThread(this);
+ tile_task->DidComplete();
}
completed_tasks_.clear();
}
diff --git a/chromium/cc/raster/gpu_tile_task_worker_pool.h b/chromium/cc/raster/gpu_tile_task_worker_pool.h
index 32a9d232550..f9ab24c6fea 100644
--- a/chromium/cc/raster/gpu_tile_task_worker_pool.h
+++ b/chromium/cc/raster/gpu_tile_task_worker_pool.h
@@ -36,8 +36,8 @@ class CC_EXPORT GpuTileTaskWorkerPool : public TileTaskWorkerPool,
void Shutdown() override;
void ScheduleTasks(TileTaskQueue* queue) override;
void CheckForCompletedTasks() override;
- ResourceFormat GetResourceFormat() const override;
- bool GetResourceRequiresSwizzle() const override;
+ ResourceFormat GetResourceFormat(bool must_support_alpha) const override;
+ bool GetResourceRequiresSwizzle(bool must_support_alpha) const override;
// Overridden from TileTaskClient:
scoped_ptr<RasterBuffer> AcquireBufferForRaster(
diff --git a/chromium/cc/raster/one_copy_tile_task_worker_pool.cc b/chromium/cc/raster/one_copy_tile_task_worker_pool.cc
index 78e6b106ce9..86a0561b1ca 100644
--- a/chromium/cc/raster/one_copy_tile_task_worker_pool.cc
+++ b/chromium/cc/raster/one_copy_tile_task_worker_pool.cc
@@ -8,16 +8,21 @@
#include <limits>
#include "base/strings/stringprintf.h"
+#include "base/thread_task_runner_handle.h"
+#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/trace_event_argument.h"
#include "cc/base/math_util.h"
#include "cc/debug/traced_value.h"
#include "cc/raster/raster_buffer.h"
#include "cc/resources/platform_color.h"
-#include "cc/resources/resource_pool.h"
+#include "cc/resources/resource_format.h"
+#include "cc/resources/resource_util.h"
#include "cc/resources/scoped_resource.h"
+#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/gles2_interface.h"
-#include "ui/gfx/gpu_memory_buffer.h"
+#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
+#include "ui/gfx/buffer_format_util.h"
namespace cc {
namespace {
@@ -26,105 +31,140 @@ class RasterBufferImpl : public RasterBuffer {
public:
RasterBufferImpl(OneCopyTileTaskWorkerPool* worker_pool,
ResourceProvider* resource_provider,
- ResourcePool* resource_pool,
ResourceFormat resource_format,
- const Resource* output_resource,
+ const Resource* resource,
uint64_t previous_content_id)
: worker_pool_(worker_pool),
- resource_provider_(resource_provider),
- resource_pool_(resource_pool),
- output_resource_(output_resource),
- raster_content_id_(0),
- sequence_(0) {
- if (worker_pool->have_persistent_gpu_memory_buffers() &&
- previous_content_id) {
- raster_resource_ =
- resource_pool->TryAcquireResourceWithContentId(previous_content_id);
- }
- if (raster_resource_) {
- raster_content_id_ = previous_content_id;
- DCHECK_EQ(resource_format, raster_resource_->format());
- DCHECK_EQ(output_resource->size().ToString(),
- raster_resource_->size().ToString());
- } else {
- raster_resource_ = resource_pool->AcquireResource(output_resource->size(),
- resource_format);
- }
-
- lock_.reset(new ResourceProvider::ScopedWriteLockGpuMemoryBuffer(
- resource_provider_, raster_resource_->id()));
- }
+ resource_(resource),
+ lock_(resource_provider, resource->id()),
+ previous_content_id_(previous_content_id) {}
- ~RasterBufferImpl() override {
- // Release write lock in case a copy was never scheduled.
- lock_.reset();
-
- // Make sure any scheduled copy operations are issued before we release the
- // raster resource.
- if (sequence_)
- worker_pool_->AdvanceLastIssuedCopyTo(sequence_);
-
- // Return resources to pool so they can be used by another RasterBuffer
- // instance.
- resource_pool_->ReleaseResource(raster_resource_.Pass(),
- raster_content_id_);
- }
+ ~RasterBufferImpl() override {}
// Overridden from RasterBuffer:
void Playback(const RasterSource* raster_source,
const gfx::Rect& raster_full_rect,
const gfx::Rect& raster_dirty_rect,
uint64_t new_content_id,
- float scale) override {
- // If there's a raster_content_id_, we are reusing a resource with that
- // content id.
- bool reusing_raster_resource = raster_content_id_ != 0;
- sequence_ = worker_pool_->PlaybackAndScheduleCopyOnWorkerThread(
- reusing_raster_resource, lock_.Pass(), raster_resource_.get(),
- output_resource_, raster_source, raster_full_rect, raster_dirty_rect,
- scale);
- // Store the content id of the resource to return to the pool.
- raster_content_id_ = new_content_id;
+ float scale,
+ bool include_images) override {
+ worker_pool_->PlaybackAndCopyOnWorkerThread(
+ resource_, &lock_, raster_source, raster_full_rect, raster_dirty_rect,
+ scale, include_images, previous_content_id_, new_content_id);
}
private:
OneCopyTileTaskWorkerPool* worker_pool_;
- ResourceProvider* resource_provider_;
- ResourcePool* resource_pool_;
- const Resource* output_resource_;
- uint64_t raster_content_id_;
- scoped_ptr<ScopedResource> raster_resource_;
- scoped_ptr<ResourceProvider::ScopedWriteLockGpuMemoryBuffer> lock_;
- CopySequenceNumber sequence_;
+ const Resource* resource_;
+ ResourceProvider::ScopedWriteLockGL lock_;
+ uint64_t previous_content_id_;
DISALLOW_COPY_AND_ASSIGN(RasterBufferImpl);
};
-// Number of in-flight copy operations to allow.
-const int kMaxCopyOperations = 32;
+// Delay between checking for query result to be available.
+const int kCheckForQueryResultAvailableTickRateMs = 1;
-// Delay been checking for copy operations to complete.
-const int kCheckForCompletedCopyOperationsTickRateMs = 1;
-
-// Number of failed attempts to allow before we perform a check that will
-// wait for copy operations to complete if needed.
-const int kFailedAttemptsBeforeWaitIfNeeded = 256;
+// Number of attempts to allow before we perform a check that will wait for
+// query to complete.
+const int kMaxCheckForQueryResultAvailableAttempts = 256;
// 4MiB is the size of 4 512x512 tiles, which has proven to be a good
// default batch size for copy operations.
const int kMaxBytesPerCopyOperation = 1024 * 1024 * 4;
+// Delay before a staging buffer might be released.
+const int kStagingBufferExpirationDelayMs = 1000;
+
+bool CheckForQueryResult(gpu::gles2::GLES2Interface* gl, unsigned query_id) {
+ unsigned complete = 1;
+ gl->GetQueryObjectuivEXT(query_id, GL_QUERY_RESULT_AVAILABLE_EXT, &complete);
+ return !!complete;
+}
+
+void WaitForQueryResult(gpu::gles2::GLES2Interface* gl, unsigned query_id) {
+ TRACE_EVENT0("cc", "WaitForQueryResult");
+
+ int attempts_left = kMaxCheckForQueryResultAvailableAttempts;
+ while (attempts_left--) {
+ if (CheckForQueryResult(gl, query_id))
+ break;
+
+ base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(
+ kCheckForQueryResultAvailableTickRateMs));
+ }
+
+ unsigned result = 0;
+ gl->GetQueryObjectuivEXT(query_id, GL_QUERY_RESULT_EXT, &result);
+}
+
} // namespace
-OneCopyTileTaskWorkerPool::CopyOperation::CopyOperation(
- scoped_ptr<ResourceProvider::ScopedWriteLockGpuMemoryBuffer> src_write_lock,
- const Resource* src,
- const Resource* dst,
- const gfx::Rect& rect)
- : src_write_lock(src_write_lock.Pass()), src(src), dst(dst), rect(rect) {
+OneCopyTileTaskWorkerPool::StagingBuffer::StagingBuffer(const gfx::Size& size,
+ ResourceFormat format)
+ : size(size),
+ format(format),
+ texture_id(0),
+ image_id(0),
+ query_id(0),
+ content_id(0) {}
+
+OneCopyTileTaskWorkerPool::StagingBuffer::~StagingBuffer() {
+ DCHECK_EQ(texture_id, 0u);
+ DCHECK_EQ(image_id, 0u);
+ DCHECK_EQ(query_id, 0u);
+}
+
+void OneCopyTileTaskWorkerPool::StagingBuffer::DestroyGLResources(
+ gpu::gles2::GLES2Interface* gl) {
+ if (query_id) {
+ gl->DeleteQueriesEXT(1, &query_id);
+ query_id = 0;
+ }
+ if (image_id) {
+ gl->DestroyImageCHROMIUM(image_id);
+ image_id = 0;
+ }
+ if (texture_id) {
+ gl->DeleteTextures(1, &texture_id);
+ texture_id = 0;
+ }
}
-OneCopyTileTaskWorkerPool::CopyOperation::~CopyOperation() {
+void OneCopyTileTaskWorkerPool::StagingBuffer::OnMemoryDump(
+ base::trace_event::ProcessMemoryDump* pmd,
+ ResourceFormat format,
+ bool in_free_list) const {
+ if (!gpu_memory_buffer)
+ return;
+
+ gfx::GpuMemoryBufferId buffer_id = gpu_memory_buffer->GetId();
+ std::string buffer_dump_name =
+ base::StringPrintf("cc/one_copy/staging_memory/buffer_%d", buffer_id.id);
+ base::trace_event::MemoryAllocatorDump* buffer_dump =
+ pmd->CreateAllocatorDump(buffer_dump_name);
+
+ uint64_t buffer_size_in_bytes =
+ ResourceUtil::UncheckedSizeInBytes<uint64_t>(size, format);
+ buffer_dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+ buffer_size_in_bytes);
+ buffer_dump->AddScalar("free_size",
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+ in_free_list ? buffer_size_in_bytes : 0);
+
+ // Emit an ownership edge towards a global allocator dump node.
+ const uint64 tracing_process_id =
+ base::trace_event::MemoryDumpManager::GetInstance()
+ ->GetTracingProcessId();
+ base::trace_event::MemoryAllocatorDumpGuid shared_buffer_guid =
+ gfx::GetGpuMemoryBufferGUIDForTracing(tracing_process_id, buffer_id);
+ pmd->CreateSharedGlobalAllocatorDump(shared_buffer_guid);
+
+ // By creating an edge with a higher |importance| (w.r.t. browser-side dumps)
+ // the tracing UI will account the effective size of the buffer to the child.
+ const int kImportance = 2;
+ pmd->AddOwnershipEdge(buffer_dump->guid(), shared_buffer_guid, kImportance);
}
// static
@@ -133,51 +173,54 @@ scoped_ptr<TileTaskWorkerPool> OneCopyTileTaskWorkerPool::Create(
TaskGraphRunner* task_graph_runner,
ContextProvider* context_provider,
ResourceProvider* resource_provider,
- ResourcePool* resource_pool,
int max_copy_texture_chromium_size,
- bool have_persistent_gpu_memory_buffers) {
+ bool use_persistent_gpu_memory_buffers,
+ int max_staging_buffer_usage_in_bytes,
+ bool use_rgba_4444_texture_format) {
return make_scoped_ptr<TileTaskWorkerPool>(new OneCopyTileTaskWorkerPool(
- task_runner, task_graph_runner, context_provider, resource_provider,
- resource_pool, max_copy_texture_chromium_size,
- have_persistent_gpu_memory_buffers));
+ task_runner, task_graph_runner, resource_provider,
+ max_copy_texture_chromium_size, use_persistent_gpu_memory_buffers,
+ max_staging_buffer_usage_in_bytes, use_rgba_4444_texture_format));
}
OneCopyTileTaskWorkerPool::OneCopyTileTaskWorkerPool(
base::SequencedTaskRunner* task_runner,
TaskGraphRunner* task_graph_runner,
- ContextProvider* context_provider,
ResourceProvider* resource_provider,
- ResourcePool* resource_pool,
int max_copy_texture_chromium_size,
- bool have_persistent_gpu_memory_buffers)
+ bool use_persistent_gpu_memory_buffers,
+ int max_staging_buffer_usage_in_bytes,
+ bool use_rgba_4444_texture_format)
: task_runner_(task_runner),
task_graph_runner_(task_graph_runner),
namespace_token_(task_graph_runner->GetNamespaceToken()),
- context_provider_(context_provider),
resource_provider_(resource_provider),
- resource_pool_(resource_pool),
max_bytes_per_copy_operation_(
max_copy_texture_chromium_size
? std::min(kMaxBytesPerCopyOperation,
max_copy_texture_chromium_size)
: kMaxBytesPerCopyOperation),
- have_persistent_gpu_memory_buffers_(have_persistent_gpu_memory_buffers),
- last_issued_copy_operation_(0),
- last_flushed_copy_operation_(0),
- lock_(),
- copy_operation_count_cv_(&lock_),
+ use_persistent_gpu_memory_buffers_(use_persistent_gpu_memory_buffers),
bytes_scheduled_since_last_flush_(0),
- issued_copy_operation_count_(0),
- next_copy_operation_sequence_(1),
- check_for_completed_copy_operations_pending_(false),
- shutdown_(false),
+ max_staging_buffer_usage_in_bytes_(max_staging_buffer_usage_in_bytes),
+ use_rgba_4444_texture_format_(use_rgba_4444_texture_format),
+ staging_buffer_usage_in_bytes_(0),
+ free_staging_buffer_usage_in_bytes_(0),
+ staging_buffer_expiration_delay_(
+ base::TimeDelta::FromMilliseconds(kStagingBufferExpirationDelayMs)),
+ reduce_memory_usage_pending_(false),
weak_ptr_factory_(this),
task_set_finished_weak_ptr_factory_(this) {
- DCHECK(context_provider_);
+ base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
+ this, base::ThreadTaskRunnerHandle::Get());
+ reduce_memory_usage_callback_ =
+ base::Bind(&OneCopyTileTaskWorkerPool::ReduceMemoryUsage,
+ weak_ptr_factory_.GetWeakPtr());
}
OneCopyTileTaskWorkerPool::~OneCopyTileTaskWorkerPool() {
- DCHECK_EQ(pending_copy_operations_.size(), 0u);
+ base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
+ this);
}
TileTaskRunner* OneCopyTileTaskWorkerPool::AsTileTaskRunner() {
@@ -191,28 +234,23 @@ void OneCopyTileTaskWorkerPool::SetClient(TileTaskRunnerClient* client) {
void OneCopyTileTaskWorkerPool::Shutdown() {
TRACE_EVENT0("cc", "OneCopyTileTaskWorkerPool::Shutdown");
- {
- base::AutoLock lock(lock_);
-
- shutdown_ = true;
- copy_operation_count_cv_.Signal();
- }
-
TaskGraph empty;
task_graph_runner_->ScheduleTasks(namespace_token_, &empty);
task_graph_runner_->WaitForTasksToFinishRunning(namespace_token_);
+
+ base::AutoLock lock(lock_);
+
+ if (buffers_.empty())
+ return;
+
+ ReleaseBuffersNotUsedSince(base::TimeTicks() + base::TimeDelta::Max());
+ DCHECK_EQ(staging_buffer_usage_in_bytes_, 0);
+ DCHECK_EQ(free_staging_buffer_usage_in_bytes_, 0);
}
void OneCopyTileTaskWorkerPool::ScheduleTasks(TileTaskQueue* queue) {
TRACE_EVENT0("cc", "OneCopyTileTaskWorkerPool::ScheduleTasks");
-#if DCHECK_IS_ON()
- {
- base::AutoLock lock(lock_);
- DCHECK(!shutdown_);
- }
-#endif
-
if (tasks_pending_.none())
TRACE_EVENT_ASYNC_BEGIN0("cc", "ScheduledTasks", this);
@@ -237,8 +275,6 @@ void OneCopyTileTaskWorkerPool::ScheduleTasks(TileTaskQueue* queue) {
task_set_finished_weak_ptr_factory_.GetWeakPtr(), task_set));
}
- resource_pool_->CheckBusyResources(false);
-
for (TileTaskQueue::Item::Vector::const_iterator it = queue->items.begin();
it != queue->items.end(); ++it) {
const TileTaskQueue::Item& item = *it;
@@ -265,14 +301,19 @@ void OneCopyTileTaskWorkerPool::ScheduleTasks(TileTaskQueue* queue) {
}
ScheduleTasksOnOriginThread(this, &graph_);
+
+ // Barrier to sync any new resources to the worker context.
+ resource_provider_->output_surface()
+ ->context_provider()
+ ->ContextGL()
+ ->OrderingBarrierCHROMIUM();
+
task_graph_runner_->ScheduleTasks(namespace_token_, &graph_);
std::copy(new_task_set_finished_tasks,
new_task_set_finished_tasks + kNumberOfTaskSets,
task_set_finished_tasks_);
- resource_pool_->ReduceResourceUsage();
-
TRACE_EVENT_ASYNC_STEP_INTO1("cc", "ScheduledTasks", this, "running", "state",
StateAsValue());
}
@@ -290,18 +331,21 @@ void OneCopyTileTaskWorkerPool::CheckForCompletedTasks() {
task->WillComplete();
task->CompleteOnOriginThread(this);
task->DidComplete();
-
- task->RunReplyOnOriginThread();
}
completed_tasks_.clear();
}
-ResourceFormat OneCopyTileTaskWorkerPool::GetResourceFormat() const {
- return resource_provider_->best_texture_format();
+ResourceFormat OneCopyTileTaskWorkerPool::GetResourceFormat(
+ bool must_support_alpha) const {
+ return use_rgba_4444_texture_format_
+ ? RGBA_4444
+ : resource_provider_->best_texture_format();
}
-bool OneCopyTileTaskWorkerPool::GetResourceRequiresSwizzle() const {
- return !PlatformColor::SameComponentOrder(GetResourceFormat());
+bool OneCopyTileTaskWorkerPool::GetResourceRequiresSwizzle(
+ bool must_support_alpha) const {
+ return !PlatformColor::SameComponentOrder(
+ GetResourceFormat(must_support_alpha));
}
scoped_ptr<RasterBuffer> OneCopyTileTaskWorkerPool::AcquireBufferForRaster(
@@ -310,11 +354,9 @@ scoped_ptr<RasterBuffer> OneCopyTileTaskWorkerPool::AcquireBufferForRaster(
uint64_t previous_content_id) {
// TODO(danakj): If resource_content_id != 0, we only need to copy/upload
// the dirty rect.
- DCHECK_EQ(resource->format(), resource_provider_->best_texture_format());
return make_scoped_ptr<RasterBuffer>(
- new RasterBufferImpl(this, resource_provider_, resource_pool_,
- resource_provider_->best_texture_format(), resource,
- previous_content_id));
+ new RasterBufferImpl(this, resource_provider_, resource->format(),
+ resource, previous_content_id));
}
void OneCopyTileTaskWorkerPool::ReleaseBufferForRaster(
@@ -322,235 +364,429 @@ void OneCopyTileTaskWorkerPool::ReleaseBufferForRaster(
// Nothing to do here. RasterBufferImpl destructor cleans up after itself.
}
-CopySequenceNumber
-OneCopyTileTaskWorkerPool::PlaybackAndScheduleCopyOnWorkerThread(
- bool reusing_raster_resource,
- scoped_ptr<ResourceProvider::ScopedWriteLockGpuMemoryBuffer>
- raster_resource_write_lock,
- const Resource* raster_resource,
- const Resource* output_resource,
+void OneCopyTileTaskWorkerPool::PlaybackAndCopyOnWorkerThread(
+ const Resource* resource,
+ const ResourceProvider::ScopedWriteLockGL* resource_lock,
const RasterSource* raster_source,
const gfx::Rect& raster_full_rect,
const gfx::Rect& raster_dirty_rect,
- float scale) {
- gfx::GpuMemoryBuffer* gpu_memory_buffer =
- raster_resource_write_lock->GetGpuMemoryBuffer();
- if (gpu_memory_buffer) {
- void* data = NULL;
- bool rv = gpu_memory_buffer->Map(&data);
- DCHECK(rv);
- int stride;
- gpu_memory_buffer->GetStride(&stride);
- // TileTaskWorkerPool::PlaybackToMemory only supports unsigned strides.
- DCHECK_GE(stride, 0);
+ float scale,
+ bool include_images,
+ uint64_t previous_content_id,
+ uint64_t new_content_id) {
+ base::AutoLock lock(lock_);
- gfx::Rect playback_rect = raster_full_rect;
- if (reusing_raster_resource) {
- playback_rect.Intersect(raster_dirty_rect);
+ scoped_ptr<StagingBuffer> staging_buffer =
+ AcquireStagingBuffer(resource, previous_content_id);
+ DCHECK(staging_buffer);
+
+ {
+ base::AutoUnlock unlock(lock_);
+
+ // Allocate GpuMemoryBuffer if necessary.
+ if (!staging_buffer->gpu_memory_buffer) {
+ staging_buffer->gpu_memory_buffer =
+ resource_provider_->gpu_memory_buffer_manager()
+ ->AllocateGpuMemoryBuffer(staging_buffer->size,
+ BufferFormat(resource->format()),
+ use_persistent_gpu_memory_buffers_
+ ? gfx::BufferUsage::PERSISTENT_MAP
+ : gfx::BufferUsage::MAP);
+ DCHECK_EQ(gfx::NumberOfPlanesForBufferFormat(
+ staging_buffer->gpu_memory_buffer->GetFormat()),
+ 1u);
}
- DCHECK(!playback_rect.IsEmpty())
- << "Why are we rastering a tile that's not dirty?";
- TileTaskWorkerPool::PlaybackToMemory(
- data, raster_resource->format(), raster_resource->size(),
- static_cast<size_t>(stride), raster_source, raster_full_rect,
- playback_rect, scale);
- gpu_memory_buffer->Unmap();
- }
- base::AutoLock lock(lock_);
+ gfx::Rect playback_rect = raster_full_rect;
+ if (use_persistent_gpu_memory_buffers_ && previous_content_id) {
+ // Reduce playback rect to dirty region if the content id of the staging
+ // buffer matches the prevous content id.
+ if (previous_content_id == staging_buffer->content_id)
+ playback_rect.Intersect(raster_dirty_rect);
+ }
- CopySequenceNumber sequence = 0;
- int bytes_per_row = (BitsPerPixel(raster_resource->format()) *
- raster_resource->size().width()) /
- 8;
- int chunk_size_in_rows =
- std::max(1, max_bytes_per_copy_operation_ / bytes_per_row);
- // Align chunk size to 4. Required to support compressed texture formats.
- chunk_size_in_rows = MathUtil::RoundUp(chunk_size_in_rows, 4);
- int y = 0;
- int height = raster_resource->size().height();
- while (y < height) {
- int failed_attempts = 0;
- while ((pending_copy_operations_.size() + issued_copy_operation_count_) >=
- kMaxCopyOperations) {
- // Ignore limit when shutdown is set.
- if (shutdown_)
- break;
+ if (staging_buffer->gpu_memory_buffer) {
+ void* data = nullptr;
+ bool rv = staging_buffer->gpu_memory_buffer->Map(&data);
+ DCHECK(rv);
+ int stride;
+ staging_buffer->gpu_memory_buffer->GetStride(&stride);
+ // TileTaskWorkerPool::PlaybackToMemory only supports unsigned strides.
+ DCHECK_GE(stride, 0);
+
+ DCHECK(!playback_rect.IsEmpty())
+ << "Why are we rastering a tile that's not dirty?";
+ TileTaskWorkerPool::PlaybackToMemory(
+ data, resource->format(), staging_buffer->size,
+ static_cast<size_t>(stride), raster_source, raster_full_rect,
+ playback_rect, scale, include_images);
+ staging_buffer->gpu_memory_buffer->Unmap();
+ staging_buffer->content_id = new_content_id;
+ }
+ }
- ++failed_attempts;
+ ContextProvider* context_provider =
+ resource_provider_->output_surface()->worker_context_provider();
+ DCHECK(context_provider);
- // Schedule a check that will also wait for operations to complete
- // after too many failed attempts.
- bool wait_if_needed = failed_attempts > kFailedAttemptsBeforeWaitIfNeeded;
+ {
+ ContextProvider::ScopedContextLock scoped_context(context_provider);
+
+ gpu::gles2::GLES2Interface* gl = scoped_context.ContextGL();
+ DCHECK(gl);
+
+ unsigned image_target =
+ resource_provider_->GetImageTextureTarget(resource->format());
+
+ // Create and bind staging texture.
+ if (!staging_buffer->texture_id) {
+ gl->GenTextures(1, &staging_buffer->texture_id);
+ gl->BindTexture(image_target, staging_buffer->texture_id);
+ gl->TexParameteri(image_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ gl->TexParameteri(image_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ gl->TexParameteri(image_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ gl->TexParameteri(image_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ } else {
+ gl->BindTexture(image_target, staging_buffer->texture_id);
+ }
- // Schedule a check for completed copy operations if too many operations
- // are currently in-flight.
- ScheduleCheckForCompletedCopyOperationsWithLockAcquired(wait_if_needed);
+ // Create and bind image.
+ if (!staging_buffer->image_id) {
+ if (staging_buffer->gpu_memory_buffer) {
+ staging_buffer->image_id = gl->CreateImageCHROMIUM(
+ staging_buffer->gpu_memory_buffer->AsClientBuffer(),
+ staging_buffer->size.width(), staging_buffer->size.height(),
+ GLInternalFormat(resource->format()));
+ gl->BindTexImage2DCHROMIUM(image_target, staging_buffer->image_id);
+ }
+ } else {
+ gl->ReleaseTexImage2DCHROMIUM(image_target, staging_buffer->image_id);
+ gl->BindTexImage2DCHROMIUM(image_target, staging_buffer->image_id);
+ }
- {
- TRACE_EVENT0("cc", "WaitingForCopyOperationsToComplete");
+ // Unbind staging texture.
+ gl->BindTexture(image_target, 0);
+
+ if (resource_provider_->use_sync_query()) {
+ if (!staging_buffer->query_id)
+ gl->GenQueriesEXT(1, &staging_buffer->query_id);
+
+#if defined(OS_CHROMEOS)
+ // TODO(reveman): This avoids a performance problem on some ChromeOS
+ // devices. This needs to be removed to support native GpuMemoryBuffer
+ // implementations. crbug.com/436314
+ gl->BeginQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM, staging_buffer->query_id);
+#else
+ gl->BeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM,
+ staging_buffer->query_id);
+#endif
+ }
- // Wait for in-flight copy operations to drop below limit.
- copy_operation_count_cv_.Wait();
+ int bytes_per_row =
+ (BitsPerPixel(resource->format()) * resource->size().width()) / 8;
+ int chunk_size_in_rows =
+ std::max(1, max_bytes_per_copy_operation_ / bytes_per_row);
+ // Align chunk size to 4. Required to support compressed texture formats.
+ chunk_size_in_rows = MathUtil::UncheckedRoundUp(chunk_size_in_rows, 4);
+ int y = 0;
+ int height = resource->size().height();
+ while (y < height) {
+ // Copy at most |chunk_size_in_rows|.
+ int rows_to_copy = std::min(chunk_size_in_rows, height - y);
+ DCHECK_GT(rows_to_copy, 0);
+
+ gl->CopySubTextureCHROMIUM(GL_TEXTURE_2D, staging_buffer->texture_id,
+ resource_lock->texture_id(), 0, y, 0, y,
+ resource->size().width(), rows_to_copy, false,
+ false, false);
+ y += rows_to_copy;
+
+ // Increment |bytes_scheduled_since_last_flush_| by the amount of memory
+ // used for this copy operation.
+ bytes_scheduled_since_last_flush_ += rows_to_copy * bytes_per_row;
+
+ if (bytes_scheduled_since_last_flush_ >= max_bytes_per_copy_operation_) {
+ gl->ShallowFlushCHROMIUM();
+ bytes_scheduled_since_last_flush_ = 0;
}
}
- // There may be more work available, so wake up another worker thread.
- copy_operation_count_cv_.Signal();
-
- // Copy at most |chunk_size_in_rows|.
- int rows_to_copy = std::min(chunk_size_in_rows, height - y);
- DCHECK_GT(rows_to_copy, 0);
-
- // |raster_resource_write_lock| is passed to the first copy operation as it
- // needs to be released before we can issue a copy.
- pending_copy_operations_.push_back(make_scoped_ptr(new CopyOperation(
- raster_resource_write_lock.Pass(), raster_resource, output_resource,
- gfx::Rect(0, y, raster_resource->size().width(), rows_to_copy))));
- y += rows_to_copy;
-
- // Acquire a sequence number for this copy operation.
- sequence = next_copy_operation_sequence_++;
-
- // Increment |bytes_scheduled_since_last_flush_| by the amount of memory
- // used for this copy operation.
- bytes_scheduled_since_last_flush_ += rows_to_copy * bytes_per_row;
-
- // Post task that will advance last flushed copy operation to |sequence|
- // when |bytes_scheduled_since_last_flush_| has reached
- // |max_bytes_per_copy_operation_|.
- if (bytes_scheduled_since_last_flush_ >= max_bytes_per_copy_operation_) {
- task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&OneCopyTileTaskWorkerPool::AdvanceLastFlushedCopyTo,
- weak_ptr_factory_.GetWeakPtr(), sequence));
- bytes_scheduled_since_last_flush_ = 0;
+ if (resource_provider_->use_sync_query()) {
+#if defined(OS_CHROMEOS)
+ gl->EndQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM);
+#else
+ gl->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM);
+#endif
}
+
+ // Barrier to sync worker context output to cc context.
+ gl->OrderingBarrierCHROMIUM();
}
- return sequence;
+ staging_buffer->last_usage = base::TimeTicks::Now();
+ busy_buffers_.push_back(staging_buffer.Pass());
+
+ ScheduleReduceMemoryUsage();
}
-void OneCopyTileTaskWorkerPool::AdvanceLastIssuedCopyTo(
- CopySequenceNumber sequence) {
- if (last_issued_copy_operation_ >= sequence)
- return;
+bool OneCopyTileTaskWorkerPool::OnMemoryDump(
+ const base::trace_event::MemoryDumpArgs& args,
+ base::trace_event::ProcessMemoryDump* pmd) {
+ base::AutoLock lock(lock_);
- IssueCopyOperations(sequence - last_issued_copy_operation_);
- last_issued_copy_operation_ = sequence;
+ for (const auto& buffer : buffers_) {
+ buffer->OnMemoryDump(pmd, buffer->format,
+ std::find(free_buffers_.begin(), free_buffers_.end(),
+ buffer) != free_buffers_.end());
+ }
+
+ return true;
}
-void OneCopyTileTaskWorkerPool::AdvanceLastFlushedCopyTo(
- CopySequenceNumber sequence) {
- if (last_flushed_copy_operation_ >= sequence)
- return;
+void OneCopyTileTaskWorkerPool::AddStagingBuffer(
+ const StagingBuffer* staging_buffer,
+ ResourceFormat format) {
+ lock_.AssertAcquired();
+
+ DCHECK(buffers_.find(staging_buffer) == buffers_.end());
+ buffers_.insert(staging_buffer);
+ int buffer_usage_in_bytes =
+ ResourceUtil::UncheckedSizeInBytes<int>(staging_buffer->size, format);
+ staging_buffer_usage_in_bytes_ += buffer_usage_in_bytes;
+}
- AdvanceLastIssuedCopyTo(sequence);
+void OneCopyTileTaskWorkerPool::RemoveStagingBuffer(
+ const StagingBuffer* staging_buffer) {
+ lock_.AssertAcquired();
- // Flush all issued copy operations.
- context_provider_->ContextGL()->ShallowFlushCHROMIUM();
- last_flushed_copy_operation_ = last_issued_copy_operation_;
+ DCHECK(buffers_.find(staging_buffer) != buffers_.end());
+ buffers_.erase(staging_buffer);
+ int buffer_usage_in_bytes = ResourceUtil::UncheckedSizeInBytes<int>(
+ staging_buffer->size, staging_buffer->format);
+ DCHECK_GE(staging_buffer_usage_in_bytes_, buffer_usage_in_bytes);
+ staging_buffer_usage_in_bytes_ -= buffer_usage_in_bytes;
}
-void OneCopyTileTaskWorkerPool::OnTaskSetFinished(TaskSet task_set) {
- TRACE_EVENT1("cc", "OneCopyTileTaskWorkerPool::OnTaskSetFinished", "task_set",
- task_set);
+void OneCopyTileTaskWorkerPool::MarkStagingBufferAsFree(
+ const StagingBuffer* staging_buffer) {
+ lock_.AssertAcquired();
- DCHECK(tasks_pending_[task_set]);
- tasks_pending_[task_set] = false;
- if (tasks_pending_.any()) {
- TRACE_EVENT_ASYNC_STEP_INTO1("cc", "ScheduledTasks", this, "running",
- "state", StateAsValue());
- } else {
- TRACE_EVENT_ASYNC_END0("cc", "ScheduledTasks", this);
- }
- client_->DidFinishRunningTileTasks(task_set);
+ int buffer_usage_in_bytes = ResourceUtil::UncheckedSizeInBytes<int>(
+ staging_buffer->size, staging_buffer->format);
+ free_staging_buffer_usage_in_bytes_ += buffer_usage_in_bytes;
}
-void OneCopyTileTaskWorkerPool::IssueCopyOperations(int64 count) {
- TRACE_EVENT1("cc", "OneCopyTileTaskWorkerPool::IssueCopyOperations", "count",
- count);
+void OneCopyTileTaskWorkerPool::MarkStagingBufferAsBusy(
+ const StagingBuffer* staging_buffer) {
+ lock_.AssertAcquired();
- CopyOperation::Deque copy_operations;
+ int buffer_usage_in_bytes = ResourceUtil::UncheckedSizeInBytes<int>(
+ staging_buffer->size, staging_buffer->format);
+ DCHECK_GE(free_staging_buffer_usage_in_bytes_, buffer_usage_in_bytes);
+ free_staging_buffer_usage_in_bytes_ -= buffer_usage_in_bytes;
+}
- {
- base::AutoLock lock(lock_);
+scoped_ptr<OneCopyTileTaskWorkerPool::StagingBuffer>
+OneCopyTileTaskWorkerPool::AcquireStagingBuffer(const Resource* resource,
+ uint64_t previous_content_id) {
+ lock_.AssertAcquired();
+
+ scoped_ptr<StagingBuffer> staging_buffer;
+
+ ContextProvider* context_provider =
+ resource_provider_->output_surface()->worker_context_provider();
+ DCHECK(context_provider);
- for (int64 i = 0; i < count; ++i) {
- DCHECK(!pending_copy_operations_.empty());
- copy_operations.push_back(pending_copy_operations_.take_front());
+ ContextProvider::ScopedContextLock scoped_context(context_provider);
+
+ gpu::gles2::GLES2Interface* gl = scoped_context.ContextGL();
+ DCHECK(gl);
+
+ // Check if any busy buffers have become available.
+ if (resource_provider_->use_sync_query()) {
+ while (!busy_buffers_.empty()) {
+ if (!CheckForQueryResult(gl, busy_buffers_.front()->query_id))
+ break;
+
+ MarkStagingBufferAsFree(busy_buffers_.front());
+ free_buffers_.push_back(busy_buffers_.take_front());
}
+ }
- // Increment |issued_copy_operation_count_| to reflect the transition of
- // copy operations from "pending" to "issued" state.
- issued_copy_operation_count_ += copy_operations.size();
+ // Wait for memory usage of non-free buffers to become less than the limit.
+ while (
+ (staging_buffer_usage_in_bytes_ - free_staging_buffer_usage_in_bytes_) >=
+ max_staging_buffer_usage_in_bytes_) {
+ // Stop when there are no more busy buffers to wait for.
+ if (busy_buffers_.empty())
+ break;
+
+ if (resource_provider_->use_sync_query()) {
+ WaitForQueryResult(gl, busy_buffers_.front()->query_id);
+ MarkStagingBufferAsFree(busy_buffers_.front());
+ free_buffers_.push_back(busy_buffers_.take_front());
+ } else {
+ // Fall-back to glFinish if CHROMIUM_sync_query is not available.
+ gl->Finish();
+ while (!busy_buffers_.empty()) {
+ MarkStagingBufferAsFree(busy_buffers_.front());
+ free_buffers_.push_back(busy_buffers_.take_front());
+ }
+ }
}
- while (!copy_operations.empty()) {
- scoped_ptr<CopyOperation> copy_operation = copy_operations.take_front();
+ // Find a staging buffer that allows us to perform partial raster when
+ // using persistent GpuMemoryBuffers.
+ if (use_persistent_gpu_memory_buffers_ && previous_content_id) {
+ StagingBufferDeque::iterator it =
+ std::find_if(free_buffers_.begin(), free_buffers_.end(),
+ [previous_content_id](const StagingBuffer* buffer) {
+ return buffer->content_id == previous_content_id;
+ });
+ if (it != free_buffers_.end()) {
+ staging_buffer = free_buffers_.take(it);
+ MarkStagingBufferAsBusy(staging_buffer.get());
+ }
+ }
- // Remove the write lock.
- copy_operation->src_write_lock.reset();
+ // Find staging buffer of correct size and format.
+ if (!staging_buffer) {
+ StagingBufferDeque::iterator it =
+ std::find_if(free_buffers_.begin(), free_buffers_.end(),
+ [resource](const StagingBuffer* buffer) {
+ return buffer->size == resource->size() &&
+ buffer->format == resource->format();
+ });
+ if (it != free_buffers_.end()) {
+ staging_buffer = free_buffers_.take(it);
+ MarkStagingBufferAsBusy(staging_buffer.get());
+ }
+ }
+
+ // Create new staging buffer if necessary.
+ if (!staging_buffer) {
+ staging_buffer = make_scoped_ptr(
+ new StagingBuffer(resource->size(), resource->format()));
+ AddStagingBuffer(staging_buffer.get(), resource->format());
+ }
+
+ // Release enough free buffers to stay within the limit.
+ while (staging_buffer_usage_in_bytes_ > max_staging_buffer_usage_in_bytes_) {
+ if (free_buffers_.empty())
+ break;
- // Copy contents of source resource to destination resource.
- resource_provider_->CopyResource(copy_operation->src->id(),
- copy_operation->dst->id(),
- copy_operation->rect);
+ free_buffers_.front()->DestroyGLResources(gl);
+ MarkStagingBufferAsBusy(free_buffers_.front());
+ RemoveStagingBuffer(free_buffers_.front());
+ free_buffers_.take_front();
}
+
+ return staging_buffer.Pass();
}
-void OneCopyTileTaskWorkerPool::
- ScheduleCheckForCompletedCopyOperationsWithLockAcquired(
- bool wait_if_needed) {
+base::TimeTicks OneCopyTileTaskWorkerPool::GetUsageTimeForLRUBuffer() {
lock_.AssertAcquired();
- if (check_for_completed_copy_operations_pending_)
- return;
+ if (!free_buffers_.empty())
+ return free_buffers_.front()->last_usage;
- base::TimeTicks now = base::TimeTicks::Now();
+ if (!busy_buffers_.empty())
+ return busy_buffers_.front()->last_usage;
- // Schedule a check for completed copy operations as soon as possible but
- // don't allow two consecutive checks to be scheduled to run less than the
- // tick rate apart.
- base::TimeTicks next_check_for_completed_copy_operations_time =
- std::max(last_check_for_completed_copy_operations_time_ +
- base::TimeDelta::FromMilliseconds(
- kCheckForCompletedCopyOperationsTickRateMs),
- now);
+ return base::TimeTicks();
+}
+void OneCopyTileTaskWorkerPool::ScheduleReduceMemoryUsage() {
+ lock_.AssertAcquired();
+
+ if (reduce_memory_usage_pending_)
+ return;
+
+ reduce_memory_usage_pending_ = true;
+
+ // Schedule a call to ReduceMemoryUsage at the time when the LRU buffer
+ // should be released.
+ base::TimeTicks reduce_memory_usage_time =
+ GetUsageTimeForLRUBuffer() + staging_buffer_expiration_delay_;
task_runner_->PostDelayedTask(
- FROM_HERE,
- base::Bind(&OneCopyTileTaskWorkerPool::CheckForCompletedCopyOperations,
- weak_ptr_factory_.GetWeakPtr(), wait_if_needed),
- next_check_for_completed_copy_operations_time - now);
-
- last_check_for_completed_copy_operations_time_ =
- next_check_for_completed_copy_operations_time;
- check_for_completed_copy_operations_pending_ = true;
+ FROM_HERE, reduce_memory_usage_callback_,
+ reduce_memory_usage_time - base::TimeTicks::Now());
}
-void OneCopyTileTaskWorkerPool::CheckForCompletedCopyOperations(
- bool wait_if_needed) {
- TRACE_EVENT1("cc",
- "OneCopyTileTaskWorkerPool::CheckForCompletedCopyOperations",
- "wait_if_needed", wait_if_needed);
+void OneCopyTileTaskWorkerPool::ReduceMemoryUsage() {
+ base::AutoLock lock(lock_);
+
+ reduce_memory_usage_pending_ = false;
+
+ if (free_buffers_.empty() && busy_buffers_.empty())
+ return;
- resource_pool_->CheckBusyResources(wait_if_needed);
+ base::TimeTicks current_time = base::TimeTicks::Now();
+ ReleaseBuffersNotUsedSince(current_time - staging_buffer_expiration_delay_);
+
+ if (free_buffers_.empty() && busy_buffers_.empty())
+ return;
+
+ reduce_memory_usage_pending_ = true;
+
+ // Schedule another call to ReduceMemoryUsage at the time when the next
+ // buffer should be released.
+ base::TimeTicks reduce_memory_usage_time =
+ GetUsageTimeForLRUBuffer() + staging_buffer_expiration_delay_;
+ task_runner_->PostDelayedTask(FROM_HERE, reduce_memory_usage_callback_,
+ reduce_memory_usage_time - current_time);
+}
+
+void OneCopyTileTaskWorkerPool::ReleaseBuffersNotUsedSince(
+ base::TimeTicks time) {
+ lock_.AssertAcquired();
+
+ ContextProvider* context_provider =
+ resource_provider_->output_surface()->worker_context_provider();
+ DCHECK(context_provider);
{
- base::AutoLock lock(lock_);
+ ContextProvider::ScopedContextLock scoped_context(context_provider);
+
+ gpu::gles2::GLES2Interface* gl = scoped_context.ContextGL();
+ DCHECK(gl);
- DCHECK(check_for_completed_copy_operations_pending_);
- check_for_completed_copy_operations_pending_ = false;
+ // Note: Front buffer is guaranteed to be LRU so we can stop releasing
+ // buffers as soon as we find a buffer that has been used since |time|.
+ while (!free_buffers_.empty()) {
+ if (free_buffers_.front()->last_usage > time)
+ return;
+
+ free_buffers_.front()->DestroyGLResources(gl);
+ MarkStagingBufferAsBusy(free_buffers_.front());
+ RemoveStagingBuffer(free_buffers_.front());
+ free_buffers_.take_front();
+ }
- // The number of busy resources in the pool reflects the number of issued
- // copy operations that have not yet completed.
- issued_copy_operation_count_ = resource_pool_->busy_resource_count();
+ while (!busy_buffers_.empty()) {
+ if (busy_buffers_.front()->last_usage > time)
+ return;
- // There may be work blocked on too many in-flight copy operations, so wake
- // up a worker thread.
- copy_operation_count_cv_.Signal();
+ busy_buffers_.front()->DestroyGLResources(gl);
+ RemoveStagingBuffer(busy_buffers_.front());
+ busy_buffers_.take_front();
+ }
+ }
+}
+
+void OneCopyTileTaskWorkerPool::OnTaskSetFinished(TaskSet task_set) {
+ TRACE_EVENT1("cc", "OneCopyTileTaskWorkerPool::OnTaskSetFinished", "task_set",
+ task_set);
+
+ DCHECK(tasks_pending_[task_set]);
+ tasks_pending_[task_set] = false;
+ if (tasks_pending_.any()) {
+ TRACE_EVENT_ASYNC_STEP_INTO1("cc", "ScheduledTasks", this, "running",
+ "state", StateAsValue());
+ } else {
+ TRACE_EVENT_ASYNC_END0("cc", "ScheduledTasks", this);
}
+ client_->DidFinishRunningTileTasks(task_set);
}
scoped_refptr<base::trace_event::ConvertableToTraceFormat>
@@ -571,20 +807,14 @@ OneCopyTileTaskWorkerPool::StateAsValue() const {
void OneCopyTileTaskWorkerPool::StagingStateAsValueInto(
base::trace_event::TracedValue* staging_state) const {
- staging_state->SetInteger(
- "staging_resource_count",
- static_cast<int>(resource_pool_->total_resource_count()));
- staging_state->SetInteger(
- "bytes_used_for_staging_resources",
- static_cast<int>(resource_pool_->total_memory_usage_bytes()));
- staging_state->SetInteger(
- "pending_copy_count",
- static_cast<int>(resource_pool_->total_resource_count() -
- resource_pool_->acquired_resource_count()));
- staging_state->SetInteger(
- "bytes_pending_copy",
- static_cast<int>(resource_pool_->total_memory_usage_bytes() -
- resource_pool_->acquired_memory_usage_bytes()));
+ base::AutoLock lock(lock_);
+
+ staging_state->SetInteger("staging_buffer_count",
+ static_cast<int>(buffers_.size()));
+ staging_state->SetInteger("busy_count",
+ static_cast<int>(busy_buffers_.size()));
+ staging_state->SetInteger("free_count",
+ static_cast<int>(free_buffers_.size()));
}
} // namespace cc
diff --git a/chromium/cc/raster/one_copy_tile_task_worker_pool.h b/chromium/cc/raster/one_copy_tile_task_worker_pool.h
index 518aaa2d490..3b02bae062a 100644
--- a/chromium/cc/raster/one_copy_tile_task_worker_pool.h
+++ b/chromium/cc/raster/one_copy_tile_task_worker_pool.h
@@ -5,8 +5,12 @@
#ifndef CC_RASTER_ONE_COPY_TILE_TASK_WORKER_POOL_H_
#define CC_RASTER_ONE_COPY_TILE_TASK_WORKER_POOL_H_
+#include <set>
+
#include "base/memory/weak_ptr.h"
#include "base/synchronization/lock.h"
+#include "base/time/time.h"
+#include "base/trace_event/memory_dump_provider.h"
#include "base/values.h"
#include "cc/base/scoped_ptr_deque.h"
#include "cc/output/context_provider.h"
@@ -21,15 +25,20 @@ class TracedValue;
}
}
+namespace gpu {
+namespace gles2 {
+class GLES2Interface;
+}
+}
+
namespace cc {
class ResourcePool;
-class ScopedResource;
-
-typedef int64 CopySequenceNumber;
-class CC_EXPORT OneCopyTileTaskWorkerPool : public TileTaskWorkerPool,
- public TileTaskRunner,
- public TileTaskClient {
+class CC_EXPORT OneCopyTileTaskWorkerPool
+ : public TileTaskWorkerPool,
+ public TileTaskRunner,
+ public TileTaskClient,
+ public base::trace_event::MemoryDumpProvider {
public:
~OneCopyTileTaskWorkerPool() override;
@@ -38,9 +47,10 @@ class CC_EXPORT OneCopyTileTaskWorkerPool : public TileTaskWorkerPool,
TaskGraphRunner* task_graph_runner,
ContextProvider* context_provider,
ResourceProvider* resource_provider,
- ResourcePool* resource_pool,
int max_copy_texture_chromium_size,
- bool have_persistent_gpu_memory_buffers);
+ bool use_persistent_gpu_memory_buffers,
+ int max_staging_buffer_usage_in_bytes,
+ bool use_rgba_4444_texture_format);
// Overridden from TileTaskWorkerPool:
TileTaskRunner* AsTileTaskRunner() override;
@@ -50,8 +60,8 @@ class CC_EXPORT OneCopyTileTaskWorkerPool : public TileTaskWorkerPool,
void Shutdown() override;
void ScheduleTasks(TileTaskQueue* queue) override;
void CheckForCompletedTasks() override;
- ResourceFormat GetResourceFormat() const override;
- bool GetResourceRequiresSwizzle() const override;
+ ResourceFormat GetResourceFormat(bool must_support_alpha) const override;
+ bool GetResourceRequiresSwizzle(bool must_support_alpha) const override;
// Overridden from TileTaskClient:
scoped_ptr<RasterBuffer> AcquireBufferForRaster(
@@ -60,60 +70,64 @@ class CC_EXPORT OneCopyTileTaskWorkerPool : public TileTaskWorkerPool,
uint64_t previous_content_id) override;
void ReleaseBufferForRaster(scoped_ptr<RasterBuffer> buffer) override;
- // Playback raster source and schedule copy of |raster_resource| resource to
- // |output_resource|. Returns a non-zero sequence number for this copy
- // operation.
- CopySequenceNumber PlaybackAndScheduleCopyOnWorkerThread(
- bool reusing_raster_resource,
- scoped_ptr<ResourceProvider::ScopedWriteLockGpuMemoryBuffer>
- raster_resource_write_lock,
- const Resource* raster_resource,
- const Resource* output_resource,
+ // Overridden from base::trace_event::MemoryDumpProvider:
+ bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
+ base::trace_event::ProcessMemoryDump* pmd) override;
+
+ // Playback raster source and copy result into |resource|.
+ void PlaybackAndCopyOnWorkerThread(
+ const Resource* resource,
+ const ResourceProvider::ScopedWriteLockGL* resource_lock,
const RasterSource* raster_source,
const gfx::Rect& raster_full_rect,
const gfx::Rect& raster_dirty_rect,
- float scale);
-
- // Issues copy operations until |sequence| has been processed. This will
- // return immediately if |sequence| has already been processed.
- void AdvanceLastIssuedCopyTo(CopySequenceNumber sequence);
-
- bool have_persistent_gpu_memory_buffers() const {
- return have_persistent_gpu_memory_buffers_;
- }
+ float scale,
+ bool include_images,
+ uint64_t resource_content_id,
+ uint64_t previous_content_id);
protected:
OneCopyTileTaskWorkerPool(base::SequencedTaskRunner* task_runner,
TaskGraphRunner* task_graph_runner,
- ContextProvider* context_provider,
ResourceProvider* resource_provider,
- ResourcePool* resource_pool,
int max_copy_texture_chromium_size,
- bool have_persistent_gpu_memory_buffers);
+ bool use_persistent_gpu_memory_buffers,
+ int max_staging_buffer_usage_in_bytes,
+ bool use_rgba_4444_texture_format);
private:
- struct CopyOperation {
- typedef ScopedPtrDeque<CopyOperation> Deque;
-
- CopyOperation(scoped_ptr<ResourceProvider::ScopedWriteLockGpuMemoryBuffer>
- src_write_lock,
- const Resource* src,
- const Resource* dst,
- const gfx::Rect& rect);
- ~CopyOperation();
-
- scoped_ptr<ResourceProvider::ScopedWriteLockGpuMemoryBuffer> src_write_lock;
- const Resource* src;
- const Resource* dst;
- const gfx::Rect rect;
+ struct StagingBuffer {
+ StagingBuffer(const gfx::Size& size, ResourceFormat format);
+ ~StagingBuffer();
+
+ void DestroyGLResources(gpu::gles2::GLES2Interface* gl);
+ void OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd,
+ ResourceFormat format,
+ bool is_free) const;
+
+ const gfx::Size size;
+ const ResourceFormat format;
+ scoped_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer;
+ base::TimeTicks last_usage;
+ unsigned texture_id;
+ unsigned image_id;
+ unsigned query_id;
+ uint64_t content_id;
};
+ void AddStagingBuffer(const StagingBuffer* staging_buffer,
+ ResourceFormat format);
+ void RemoveStagingBuffer(const StagingBuffer* staging_buffer);
+ void MarkStagingBufferAsFree(const StagingBuffer* staging_buffer);
+ void MarkStagingBufferAsBusy(const StagingBuffer* staging_buffer);
+ scoped_ptr<StagingBuffer> AcquireStagingBuffer(const Resource* resource,
+ uint64_t previous_content_id);
+ base::TimeTicks GetUsageTimeForLRUBuffer();
+ void ScheduleReduceMemoryUsage();
+ void ReduceMemoryUsage();
+ void ReleaseBuffersNotUsedSince(base::TimeTicks time);
+
void OnTaskSetFinished(TaskSet task_set);
- void AdvanceLastFlushedCopyTo(CopySequenceNumber sequence);
- void IssueCopyOperations(int64 count);
- void ScheduleCheckForCompletedCopyOperationsWithLockAcquired(
- bool wait_if_needed);
- void CheckForCompletedCopyOperations(bool wait_if_needed);
scoped_refptr<base::trace_event::ConvertableToTraceFormat> StateAsValue()
const;
void StagingStateAsValueInto(
@@ -123,31 +137,32 @@ class CC_EXPORT OneCopyTileTaskWorkerPool : public TileTaskWorkerPool,
TaskGraphRunner* task_graph_runner_;
const NamespaceToken namespace_token_;
TileTaskRunnerClient* client_;
- ContextProvider* context_provider_;
- ResourceProvider* resource_provider_;
- ResourcePool* resource_pool_;
+ ResourceProvider* const resource_provider_;
const int max_bytes_per_copy_operation_;
- const bool have_persistent_gpu_memory_buffers_;
+ const bool use_persistent_gpu_memory_buffers_;
TaskSetCollection tasks_pending_;
scoped_refptr<TileTask> task_set_finished_tasks_[kNumberOfTaskSets];
- CopySequenceNumber last_issued_copy_operation_;
- CopySequenceNumber last_flushed_copy_operation_;
// Task graph used when scheduling tasks and vector used to gather
// completed tasks.
TaskGraph graph_;
Task::Vector completed_tasks_;
- base::Lock lock_;
+ mutable base::Lock lock_;
// |lock_| must be acquired when accessing the following members.
- base::ConditionVariable copy_operation_count_cv_;
+ using StagingBufferSet = std::set<const StagingBuffer*>;
+ StagingBufferSet buffers_;
+ using StagingBufferDeque = ScopedPtrDeque<StagingBuffer>;
+ StagingBufferDeque free_buffers_;
+ StagingBufferDeque busy_buffers_;
int bytes_scheduled_since_last_flush_;
- size_t issued_copy_operation_count_;
- CopyOperation::Deque pending_copy_operations_;
- CopySequenceNumber next_copy_operation_sequence_;
- bool check_for_completed_copy_operations_pending_;
- base::TimeTicks last_check_for_completed_copy_operations_time_;
- bool shutdown_;
+ const int max_staging_buffer_usage_in_bytes_;
+ bool use_rgba_4444_texture_format_;
+ int staging_buffer_usage_in_bytes_;
+ int free_staging_buffer_usage_in_bytes_;
+ const base::TimeDelta staging_buffer_expiration_delay_;
+ bool reduce_memory_usage_pending_;
+ base::Closure reduce_memory_usage_callback_;
base::WeakPtrFactory<OneCopyTileTaskWorkerPool> weak_ptr_factory_;
// "raster finished" tasks need their own factory as they need to be
diff --git a/chromium/cc/raster/pixel_buffer_tile_task_worker_pool.cc b/chromium/cc/raster/pixel_buffer_tile_task_worker_pool.cc
deleted file mode 100644
index df79519485d..00000000000
--- a/chromium/cc/raster/pixel_buffer_tile_task_worker_pool.cc
+++ /dev/null
@@ -1,754 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cc/raster/pixel_buffer_tile_task_worker_pool.h"
-
-#include <algorithm>
-
-#include "base/containers/stack_container.h"
-#include "base/strings/stringprintf.h"
-#include "base/trace_event/trace_event.h"
-#include "base/trace_event/trace_event_argument.h"
-#include "cc/debug/traced_value.h"
-#include "cc/raster/raster_buffer.h"
-#include "cc/resources/platform_color.h"
-#include "cc/resources/resource.h"
-#include "gpu/command_buffer/client/gles2_interface.h"
-
-namespace cc {
-namespace {
-
-class RasterBufferImpl : public RasterBuffer {
- public:
- RasterBufferImpl(ResourceProvider* resource_provider,
- const Resource* resource)
- : resource_provider_(resource_provider),
- resource_(resource),
- memory_(NULL),
- stride_(0) {
- resource_provider_->AcquirePixelBuffer(resource_->id());
- memory_ = resource_provider_->MapPixelBuffer(resource_->id(), &stride_);
- }
-
- ~RasterBufferImpl() override {
- resource_provider_->ReleasePixelBuffer(resource_->id());
- }
-
- // Overridden from RasterBuffer:
- void Playback(const RasterSource* raster_source,
- const gfx::Rect& raster_full_rect,
- const gfx::Rect& raster_dirty_rect,
- uint64_t new_content_id,
- float scale) override {
- if (!memory_)
- return;
-
- // TileTaskWorkerPool::PlaybackToMemory only supports unsigned strides.
- DCHECK_GE(stride_, 0);
- TileTaskWorkerPool::PlaybackToMemory(
- memory_, resource_->format(), resource_->size(),
- static_cast<size_t>(stride_), raster_source, raster_full_rect,
- raster_full_rect, scale);
- }
-
- private:
- ResourceProvider* resource_provider_;
- const Resource* resource_;
- uint8_t* memory_;
- int stride_;
-
- DISALLOW_COPY_AND_ASSIGN(RasterBufferImpl);
-};
-
-const int kCheckForCompletedRasterTasksDelayMs = 6;
-
-const size_t kMaxScheduledRasterTasks = 48;
-
-typedef base::StackVector<RasterTask*, kMaxScheduledRasterTasks>
- RasterTaskVector;
-
-TaskSetCollection NonEmptyTaskSetsFromTaskCounts(const size_t* task_counts) {
- TaskSetCollection task_sets;
- for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) {
- if (task_counts[task_set])
- task_sets[task_set] = true;
- }
- return task_sets;
-}
-
-void AddTaskSetsToTaskCounts(size_t* task_counts,
- const TaskSetCollection& task_sets) {
- for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) {
- if (task_sets[task_set])
- task_counts[task_set]++;
- }
-}
-
-void RemoveTaskSetsFromTaskCounts(size_t* task_counts,
- const TaskSetCollection& task_sets) {
- for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) {
- if (task_sets[task_set])
- task_counts[task_set]--;
- }
-}
-
-} // namespace
-
-PixelBufferTileTaskWorkerPool::RasterTaskState::RasterTaskState(
- RasterTask* task,
- const TaskSetCollection& task_sets)
- : type(UNSCHEDULED), task(task), task_sets(task_sets) {
-}
-
-// static
-scoped_ptr<TileTaskWorkerPool> PixelBufferTileTaskWorkerPool::Create(
- base::SequencedTaskRunner* task_runner,
- TaskGraphRunner* task_graph_runner,
- ContextProvider* context_provider,
- ResourceProvider* resource_provider,
- size_t max_transfer_buffer_usage_bytes) {
- return make_scoped_ptr<TileTaskWorkerPool>(new PixelBufferTileTaskWorkerPool(
- task_runner, task_graph_runner, context_provider, resource_provider,
- max_transfer_buffer_usage_bytes));
-}
-
-PixelBufferTileTaskWorkerPool::PixelBufferTileTaskWorkerPool(
- base::SequencedTaskRunner* task_runner,
- TaskGraphRunner* task_graph_runner,
- ContextProvider* context_provider,
- ResourceProvider* resource_provider,
- size_t max_transfer_buffer_usage_bytes)
- : task_runner_(task_runner),
- task_graph_runner_(task_graph_runner),
- namespace_token_(task_graph_runner->GetNamespaceToken()),
- context_provider_(context_provider),
- resource_provider_(resource_provider),
- shutdown_(false),
- scheduled_raster_task_count_(0u),
- bytes_pending_upload_(0u),
- max_bytes_pending_upload_(max_transfer_buffer_usage_bytes),
- has_performed_uploads_since_last_flush_(false),
- check_for_completed_raster_task_notifier_(
- task_runner,
- base::Bind(
- &PixelBufferTileTaskWorkerPool::CheckForCompletedRasterTasks,
- base::Unretained(this)),
- base::TimeDelta::FromMilliseconds(
- kCheckForCompletedRasterTasksDelayMs)),
- task_set_finished_weak_ptr_factory_(this) {
- DCHECK(context_provider_);
- std::fill(task_counts_, task_counts_ + kNumberOfTaskSets, 0);
-}
-
-PixelBufferTileTaskWorkerPool::~PixelBufferTileTaskWorkerPool() {
- DCHECK_EQ(0u, raster_task_states_.size());
- DCHECK_EQ(0u, raster_tasks_with_pending_upload_.size());
- DCHECK_EQ(0u, completed_raster_tasks_.size());
- DCHECK_EQ(0u, completed_image_decode_tasks_.size());
- DCHECK(NonEmptyTaskSetsFromTaskCounts(task_counts_).none());
-}
-
-TileTaskRunner* PixelBufferTileTaskWorkerPool::AsTileTaskRunner() {
- return this;
-}
-
-void PixelBufferTileTaskWorkerPool::SetClient(TileTaskRunnerClient* client) {
- client_ = client;
-}
-
-void PixelBufferTileTaskWorkerPool::Shutdown() {
- TRACE_EVENT0("cc", "PixelBufferTileTaskWorkerPool::Shutdown");
-
- shutdown_ = true;
-
- TaskGraph empty;
- task_graph_runner_->ScheduleTasks(namespace_token_, &empty);
- task_graph_runner_->WaitForTasksToFinishRunning(namespace_token_);
-
- CheckForCompletedRasterizerTasks();
- CheckForCompletedUploads();
-
- check_for_completed_raster_task_notifier_.Shutdown();
-
- for (RasterTaskState::Vector::iterator it = raster_task_states_.begin();
- it != raster_task_states_.end(); ++it) {
- RasterTaskState& state = *it;
-
- // All unscheduled tasks need to be canceled.
- if (state.type == RasterTaskState::UNSCHEDULED) {
- completed_raster_tasks_.push_back(state.task);
- state.type = RasterTaskState::COMPLETED;
- }
- }
- DCHECK_EQ(completed_raster_tasks_.size(), raster_task_states_.size());
-}
-
-void PixelBufferTileTaskWorkerPool::ScheduleTasks(TileTaskQueue* queue) {
- TRACE_EVENT0("cc", "PixelBufferTileTaskWorkerPool::ScheduleTasks");
-
- if (should_notify_client_if_no_tasks_are_pending_.none())
- TRACE_EVENT_ASYNC_BEGIN0("cc", "ScheduledTasks", this);
-
- should_notify_client_if_no_tasks_are_pending_.set();
- std::fill(task_counts_, task_counts_ + kNumberOfTaskSets, 0);
-
- // Update raster task state and remove items from old queue.
- for (TileTaskQueue::Item::Vector::const_iterator it = queue->items.begin();
- it != queue->items.end(); ++it) {
- const TileTaskQueue::Item& item = *it;
- RasterTask* task = item.task;
-
- // Remove any old items that are associated with this task. The result is
- // that the old queue is left with all items not present in this queue,
- // which we use below to determine what tasks need to be canceled.
- TileTaskQueue::Item::Vector::iterator old_it =
- std::find_if(raster_tasks_.items.begin(), raster_tasks_.items.end(),
- TileTaskQueue::Item::TaskComparator(task));
- if (old_it != raster_tasks_.items.end()) {
- std::swap(*old_it, raster_tasks_.items.back());
- raster_tasks_.items.pop_back();
- }
-
- RasterTaskState::Vector::iterator state_it =
- std::find_if(raster_task_states_.begin(), raster_task_states_.end(),
- RasterTaskState::TaskComparator(task));
- if (state_it != raster_task_states_.end()) {
- RasterTaskState& state = *state_it;
-
- state.task_sets = item.task_sets;
- // |raster_tasks_required_for_activation_count| accounts for all tasks
- // that need to complete before we can send a "ready to activate" signal.
- // Tasks that have already completed should not be part of this count.
- if (state.type != RasterTaskState::COMPLETED)
- AddTaskSetsToTaskCounts(task_counts_, item.task_sets);
-
- continue;
- }
-
- DCHECK(!task->HasBeenScheduled());
- raster_task_states_.push_back(RasterTaskState(task, item.task_sets));
- AddTaskSetsToTaskCounts(task_counts_, item.task_sets);
- }
-
- // Determine what tasks in old queue need to be canceled.
- for (TileTaskQueue::Item::Vector::const_iterator it =
- raster_tasks_.items.begin();
- it != raster_tasks_.items.end(); ++it) {
- const TileTaskQueue::Item& item = *it;
- RasterTask* task = item.task;
-
- RasterTaskState::Vector::iterator state_it =
- std::find_if(raster_task_states_.begin(), raster_task_states_.end(),
- RasterTaskState::TaskComparator(task));
- // We've already processed completion if we can't find a RasterTaskState for
- // this task.
- if (state_it == raster_task_states_.end())
- continue;
-
- RasterTaskState& state = *state_it;
-
- // Unscheduled task can be canceled.
- if (state.type == RasterTaskState::UNSCHEDULED) {
- DCHECK(!task->HasBeenScheduled());
- DCHECK(std::find(completed_raster_tasks_.begin(),
- completed_raster_tasks_.end(),
- task) == completed_raster_tasks_.end());
- completed_raster_tasks_.push_back(task);
- state.type = RasterTaskState::COMPLETED;
- }
-
- // No longer in any task set.
- state.task_sets.reset();
- }
-
- raster_tasks_.Swap(queue);
-
- // Check for completed tasks when ScheduleTasks() is called as
- // priorities might have changed and this maximizes the number
- // of top priority tasks that are scheduled.
- CheckForCompletedRasterizerTasks();
- CheckForCompletedUploads();
- FlushUploads();
-
- // Schedule new tasks.
- ScheduleMoreTasks();
-
- // Reschedule check for completed raster tasks.
- check_for_completed_raster_task_notifier_.Schedule();
-
- TRACE_EVENT_ASYNC_STEP_INTO1("cc", "ScheduledTasks", this, StateName(),
- "state", StateAsValue());
-}
-
-void PixelBufferTileTaskWorkerPool::CheckForCompletedTasks() {
- TRACE_EVENT0("cc", "PixelBufferTileTaskWorkerPool::CheckForCompletedTasks");
-
- CheckForCompletedRasterizerTasks();
- CheckForCompletedUploads();
- FlushUploads();
-
- for (TileTask::Vector::const_iterator it =
- completed_image_decode_tasks_.begin();
- it != completed_image_decode_tasks_.end(); ++it) {
- TileTask* task = it->get();
- task->RunReplyOnOriginThread();
- }
- completed_image_decode_tasks_.clear();
-
- for (RasterTask::Vector::const_iterator it = completed_raster_tasks_.begin();
- it != completed_raster_tasks_.end(); ++it) {
- RasterTask* task = it->get();
- RasterTaskState::Vector::iterator state_it =
- std::find_if(raster_task_states_.begin(), raster_task_states_.end(),
- RasterTaskState::TaskComparator(task));
- DCHECK(state_it != raster_task_states_.end());
- DCHECK_EQ(RasterTaskState::COMPLETED, state_it->type);
-
- std::swap(*state_it, raster_task_states_.back());
- raster_task_states_.pop_back();
-
- task->RunReplyOnOriginThread();
- }
- completed_raster_tasks_.clear();
-}
-
-ResourceFormat PixelBufferTileTaskWorkerPool::GetResourceFormat() const {
- return resource_provider_->memory_efficient_texture_format();
-}
-
-bool PixelBufferTileTaskWorkerPool::GetResourceRequiresSwizzle() const {
- return !PlatformColor::SameComponentOrder(GetResourceFormat());
-}
-
-scoped_ptr<RasterBuffer> PixelBufferTileTaskWorkerPool::AcquireBufferForRaster(
- const Resource* resource,
- uint64_t resource_content_id,
- uint64_t previous_content_id) {
- return make_scoped_ptr<RasterBuffer>(
- new RasterBufferImpl(resource_provider_, resource));
-}
-
-void PixelBufferTileTaskWorkerPool::ReleaseBufferForRaster(
- scoped_ptr<RasterBuffer> buffer) {
- // Nothing to do here. RasterBufferImpl destructor cleans up after itself.
-}
-
-void PixelBufferTileTaskWorkerPool::OnTaskSetFinished(TaskSet task_set) {
- TRACE_EVENT2("cc", "PixelBufferTileTaskWorkerPool::OnTaskSetFinished",
- "task_set", task_set,
- "should_notify_client_if_no_tasks_are_pending",
- should_notify_client_if_no_tasks_are_pending_[task_set]);
-
- // There's no need to call CheckForCompletedRasterTasks() if the client has
- // already been notified.
- if (!should_notify_client_if_no_tasks_are_pending_[task_set])
- return;
- task_set_finished_tasks_pending_[task_set] = false;
-
- // This reduces latency between the time when all tasks required for
- // activation have finished running and the time when the client is
- // notified.
- CheckForCompletedRasterTasks();
-}
-
-void PixelBufferTileTaskWorkerPool::FlushUploads() {
- if (!has_performed_uploads_since_last_flush_)
- return;
-
- context_provider_->ContextGL()->ShallowFlushCHROMIUM();
- has_performed_uploads_since_last_flush_ = false;
-}
-
-void PixelBufferTileTaskWorkerPool::CheckForCompletedUploads() {
- RasterTask::Vector tasks_with_completed_uploads;
-
- // First check if any have completed.
- while (!raster_tasks_with_pending_upload_.empty()) {
- RasterTask* task = raster_tasks_with_pending_upload_.front().get();
- DCHECK(std::find_if(raster_task_states_.begin(), raster_task_states_.end(),
- RasterTaskState::TaskComparator(task)) !=
- raster_task_states_.end());
- DCHECK_EQ(
- RasterTaskState::UPLOADING,
- std::find_if(raster_task_states_.begin(), raster_task_states_.end(),
- RasterTaskState::TaskComparator(task))->type);
-
- // Uploads complete in the order they are issued.
- if (!resource_provider_->DidSetPixelsComplete(task->resource()->id()))
- break;
-
- tasks_with_completed_uploads.push_back(task);
- raster_tasks_with_pending_upload_.pop_front();
- }
-
- DCHECK(client_);
- TaskSetCollection tasks_that_should_be_forced_to_complete =
- client_->TasksThatShouldBeForcedToComplete();
- bool should_force_some_uploads_to_complete =
- shutdown_ || tasks_that_should_be_forced_to_complete.any();
-
- if (should_force_some_uploads_to_complete) {
- RasterTask::Vector tasks_with_uploads_to_force;
- RasterTaskDeque::iterator it = raster_tasks_with_pending_upload_.begin();
- while (it != raster_tasks_with_pending_upload_.end()) {
- RasterTask* task = it->get();
- RasterTaskState::Vector::const_iterator state_it =
- std::find_if(raster_task_states_.begin(), raster_task_states_.end(),
- RasterTaskState::TaskComparator(task));
- DCHECK(state_it != raster_task_states_.end());
- const RasterTaskState& state = *state_it;
-
- // Force all uploads to complete for which the client requests to do so.
- // During shutdown, force all pending uploads to complete.
- if (shutdown_ ||
- (state.task_sets & tasks_that_should_be_forced_to_complete).any()) {
- tasks_with_uploads_to_force.push_back(task);
- tasks_with_completed_uploads.push_back(task);
- it = raster_tasks_with_pending_upload_.erase(it);
- continue;
- }
-
- ++it;
- }
-
- // Force uploads in reverse order. Since forcing can cause a wait on
- // all previous uploads, we would rather wait only once downstream.
- for (RasterTask::Vector::reverse_iterator it =
- tasks_with_uploads_to_force.rbegin();
- it != tasks_with_uploads_to_force.rend(); ++it) {
- RasterTask* task = it->get();
-
- resource_provider_->ForceSetPixelsToComplete(task->resource()->id());
- has_performed_uploads_since_last_flush_ = true;
- }
- }
-
- // Release shared memory and move tasks with completed uploads
- // to |completed_raster_tasks_|.
- for (RasterTask::Vector::const_iterator it =
- tasks_with_completed_uploads.begin();
- it != tasks_with_completed_uploads.end(); ++it) {
- RasterTask* task = it->get();
- RasterTaskState::Vector::iterator state_it =
- std::find_if(raster_task_states_.begin(), raster_task_states_.end(),
- RasterTaskState::TaskComparator(task));
- DCHECK(state_it != raster_task_states_.end());
- RasterTaskState& state = *state_it;
-
- // We can use UncheckedMemorySizeBytes here, since these tasks come from
- // tiles, the size of which is controlled by the compositor.
- bytes_pending_upload_ -= Resource::UncheckedMemorySizeBytes(
- task->resource()->size(), task->resource()->format());
-
- task->WillComplete();
- task->CompleteOnOriginThread(this);
- task->DidComplete();
-
- DCHECK(std::find(completed_raster_tasks_.begin(),
- completed_raster_tasks_.end(),
- task) == completed_raster_tasks_.end());
- completed_raster_tasks_.push_back(task);
- state.type = RasterTaskState::COMPLETED;
- // Triggers if the current task belongs to a set that should be empty.
- DCHECK((state.task_sets & ~NonEmptyTaskSetsFromTaskCounts(task_counts_))
- .none());
- RemoveTaskSetsFromTaskCounts(task_counts_, state.task_sets);
- }
-}
-
-void PixelBufferTileTaskWorkerPool::CheckForCompletedRasterTasks() {
- TRACE_EVENT0("cc",
- "PixelBufferTileTaskWorkerPool::CheckForCompletedRasterTasks");
-
- // Since this function can be called directly, cancel any pending checks.
- check_for_completed_raster_task_notifier_.Cancel();
-
- DCHECK(should_notify_client_if_no_tasks_are_pending_.any());
-
- CheckForCompletedRasterizerTasks();
- CheckForCompletedUploads();
- FlushUploads();
-
- // Determine what client notifications to generate.
- TaskSetCollection will_notify_client_that_no_tasks_are_pending =
- should_notify_client_if_no_tasks_are_pending_ &
- ~task_set_finished_tasks_pending_ & ~PendingTasks();
-
- // Adjust the need to generate notifications before scheduling more tasks.
- should_notify_client_if_no_tasks_are_pending_ &=
- ~will_notify_client_that_no_tasks_are_pending;
-
- scheduled_raster_task_count_ = 0;
- if (PendingRasterTaskCount())
- ScheduleMoreTasks();
-
- TRACE_EVENT_ASYNC_STEP_INTO1("cc", "ScheduledTasks", this, StateName(),
- "state", StateAsValue());
-
- // Schedule another check for completed raster tasks while there are
- // pending raster tasks or pending uploads.
- if (PendingTasks().any())
- check_for_completed_raster_task_notifier_.Schedule();
-
- if (should_notify_client_if_no_tasks_are_pending_.none())
- TRACE_EVENT_ASYNC_END0("cc", "ScheduledTasks", this);
-
- // Generate client notifications.
- for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) {
- if (will_notify_client_that_no_tasks_are_pending[task_set]) {
- DCHECK(!PendingTasks()[task_set]);
- client_->DidFinishRunningTileTasks(task_set);
- }
- }
-}
-
-void PixelBufferTileTaskWorkerPool::ScheduleMoreTasks() {
- TRACE_EVENT0("cc", "PixelBufferTileTaskWorkerPool::ScheduleMoreTasks");
-
- RasterTaskVector tasks[kNumberOfTaskSets];
-
- size_t priority = kTileTaskPriorityBase;
-
- graph_.Reset();
-
- size_t bytes_pending_upload = bytes_pending_upload_;
- TaskSetCollection did_throttle_raster_tasks;
- size_t scheduled_raster_task_count = 0;
-
- for (TileTaskQueue::Item::Vector::const_iterator it =
- raster_tasks_.items.begin();
- it != raster_tasks_.items.end(); ++it) {
- const TileTaskQueue::Item& item = *it;
- RasterTask* task = item.task;
- DCHECK(item.task_sets.any());
-
- // |raster_task_states_| contains the state of all tasks that we have not
- // yet run reply callbacks for.
- RasterTaskState::Vector::iterator state_it =
- std::find_if(raster_task_states_.begin(), raster_task_states_.end(),
- RasterTaskState::TaskComparator(task));
- if (state_it == raster_task_states_.end())
- continue;
-
- RasterTaskState& state = *state_it;
-
- // Skip task if completed.
- if (state.type == RasterTaskState::COMPLETED) {
- DCHECK(std::find(completed_raster_tasks_.begin(),
- completed_raster_tasks_.end(),
- task) != completed_raster_tasks_.end());
- continue;
- }
-
- // All raster tasks need to be throttled by bytes of pending uploads,
- // but if it's the only task allow it to complete no matter what its size,
- // to prevent starvation of the task queue.
- size_t new_bytes_pending_upload = bytes_pending_upload;
- // We can use UncheckedMemorySizeBytes here, since these tasks come from
- // tiles, the size of which is controlled by the compositor.
- new_bytes_pending_upload += Resource::UncheckedMemorySizeBytes(
- task->resource()->size(), task->resource()->format());
- if (new_bytes_pending_upload > max_bytes_pending_upload_ &&
- bytes_pending_upload) {
- did_throttle_raster_tasks |= item.task_sets;
- continue;
- }
-
- // If raster has finished, just update |bytes_pending_upload|.
- if (state.type == RasterTaskState::UPLOADING) {
- DCHECK(!task->HasCompleted());
- bytes_pending_upload = new_bytes_pending_upload;
- continue;
- }
-
- // Throttle raster tasks based on kMaxScheduledRasterTasks.
- if (scheduled_raster_task_count >= kMaxScheduledRasterTasks) {
- did_throttle_raster_tasks |= item.task_sets;
- continue;
- }
-
- // Update |bytes_pending_upload| now that task has cleared all
- // throttling limits.
- bytes_pending_upload = new_bytes_pending_upload;
-
- DCHECK(state.type == RasterTaskState::UNSCHEDULED ||
- state.type == RasterTaskState::SCHEDULED);
- state.type = RasterTaskState::SCHEDULED;
-
- InsertNodesForRasterTask(&graph_, task, task->dependencies(), priority++);
-
- ++scheduled_raster_task_count;
- for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) {
- if (item.task_sets[task_set])
- tasks[task_set].container().push_back(task);
- }
- }
-
- // Cancel existing OnTaskSetFinished callbacks.
- task_set_finished_weak_ptr_factory_.InvalidateWeakPtrs();
-
- scoped_refptr<TileTask> new_task_set_finished_tasks[kNumberOfTaskSets];
- size_t scheduled_task_counts[kNumberOfTaskSets] = {0};
-
- for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) {
- scheduled_task_counts[task_set] = tasks[task_set].container().size();
- DCHECK_LE(scheduled_task_counts[task_set], task_counts_[task_set]);
- // Schedule OnTaskSetFinished call for task set only when notification is
- // pending and throttling is not preventing all pending tasks in the set
- // from being scheduled.
- if (!did_throttle_raster_tasks[task_set] &&
- should_notify_client_if_no_tasks_are_pending_[task_set]) {
- new_task_set_finished_tasks[task_set] = CreateTaskSetFinishedTask(
- task_runner_.get(),
- base::Bind(&PixelBufferTileTaskWorkerPool::OnTaskSetFinished,
- task_set_finished_weak_ptr_factory_.GetWeakPtr(),
- task_set));
- task_set_finished_tasks_pending_[task_set] = true;
- InsertNodeForTask(&graph_, new_task_set_finished_tasks[task_set].get(),
- kTaskSetFinishedTaskPriorityBase + task_set,
- scheduled_task_counts[task_set]);
- for (RasterTaskVector::ContainerType::const_iterator it =
- tasks[task_set].container().begin();
- it != tasks[task_set].container().end(); ++it) {
- graph_.edges.push_back(
- TaskGraph::Edge(*it, new_task_set_finished_tasks[task_set].get()));
- }
- }
- }
-
- DCHECK_LE(scheduled_raster_task_count, PendingRasterTaskCount());
-
- ScheduleTasksOnOriginThread(this, &graph_);
- task_graph_runner_->ScheduleTasks(namespace_token_, &graph_);
-
- scheduled_raster_task_count_ = scheduled_raster_task_count;
-
- std::copy(new_task_set_finished_tasks,
- new_task_set_finished_tasks + kNumberOfTaskSets,
- task_set_finished_tasks_);
-}
-
-size_t PixelBufferTileTaskWorkerPool::PendingRasterTaskCount() const {
- size_t num_completed_raster_tasks =
- raster_tasks_with_pending_upload_.size() + completed_raster_tasks_.size();
- DCHECK_GE(raster_task_states_.size(), num_completed_raster_tasks);
- return raster_task_states_.size() - num_completed_raster_tasks;
-}
-
-TaskSetCollection PixelBufferTileTaskWorkerPool::PendingTasks() const {
- return NonEmptyTaskSetsFromTaskCounts(task_counts_);
-}
-
-const char* PixelBufferTileTaskWorkerPool::StateName() const {
- if (scheduled_raster_task_count_)
- return "rasterizing";
- if (PendingRasterTaskCount())
- return "throttled";
- if (!raster_tasks_with_pending_upload_.empty())
- return "waiting_for_uploads";
-
- return "finishing";
-}
-
-void PixelBufferTileTaskWorkerPool::CheckForCompletedRasterizerTasks() {
- TRACE_EVENT0(
- "cc", "PixelBufferTileTaskWorkerPool::CheckForCompletedRasterizerTasks");
-
- task_graph_runner_->CollectCompletedTasks(namespace_token_,
- &completed_tasks_);
- for (Task::Vector::const_iterator it = completed_tasks_.begin();
- it != completed_tasks_.end(); ++it) {
- TileTask* task = static_cast<TileTask*>(it->get());
-
- RasterTask* raster_task = task->AsRasterTask();
- if (!raster_task) {
- task->WillComplete();
- task->CompleteOnOriginThread(this);
- task->DidComplete();
-
- completed_image_decode_tasks_.push_back(task);
- continue;
- }
-
- RasterTaskState::Vector::iterator state_it =
- std::find_if(raster_task_states_.begin(), raster_task_states_.end(),
- RasterTaskState::TaskComparator(raster_task));
- DCHECK(state_it != raster_task_states_.end());
-
- RasterTaskState& state = *state_it;
- DCHECK_EQ(RasterTaskState::SCHEDULED, state.type);
-
- resource_provider_->UnmapPixelBuffer(raster_task->resource()->id());
-
- if (!raster_task->HasFinishedRunning()) {
- // When priorites change, a raster task can be canceled as a result of
- // no longer being of high enough priority to fit in our throttled
- // raster task budget. The task has not yet completed in this case.
- raster_task->WillComplete();
- raster_task->CompleteOnOriginThread(this);
- raster_task->DidComplete();
-
- TileTaskQueue::Item::Vector::const_iterator item_it =
- std::find_if(raster_tasks_.items.begin(), raster_tasks_.items.end(),
- TileTaskQueue::Item::TaskComparator(raster_task));
- if (item_it != raster_tasks_.items.end()) {
- state.type = RasterTaskState::UNSCHEDULED;
- continue;
- }
-
- DCHECK(std::find(completed_raster_tasks_.begin(),
- completed_raster_tasks_.end(),
- raster_task) == completed_raster_tasks_.end());
- completed_raster_tasks_.push_back(raster_task);
- state.type = RasterTaskState::COMPLETED;
- // Triggers if the current task belongs to a set that should be empty.
- DCHECK((state.task_sets & ~NonEmptyTaskSetsFromTaskCounts(task_counts_))
- .none());
- RemoveTaskSetsFromTaskCounts(task_counts_, state.task_sets);
- continue;
- }
-
- resource_provider_->BeginSetPixels(raster_task->resource()->id());
- has_performed_uploads_since_last_flush_ = true;
-
- // We can use UncheckedMemorySizeBytes here, since these tasks come from
- // tiles, the size of which is controlled by the compositor.
- bytes_pending_upload_ += Resource::UncheckedMemorySizeBytes(
- raster_task->resource()->size(), raster_task->resource()->format());
- raster_tasks_with_pending_upload_.push_back(raster_task);
- state.type = RasterTaskState::UPLOADING;
- }
- completed_tasks_.clear();
-}
-
-scoped_refptr<base::trace_event::ConvertableToTraceFormat>
-PixelBufferTileTaskWorkerPool::StateAsValue() const {
- scoped_refptr<base::trace_event::TracedValue> state =
- new base::trace_event::TracedValue();
- state->SetInteger("completed_count",
- static_cast<int>(completed_raster_tasks_.size()));
- state->BeginArray("pending_count");
- for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set)
- state->AppendInteger(static_cast<int>(task_counts_[task_set]));
- state->EndArray();
- state->SetInteger("pending_upload_count",
- static_cast<int>(raster_tasks_with_pending_upload_.size()));
- state->BeginDictionary("throttle_state");
- ThrottleStateAsValueInto(state.get());
- state->EndDictionary();
- return state;
-}
-
-void PixelBufferTileTaskWorkerPool::ThrottleStateAsValueInto(
- base::trace_event::TracedValue* throttle_state) const {
- throttle_state->SetInteger(
- "bytes_available_for_upload",
- static_cast<int>(max_bytes_pending_upload_ - bytes_pending_upload_));
- throttle_state->SetInteger("bytes_pending_upload",
- static_cast<int>(bytes_pending_upload_));
- throttle_state->SetInteger("scheduled_raster_task_count",
- static_cast<int>(scheduled_raster_task_count_));
-}
-
-} // namespace cc
diff --git a/chromium/cc/raster/pixel_buffer_tile_task_worker_pool.h b/chromium/cc/raster/pixel_buffer_tile_task_worker_pool.h
deleted file mode 100644
index 2c6aeb98228..00000000000
--- a/chromium/cc/raster/pixel_buffer_tile_task_worker_pool.h
+++ /dev/null
@@ -1,146 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CC_RASTER_PIXEL_BUFFER_TILE_TASK_WORKER_POOL_H_
-#define CC_RASTER_PIXEL_BUFFER_TILE_TASK_WORKER_POOL_H_
-
-#include <deque>
-#include <vector>
-
-#include "base/memory/weak_ptr.h"
-#include "base/values.h"
-#include "cc/base/delayed_unique_notifier.h"
-#include "cc/output/context_provider.h"
-#include "cc/raster/tile_task_runner.h"
-#include "cc/raster/tile_task_worker_pool.h"
-
-namespace base {
-namespace trace_event {
-class ConvertableToTraceFormat;
-class TracedValue;
-}
-}
-
-namespace cc {
-class ResourceProvider;
-
-class CC_EXPORT PixelBufferTileTaskWorkerPool : public TileTaskWorkerPool,
- public TileTaskRunner,
- public TileTaskClient {
- public:
- ~PixelBufferTileTaskWorkerPool() override;
-
- static scoped_ptr<TileTaskWorkerPool> Create(
- base::SequencedTaskRunner* task_runner,
- TaskGraphRunner* task_graph_runner,
- ContextProvider* context_provider,
- ResourceProvider* resource_provider,
- size_t max_transfer_buffer_usage_bytes);
-
- // Overridden from TileTaskWorkerPool:
- TileTaskRunner* AsTileTaskRunner() override;
-
- // Overridden from TileTaskRunner:
- void SetClient(TileTaskRunnerClient* client) override;
- void Shutdown() override;
- void ScheduleTasks(TileTaskQueue* queue) override;
- void CheckForCompletedTasks() override;
- ResourceFormat GetResourceFormat() const override;
- bool GetResourceRequiresSwizzle() const override;
-
- // Overridden from TileTaskClient:
- scoped_ptr<RasterBuffer> AcquireBufferForRaster(
- const Resource* resource,
- uint64_t resource_content_id,
- uint64_t previous_content_id) override;
- void ReleaseBufferForRaster(scoped_ptr<RasterBuffer> buffer) override;
-
- private:
- struct RasterTaskState {
- class TaskComparator {
- public:
- explicit TaskComparator(const RasterTask* task) : task_(task) {}
-
- bool operator()(const RasterTaskState& state) const {
- return state.task == task_;
- }
-
- private:
- const RasterTask* task_;
- };
-
- typedef std::vector<RasterTaskState> Vector;
-
- RasterTaskState(RasterTask* task, const TaskSetCollection& task_sets);
-
- enum { UNSCHEDULED, SCHEDULED, UPLOADING, COMPLETED } type;
- RasterTask* task;
- TaskSetCollection task_sets;
- };
-
- typedef std::deque<scoped_refptr<RasterTask>> RasterTaskDeque;
-
- PixelBufferTileTaskWorkerPool(base::SequencedTaskRunner* task_runner,
- TaskGraphRunner* task_graph_runner,
- ContextProvider* context_provider,
- ResourceProvider* resource_provider,
- size_t max_transfer_buffer_usage_bytes);
-
- void OnTaskSetFinished(TaskSet task_set);
- void FlushUploads();
- void CheckForCompletedUploads();
- void CheckForCompletedRasterTasks();
- void ScheduleMoreTasks();
- size_t PendingRasterTaskCount() const;
- TaskSetCollection PendingTasks() const;
- void CheckForCompletedRasterizerTasks();
-
- const char* StateName() const;
- scoped_refptr<base::trace_event::ConvertableToTraceFormat> StateAsValue()
- const;
- void ThrottleStateAsValueInto(
- base::trace_event::TracedValue* throttle_state) const;
-
- scoped_refptr<base::SequencedTaskRunner> task_runner_;
- TaskGraphRunner* task_graph_runner_;
- const NamespaceToken namespace_token_;
- TileTaskRunnerClient* client_;
- ContextProvider* context_provider_;
- ResourceProvider* resource_provider_;
-
- bool shutdown_;
-
- TileTaskQueue raster_tasks_;
- RasterTaskState::Vector raster_task_states_;
- RasterTaskDeque raster_tasks_with_pending_upload_;
- RasterTask::Vector completed_raster_tasks_;
- TileTask::Vector completed_image_decode_tasks_;
-
- size_t scheduled_raster_task_count_;
- size_t task_counts_[kNumberOfTaskSets];
- size_t bytes_pending_upload_;
- size_t max_bytes_pending_upload_;
- bool has_performed_uploads_since_last_flush_;
-
- TaskSetCollection should_notify_client_if_no_tasks_are_pending_;
- TaskSetCollection task_set_finished_tasks_pending_;
-
- DelayedUniqueNotifier check_for_completed_raster_task_notifier_;
-
- scoped_refptr<TileTask> task_set_finished_tasks_[kNumberOfTaskSets];
-
- // Task graph used when scheduling tasks and vector used to gather
- // completed tasks.
- TaskGraph graph_;
- Task::Vector completed_tasks_;
-
- base::WeakPtrFactory<PixelBufferTileTaskWorkerPool>
- task_set_finished_weak_ptr_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(PixelBufferTileTaskWorkerPool);
-};
-
-} // namespace cc
-
-#endif // CC_RASTER_PIXEL_BUFFER_TILE_TASK_WORKER_POOL_H_
diff --git a/chromium/cc/raster/raster_buffer.h b/chromium/cc/raster/raster_buffer.h
index 5af4deca25b..ac4e74ca802 100644
--- a/chromium/cc/raster/raster_buffer.h
+++ b/chromium/cc/raster/raster_buffer.h
@@ -20,7 +20,8 @@ class CC_EXPORT RasterBuffer {
const gfx::Rect& raster_full_rect,
const gfx::Rect& raster_dirty_rect,
uint64_t new_content_id,
- float scale) = 0;
+ float scale,
+ bool include_images) = 0;
};
} // namespace cc
diff --git a/chromium/cc/raster/scoped_gpu_raster.cc b/chromium/cc/raster/scoped_gpu_raster.cc
index f548515b698..e6dcf231ba2 100644
--- a/chromium/cc/raster/scoped_gpu_raster.cc
+++ b/chromium/cc/raster/scoped_gpu_raster.cc
@@ -27,7 +27,7 @@ void ScopedGpuRaster::BeginGpuRaster() {
// TODO(alokp): Use a trace macro to push/pop markers.
// Using push/pop functions directly incurs cost to evaluate function
// arguments even when tracing is disabled.
- gl->PushGroupMarkerEXT(0, "GpuRasterization");
+ gl->TraceBeginCHROMIUM("ScopedGpuRaster", "GpuRasterization");
class GrContext* gr_context = context_provider_->GrContext();
gr_context->resetContext();
@@ -45,7 +45,7 @@ void ScopedGpuRaster::EndGpuRaster() {
// TODO(alokp): Use a trace macro to push/pop markers.
// Using push/pop functions directly incurs cost to evaluate function
// arguments even when tracing is disabled.
- gl->PopGroupMarkerEXT();
+ gl->TraceEndCHROMIUM();
}
} // namespace cc
diff --git a/chromium/cc/raster/task_graph_runner.cc b/chromium/cc/raster/task_graph_runner.cc
index c810aa59c0b..4fbf56e31bd 100644
--- a/chromium/cc/raster/task_graph_runner.cc
+++ b/chromium/cc/raster/task_graph_runner.cc
@@ -6,6 +6,7 @@
#include <algorithm>
+#include "base/containers/hash_tables.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_restrictions.h"
#include "base/trace_event/trace_event.h"
@@ -68,34 +69,19 @@ class DependentIterator {
TaskGraph::Node* current_node_;
};
-class DependencyMismatchComparator {
- public:
- explicit DependencyMismatchComparator(const TaskGraph* graph)
- : graph_(graph) {}
-
- bool operator()(const TaskGraph::Node& node) const {
- return static_cast<size_t>(std::count_if(graph_->edges.begin(),
- graph_->edges.end(),
- DependentComparator(node.task))) !=
- node.dependencies;
- }
-
- private:
- class DependentComparator {
- public:
- explicit DependentComparator(const Task* dependent)
- : dependent_(dependent) {}
+bool DependencyMismatch(const TaskGraph* graph) {
+ // Value storage will be 0-initialized.
+ base::hash_map<const Task*, size_t> dependents;
+ for (const TaskGraph::Edge& edge : graph->edges)
+ dependents[edge.dependent]++;
- bool operator()(const TaskGraph::Edge& edge) const {
- return edge.dependent == dependent_;
- }
-
- private:
- const Task* dependent_;
- };
+ for (const TaskGraph::Node& node : graph->nodes) {
+ if (dependents[node.task] != node.dependencies)
+ return true;
+ }
- const TaskGraph* graph_;
-};
+ return false;
+}
} // namespace
@@ -171,10 +157,7 @@ void TaskGraphRunner::ScheduleTasks(NamespaceToken token, TaskGraph* graph) {
graph->edges.size());
DCHECK(token.IsValid());
- DCHECK(std::find_if(graph->nodes.begin(),
- graph->nodes.end(),
- DependencyMismatchComparator(graph)) ==
- graph->nodes.end());
+ DCHECK(!DependencyMismatch(graph));
{
base::AutoLock lock(lock_);
@@ -349,6 +332,18 @@ void TaskGraphRunner::Shutdown() {
has_ready_to_run_tasks_cv_.Signal();
}
+void TaskGraphRunner::FlushForTesting() {
+ base::AutoLock lock(lock_);
+
+ while (std::find_if(namespaces_.begin(), namespaces_.end(),
+ [](const TaskNamespaceMap::value_type& entry) {
+ return !HasFinishedRunningTasksInNamespace(
+ &entry.second);
+ }) != namespaces_.end()) {
+ has_namespaces_with_finished_running_tasks_cv_.Wait();
+ }
+}
+
void TaskGraphRunner::Run() {
base::AutoLock lock(lock_);
diff --git a/chromium/cc/raster/task_graph_runner.h b/chromium/cc/raster/task_graph_runner.h
index bb55afc19ae..d6d41917998 100644
--- a/chromium/cc/raster/task_graph_runner.h
+++ b/chromium/cc/raster/task_graph_runner.h
@@ -137,6 +137,9 @@ class CC_EXPORT TaskGraphRunner {
// Warning: if the TaskGraphRunner remains busy, it may never quit.
void Shutdown();
+ // Wait for all the tasks to finish running on all the namespaces.
+ void FlushForTesting();
+
private:
struct PrioritizedTask {
typedef std::vector<PrioritizedTask> Vector;
diff --git a/chromium/cc/raster/tile_task_runner.cc b/chromium/cc/raster/tile_task_runner.cc
index 5450c5f777e..ce568f95ab0 100644
--- a/chromium/cc/raster/tile_task_runner.cc
+++ b/chromium/cc/raster/tile_task_runner.cc
@@ -16,14 +16,6 @@ TileTask::~TileTask() {
DCHECK(!did_run_ || did_complete_);
}
-ImageDecodeTask* TileTask::AsImageDecodeTask() {
- return NULL;
-}
-
-RasterTask* TileTask::AsRasterTask() {
- return NULL;
-}
-
void TileTask::WillSchedule() {
DCHECK(!did_schedule_);
}
@@ -58,23 +50,13 @@ ImageDecodeTask::ImageDecodeTask() {
ImageDecodeTask::~ImageDecodeTask() {
}
-ImageDecodeTask* ImageDecodeTask::AsImageDecodeTask() {
- return this;
-}
-
-RasterTask::RasterTask(const Resource* resource,
- ImageDecodeTask::Vector* dependencies)
- : resource_(resource) {
+RasterTask::RasterTask(ImageDecodeTask::Vector* dependencies) {
dependencies_.swap(*dependencies);
}
RasterTask::~RasterTask() {
}
-RasterTask* RasterTask::AsRasterTask() {
- return this;
-}
-
TileTaskQueue::Item::Item(RasterTask* task, const TaskSetCollection& task_sets)
: task(task), task_sets(task_sets) {
DCHECK(task_sets.any());
diff --git a/chromium/cc/raster/tile_task_runner.h b/chromium/cc/raster/tile_task_runner.h
index 9dffee48c74..103da1fa275 100644
--- a/chromium/cc/raster/tile_task_runner.h
+++ b/chromium/cc/raster/tile_task_runner.h
@@ -36,11 +36,6 @@ class CC_EXPORT TileTask : public Task {
virtual void ScheduleOnOriginThread(TileTaskClient* client) = 0;
virtual void CompleteOnOriginThread(TileTaskClient* client) = 0;
- virtual void RunReplyOnOriginThread() = 0;
-
- // Type-checking downcast routines.
- virtual ImageDecodeTask* AsImageDecodeTask();
- virtual RasterTask* AsRasterTask();
void WillSchedule();
void DidSchedule();
@@ -62,9 +57,6 @@ class CC_EXPORT ImageDecodeTask : public TileTask {
public:
typedef std::vector<scoped_refptr<ImageDecodeTask>> Vector;
- // Overridden from TileTask:
- ImageDecodeTask* AsImageDecodeTask() override;
-
protected:
ImageDecodeTask();
~ImageDecodeTask() override;
@@ -74,18 +66,13 @@ class CC_EXPORT RasterTask : public TileTask {
public:
typedef std::vector<scoped_refptr<RasterTask>> Vector;
- // Overridden from TileTask:
- RasterTask* AsRasterTask() override;
-
- const Resource* resource() const { return resource_; }
const ImageDecodeTask::Vector& dependencies() const { return dependencies_; }
protected:
- RasterTask(const Resource* resource, ImageDecodeTask::Vector* dependencies);
+ explicit RasterTask(ImageDecodeTask::Vector* dependencies);
~RasterTask() override;
private:
- const Resource* resource_;
ImageDecodeTask::Vector dependencies_;
};
@@ -100,7 +87,6 @@ typedef std::bitset<kNumberOfTaskSets> TaskSetCollection;
class CC_EXPORT TileTaskRunnerClient {
public:
virtual void DidFinishRunningTileTasks(TaskSet task_set) = 0;
- virtual TaskSetCollection TasksThatShouldBeForcedToComplete() const = 0;
protected:
virtual ~TileTaskRunnerClient() {}
@@ -163,10 +149,10 @@ class CC_EXPORT TileTaskRunner {
virtual void CheckForCompletedTasks() = 0;
// Returns the format to use for the tiles.
- virtual ResourceFormat GetResourceFormat() const = 0;
+ virtual ResourceFormat GetResourceFormat(bool must_support_alpha) const = 0;
// Determine if the resource requires swizzling.
- virtual bool GetResourceRequiresSwizzle() const = 0;
+ virtual bool GetResourceRequiresSwizzle(bool must_support_alpha) const = 0;
protected:
virtual ~TileTaskRunner() {}
diff --git a/chromium/cc/raster/tile_task_worker_pool.cc b/chromium/cc/raster/tile_task_worker_pool.cc
index d349514c4e8..b1d7b70a229 100644
--- a/chromium/cc/raster/tile_task_worker_pool.cc
+++ b/chromium/cc/raster/tile_task_worker_pool.cc
@@ -10,6 +10,7 @@
#include "cc/playback/raster_source.h"
#include "skia/ext/refptr.h"
#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkDrawFilter.h"
#include "third_party/skia/include/core/SkSurface.h"
namespace cc {
@@ -32,7 +33,6 @@ class TaskSetFinishedTaskImpl : public TileTask {
// Overridden from TileTask:
void ScheduleOnOriginThread(TileTaskClient* client) override {}
void CompleteOnOriginThread(TileTaskClient* client) override {}
- void RunReplyOnOriginThread() override {}
protected:
~TaskSetFinishedTaskImpl() override {}
@@ -153,6 +153,17 @@ static bool IsSupportedPlaybackToMemoryFormat(ResourceFormat format) {
return false;
}
+class SkipImageFilter : public SkDrawFilter {
+ public:
+ bool filter(SkPaint* paint, Type type) override {
+ if (type == kBitmap_Type)
+ return false;
+
+ SkShader* shader = paint->getShader();
+ return !shader || !shader->isABitmap();
+ }
+};
+
// static
void TileTaskWorkerPool::PlaybackToMemory(void* memory,
ResourceFormat format,
@@ -161,7 +172,10 @@ void TileTaskWorkerPool::PlaybackToMemory(void* memory,
const RasterSource* raster_source,
const gfx::Rect& canvas_bitmap_rect,
const gfx::Rect& canvas_playback_rect,
- float scale) {
+ float scale,
+ bool include_images) {
+ TRACE_EVENT0("cc", "TileTaskWorkerPool::PlaybackToMemory");
+
DCHECK(IsSupportedPlaybackToMemoryFormat(format)) << format;
// Uses kPremul_SkAlphaType since the result is not known to be opaque.
@@ -181,10 +195,15 @@ void TileTaskWorkerPool::PlaybackToMemory(void* memory,
stride = info.minRowBytes();
DCHECK_GT(stride, 0u);
+ skia::RefPtr<SkDrawFilter> image_filter;
+ if (!include_images)
+ image_filter = skia::AdoptRef(new SkipImageFilter);
+
if (!needs_copy) {
skia::RefPtr<SkSurface> surface = skia::AdoptRef(
SkSurface::NewRasterDirect(info, memory, stride, &surface_props));
skia::RefPtr<SkCanvas> canvas = skia::SharePtr(surface->getCanvas());
+ canvas->setDrawFilter(image_filter.get());
raster_source->PlaybackToCanvas(canvas.get(), canvas_bitmap_rect,
canvas_playback_rect, scale);
return;
@@ -193,19 +212,26 @@ void TileTaskWorkerPool::PlaybackToMemory(void* memory,
skia::RefPtr<SkSurface> surface =
skia::AdoptRef(SkSurface::NewRaster(info, &surface_props));
skia::RefPtr<SkCanvas> canvas = skia::SharePtr(surface->getCanvas());
+ canvas->setDrawFilter(image_filter.get());
+ // TODO(reveman): Improve partial raster support by reducing the size of
+ // playback rect passed to PlaybackToCanvas. crbug.com/519070
raster_source->PlaybackToCanvas(canvas.get(), canvas_bitmap_rect,
- canvas_playback_rect, scale);
-
- SkImageInfo dst_info =
- SkImageInfo::Make(info.width(), info.height(), buffer_color_type,
- info.alphaType(), info.profileType());
- // TODO(kaanb): The GL pipeline assumes a 4-byte alignment for the
- // bitmap data. There will be no need to call SkAlign4 once crbug.com/293728
- // is fixed.
- const size_t dst_row_bytes = SkAlign4(dst_info.minRowBytes());
- DCHECK_EQ(0u, dst_row_bytes % 4);
- bool success = canvas->readPixels(dst_info, memory, dst_row_bytes, 0, 0);
- DCHECK_EQ(true, success);
+ canvas_bitmap_rect, scale);
+
+ {
+ TRACE_EVENT0("cc", "TileTaskWorkerPool::PlaybackToMemory::ConvertPixels");
+
+ SkImageInfo dst_info =
+ SkImageInfo::Make(info.width(), info.height(), buffer_color_type,
+ info.alphaType(), info.profileType());
+ // TODO(kaanb): The GL pipeline assumes a 4-byte alignment for the
+ // bitmap data. There will be no need to call SkAlign4 once crbug.com/293728
+ // is fixed.
+ const size_t dst_row_bytes = SkAlign4(dst_info.minRowBytes());
+ DCHECK_EQ(0u, dst_row_bytes % 4);
+ bool success = canvas->readPixels(dst_info, memory, dst_row_bytes, 0, 0);
+ DCHECK_EQ(true, success);
+ }
}
} // namespace cc
diff --git a/chromium/cc/raster/tile_task_worker_pool.h b/chromium/cc/raster/tile_task_worker_pool.h
index ff001890507..0fc9d3f35e9 100644
--- a/chromium/cc/raster/tile_task_worker_pool.h
+++ b/chromium/cc/raster/tile_task_worker_pool.h
@@ -66,7 +66,8 @@ class CC_EXPORT TileTaskWorkerPool {
const RasterSource* raster_source,
const gfx::Rect& canvas_bitmap_rect,
const gfx::Rect& canvas_playback_rect,
- float scale);
+ float scale,
+ bool include_images);
// Type-checking downcast routine.
virtual TileTaskRunner* AsTileTaskRunner() = 0;
diff --git a/chromium/cc/raster/tile_task_worker_pool_perftest.cc b/chromium/cc/raster/tile_task_worker_pool_perftest.cc
index b49c498ac05..2605064799e 100644
--- a/chromium/cc/raster/tile_task_worker_pool_perftest.cc
+++ b/chromium/cc/raster/tile_task_worker_pool_perftest.cc
@@ -12,7 +12,6 @@
#include "cc/raster/gpu_rasterizer.h"
#include "cc/raster/gpu_tile_task_worker_pool.h"
#include "cc/raster/one_copy_tile_task_worker_pool.h"
-#include "cc/raster/pixel_buffer_tile_task_worker_pool.h"
#include "cc/raster/raster_buffer.h"
#include "cc/raster/tile_task_runner.h"
#include "cc/raster/zero_copy_tile_task_worker_pool.h"
@@ -114,7 +113,6 @@ class PerfContextProvider : public ContextProvider {
};
enum TileTaskWorkerPoolType {
- TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER,
TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY,
TILE_TASK_WORKER_POOL_TYPE_ONE_COPY,
TILE_TASK_WORKER_POOL_TYPE_GPU,
@@ -134,8 +132,7 @@ class PerfImageDecodeTaskImpl : public ImageDecodeTask {
// Overridden from TileTask:
void ScheduleOnOriginThread(TileTaskClient* client) override {}
- void CompleteOnOriginThread(TileTaskClient* client) override {}
- void RunReplyOnOriginThread() override { Reset(); }
+ void CompleteOnOriginThread(TileTaskClient* client) override { Reset(); }
void Reset() {
did_run_ = false;
@@ -153,7 +150,7 @@ class PerfRasterTaskImpl : public RasterTask {
public:
PerfRasterTaskImpl(scoped_ptr<ScopedResource> resource,
ImageDecodeTask::Vector* dependencies)
- : RasterTask(resource.get(), dependencies), resource_(resource.Pass()) {}
+ : RasterTask(dependencies), resource_(resource.Pass()) {}
// Overridden from Task:
void RunOnWorkerThread() override {}
@@ -161,12 +158,12 @@ class PerfRasterTaskImpl : public RasterTask {
// Overridden from TileTask:
void ScheduleOnOriginThread(TileTaskClient* client) override {
// No tile ids are given to support partial updates.
- raster_buffer_ = client->AcquireBufferForRaster(resource(), 0, 0);
+ raster_buffer_ = client->AcquireBufferForRaster(resource_.get(), 0, 0);
}
void CompleteOnOriginThread(TileTaskClient* client) override {
client->ReleaseBufferForRaster(raster_buffer_.Pass());
+ Reset();
}
- void RunReplyOnOriginThread() override { Reset(); }
void Reset() {
did_run_ = false;
@@ -250,28 +247,19 @@ class TileTaskWorkerPoolPerfTest
// Overridden from testing::Test:
void SetUp() override {
switch (GetParam()) {
- case TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER:
- Create3dOutputSurfaceAndResourceProvider();
- tile_task_worker_pool_ = PixelBufferTileTaskWorkerPool::Create(
- task_runner_.get(), task_graph_runner_.get(),
- context_provider_.get(), resource_provider_.get(),
- std::numeric_limits<size_t>::max());
- break;
case TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY:
Create3dOutputSurfaceAndResourceProvider();
tile_task_worker_pool_ = ZeroCopyTileTaskWorkerPool::Create(
task_runner_.get(), task_graph_runner_.get(),
- resource_provider_.get());
+ resource_provider_.get(), false);
break;
case TILE_TASK_WORKER_POOL_TYPE_ONE_COPY:
Create3dOutputSurfaceAndResourceProvider();
- staging_resource_pool_ = ResourcePool::Create(resource_provider_.get(),
- GL_TEXTURE_2D);
tile_task_worker_pool_ = OneCopyTileTaskWorkerPool::Create(
task_runner_.get(), task_graph_runner_.get(),
context_provider_.get(), resource_provider_.get(),
- staging_resource_pool_.get(), std::numeric_limits<int>::max(),
- false);
+ std::numeric_limits<int>::max(), false,
+ std::numeric_limits<int>::max(), false);
break;
case TILE_TASK_WORKER_POOL_TYPE_GPU:
Create3dOutputSurfaceAndResourceProvider();
@@ -299,9 +287,6 @@ class TileTaskWorkerPoolPerfTest
void DidFinishRunningTileTasks(TaskSet task_set) override {
tile_task_worker_pool_->AsTileTaskRunner()->CheckForCompletedTasks();
}
- TaskSetCollection TasksThatShouldBeForcedToComplete() const override {
- return TaskSetCollection();
- }
void RunMessageLoopUntilAllTasksHaveCompleted() {
task_graph_runner_->RunUntilIdle();
@@ -416,8 +401,6 @@ class TileTaskWorkerPoolPerfTest
std::string TestModifierString() const {
switch (GetParam()) {
- case TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER:
- return std::string("_pixel_tile_task_worker_pool");
case TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY:
return std::string("_zero_copy_tile_task_worker_pool");
case TILE_TASK_WORKER_POOL_TYPE_ONE_COPY:
@@ -431,7 +414,6 @@ class TileTaskWorkerPoolPerfTest
return std::string();
}
- scoped_ptr<ResourcePool> staging_resource_pool_;
scoped_ptr<TileTaskWorkerPool> tile_task_worker_pool_;
TestGpuMemoryBufferManager gpu_memory_buffer_manager_;
TestSharedBitmapManager shared_bitmap_manager_;
@@ -464,14 +446,12 @@ TEST_P(TileTaskWorkerPoolPerfTest, ScheduleAndExecuteTasks) {
RunScheduleAndExecuteTasksTest("32_4", 32, 4);
}
-INSTANTIATE_TEST_CASE_P(
- TileTaskWorkerPoolPerfTests,
- TileTaskWorkerPoolPerfTest,
- ::testing::Values(TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER,
- TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY,
- TILE_TASK_WORKER_POOL_TYPE_ONE_COPY,
- TILE_TASK_WORKER_POOL_TYPE_GPU,
- TILE_TASK_WORKER_POOL_TYPE_BITMAP));
+INSTANTIATE_TEST_CASE_P(TileTaskWorkerPoolPerfTests,
+ TileTaskWorkerPoolPerfTest,
+ ::testing::Values(TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY,
+ TILE_TASK_WORKER_POOL_TYPE_ONE_COPY,
+ TILE_TASK_WORKER_POOL_TYPE_GPU,
+ TILE_TASK_WORKER_POOL_TYPE_BITMAP));
class TileTaskWorkerPoolCommonPerfTest : public TileTaskWorkerPoolPerfTestBase,
public testing::Test {
diff --git a/chromium/cc/raster/tile_task_worker_pool_unittest.cc b/chromium/cc/raster/tile_task_worker_pool_unittest.cc
index 76e5fe4d56f..515035bed83 100644
--- a/chromium/cc/raster/tile_task_worker_pool_unittest.cc
+++ b/chromium/cc/raster/tile_task_worker_pool_unittest.cc
@@ -12,22 +12,19 @@
#include "base/single_thread_task_runner.h"
#include "base/thread_task_runner_handle.h"
#include "cc/base/unique_notifier.h"
-#include "cc/playback/picture_pile.h"
-#include "cc/playback/picture_pile_impl.h"
#include "cc/raster/bitmap_tile_task_worker_pool.h"
#include "cc/raster/gpu_rasterizer.h"
#include "cc/raster/gpu_tile_task_worker_pool.h"
#include "cc/raster/one_copy_tile_task_worker_pool.h"
-#include "cc/raster/pixel_buffer_tile_task_worker_pool.h"
#include "cc/raster/raster_buffer.h"
#include "cc/raster/tile_task_runner.h"
#include "cc/raster/zero_copy_tile_task_worker_pool.h"
#include "cc/resources/resource_pool.h"
#include "cc/resources/resource_provider.h"
#include "cc/resources/scoped_resource.h"
+#include "cc/test/fake_display_list_raster_source.h"
#include "cc/test/fake_output_surface.h"
#include "cc/test/fake_output_surface_client.h"
-#include "cc/test/fake_picture_pile_impl.h"
#include "cc/test/fake_resource_provider.h"
#include "cc/test/test_gpu_memory_buffer_manager.h"
#include "cc/test/test_shared_bitmap_manager.h"
@@ -39,15 +36,10 @@
namespace cc {
namespace {
-const size_t kMaxTransferBufferUsageBytes = 10000U;
const size_t kMaxBytesPerCopyOperation = 1000U;
-
-// A resource of this dimension^2 * 4 must be greater than the above transfer
-// buffer constant.
-const size_t kLargeResourceDimension = 1000U;
+const size_t kMaxStagingBuffers = 32U;
enum TileTaskWorkerPoolType {
- TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER,
TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY,
TILE_TASK_WORKER_POOL_TYPE_ONE_COPY,
TILE_TASK_WORKER_POOL_TYPE_GPU,
@@ -62,28 +54,27 @@ class TestRasterTaskImpl : public RasterTask {
TestRasterTaskImpl(const Resource* resource,
const Reply& reply,
ImageDecodeTask::Vector* dependencies)
- : RasterTask(resource, dependencies),
+ : RasterTask(dependencies),
+ resource_(resource),
reply_(reply),
- picture_pile_(FakePicturePileImpl::CreateEmptyPile(gfx::Size(1, 1),
- gfx::Size(1, 1))) {}
+ raster_source_(
+ FakeDisplayListRasterSource::CreateFilled(gfx::Size(1, 1))) {}
// Overridden from Task:
void RunOnWorkerThread() override {
uint64_t new_content_id = 0;
- raster_buffer_->Playback(picture_pile_.get(), gfx::Rect(1, 1),
- gfx::Rect(1, 1), new_content_id, 1.f);
+ raster_buffer_->Playback(raster_source_.get(), gfx::Rect(1, 1),
+ gfx::Rect(1, 1), new_content_id, 1.f, true);
}
// Overridden from TileTask:
void ScheduleOnOriginThread(TileTaskClient* client) override {
// The raster buffer has no tile ids associated with it for partial update,
// so doesn't need to provide a valid dirty rect.
- raster_buffer_ = client->AcquireBufferForRaster(resource(), 0, 0);
+ raster_buffer_ = client->AcquireBufferForRaster(resource_, 0, 0);
}
void CompleteOnOriginThread(TileTaskClient* client) override {
client->ReleaseBufferForRaster(raster_buffer_.Pass());
- }
- void RunReplyOnOriginThread() override {
reply_.Run(RasterSource::SolidColorAnalysis(), !HasFinishedRunning());
}
@@ -91,9 +82,10 @@ class TestRasterTaskImpl : public RasterTask {
~TestRasterTaskImpl() override {}
private:
+ const Resource* resource_;
const Reply reply_;
scoped_ptr<RasterBuffer> raster_buffer_;
- scoped_refptr<PicturePileImpl> picture_pile_;
+ scoped_refptr<RasterSource> raster_source_;
DISALLOW_COPY_AND_ASSIGN(TestRasterTaskImpl);
};
@@ -112,9 +104,6 @@ class BlockingTestRasterTaskImpl : public TestRasterTaskImpl {
TestRasterTaskImpl::RunOnWorkerThread();
}
- // Overridden from TileTask:
- void RunReplyOnOriginThread() override {}
-
protected:
~BlockingTestRasterTaskImpl() override {}
@@ -139,9 +128,10 @@ class TileTaskWorkerPoolTest
TileTaskWorkerPoolTest()
: context_provider_(TestContextProvider::Create()),
- worker_context_provider_(TestContextProvider::Create()),
+ worker_context_provider_(TestContextProvider::CreateWorker()),
all_tile_tasks_finished_(
- base::ThreadTaskRunnerHandle::Get().get(),
+ base::ThreadTaskRunnerHandle::Get()
+ .get(),
base::Bind(&TileTaskWorkerPoolTest::AllTileTasksFinished,
base::Unretained(this))),
timeout_seconds_(5),
@@ -150,27 +140,18 @@ class TileTaskWorkerPoolTest
// Overridden from testing::Test:
void SetUp() override {
switch (GetParam()) {
- case TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER:
- Create3dOutputSurfaceAndResourceProvider();
- tile_task_worker_pool_ = PixelBufferTileTaskWorkerPool::Create(
- base::ThreadTaskRunnerHandle::Get().get(), &task_graph_runner_,
- context_provider_.get(), resource_provider_.get(),
- kMaxTransferBufferUsageBytes);
- break;
case TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY:
Create3dOutputSurfaceAndResourceProvider();
tile_task_worker_pool_ = ZeroCopyTileTaskWorkerPool::Create(
base::ThreadTaskRunnerHandle::Get().get(), &task_graph_runner_,
- resource_provider_.get());
+ resource_provider_.get(), false);
break;
case TILE_TASK_WORKER_POOL_TYPE_ONE_COPY:
Create3dOutputSurfaceAndResourceProvider();
- staging_resource_pool_ = ResourcePool::Create(resource_provider_.get(),
- GL_TEXTURE_2D);
tile_task_worker_pool_ = OneCopyTileTaskWorkerPool::Create(
base::ThreadTaskRunnerHandle::Get().get(), &task_graph_runner_,
context_provider_.get(), resource_provider_.get(),
- staging_resource_pool_.get(), kMaxBytesPerCopyOperation, false);
+ kMaxBytesPerCopyOperation, false, kMaxStagingBuffers, false);
break;
case TILE_TASK_WORKER_POOL_TYPE_GPU:
Create3dOutputSurfaceAndResourceProvider();
@@ -210,10 +191,6 @@ class TileTaskWorkerPoolTest
}
}
- TaskSetCollection TasksThatShouldBeForcedToComplete() const override {
- return TaskSetCollection();
- }
-
void RunMessageLoopUntilAllTasksHaveCompleted() {
if (timeout_seconds_) {
timeout_.Reset(base::Bind(&TileTaskWorkerPoolTest::OnTimeout,
@@ -332,7 +309,6 @@ class TileTaskWorkerPoolTest
FakeOutputSurfaceClient output_surface_client_;
scoped_ptr<FakeOutputSurface> output_surface_;
scoped_ptr<ResourceProvider> resource_provider_;
- scoped_ptr<ResourcePool> staging_resource_pool_;
scoped_ptr<TileTaskWorkerPool> tile_task_worker_pool_;
TestGpuMemoryBufferManager gpu_memory_buffer_manager_;
TestSharedBitmapManager shared_bitmap_manager_;
@@ -397,30 +373,6 @@ TEST_P(TileTaskWorkerPoolTest, FalseThrottling) {
RunMessageLoopUntilAllTasksHaveCompleted();
}
-TEST_P(TileTaskWorkerPoolTest, LargeResources) {
- gfx::Size size(kLargeResourceDimension, kLargeResourceDimension);
-
- {
- // Verify a resource of this size is larger than the transfer buffer.
- scoped_ptr<ScopedResource> resource(
- ScopedResource::Create(resource_provider_.get()));
- resource->Allocate(size, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
- RGBA_8888);
- EXPECT_GE(Resource::UncheckedMemorySizeBytes(resource->size(),
- resource->format()),
- kMaxTransferBufferUsageBytes);
- }
-
- AppendTask(0u, size);
- AppendTask(1u, size);
- AppendTask(2u, size);
- ScheduleTasks();
-
- // This will time out if a resource that is larger than the throttle limit
- // never gets scheduled.
- RunMessageLoopUntilAllTasksHaveCompleted();
-}
-
TEST_P(TileTaskWorkerPoolTest, LostContext) {
LoseContext(output_surface_->context_provider());
LoseContext(output_surface_->worker_context_provider());
@@ -451,14 +403,12 @@ TEST_P(TileTaskWorkerPoolTest, ScheduleEmptyStillTriggersCallback) {
EXPECT_TRUE(completed_task_sets_[ALL]);
}
-INSTANTIATE_TEST_CASE_P(
- TileTaskWorkerPoolTests,
- TileTaskWorkerPoolTest,
- ::testing::Values(TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER,
- TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY,
- TILE_TASK_WORKER_POOL_TYPE_ONE_COPY,
- TILE_TASK_WORKER_POOL_TYPE_GPU,
- TILE_TASK_WORKER_POOL_TYPE_BITMAP));
+INSTANTIATE_TEST_CASE_P(TileTaskWorkerPoolTests,
+ TileTaskWorkerPoolTest,
+ ::testing::Values(TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY,
+ TILE_TASK_WORKER_POOL_TYPE_ONE_COPY,
+ TILE_TASK_WORKER_POOL_TYPE_GPU,
+ TILE_TASK_WORKER_POOL_TYPE_BITMAP));
} // namespace
} // namespace cc
diff --git a/chromium/cc/raster/zero_copy_tile_task_worker_pool.cc b/chromium/cc/raster/zero_copy_tile_task_worker_pool.cc
index 64fc5f453b3..0a6e80e7d1c 100644
--- a/chromium/cc/raster/zero_copy_tile_task_worker_pool.cc
+++ b/chromium/cc/raster/zero_copy_tile_task_worker_pool.cc
@@ -13,6 +13,7 @@
#include "cc/raster/raster_buffer.h"
#include "cc/resources/platform_color.h"
#include "cc/resources/resource.h"
+#include "ui/gfx/buffer_format_util.h"
#include "ui/gfx/gpu_memory_buffer.h"
namespace cc {
@@ -29,10 +30,13 @@ class RasterBufferImpl : public RasterBuffer {
const gfx::Rect& raster_full_rect,
const gfx::Rect& raster_dirty_rect,
uint64_t new_content_id,
- float scale) override {
+ float scale,
+ bool include_images) override {
gfx::GpuMemoryBuffer* gpu_memory_buffer = lock_.GetGpuMemoryBuffer();
if (!gpu_memory_buffer)
return;
+ DCHECK_EQ(
+ 1u, gfx::NumberOfPlanesForBufferFormat(gpu_memory_buffer->GetFormat()));
void* data = NULL;
bool rv = gpu_memory_buffer->Map(&data);
DCHECK(rv);
@@ -44,7 +48,7 @@ class RasterBufferImpl : public RasterBuffer {
TileTaskWorkerPool::PlaybackToMemory(
data, resource_->format(), resource_->size(),
static_cast<size_t>(stride), raster_source, raster_full_rect,
- raster_full_rect, scale);
+ raster_full_rect, scale, include_images);
gpu_memory_buffer->Unmap();
}
@@ -61,21 +65,24 @@ class RasterBufferImpl : public RasterBuffer {
scoped_ptr<TileTaskWorkerPool> ZeroCopyTileTaskWorkerPool::Create(
base::SequencedTaskRunner* task_runner,
TaskGraphRunner* task_graph_runner,
- ResourceProvider* resource_provider) {
+ ResourceProvider* resource_provider,
+ bool use_rgba_4444_texture_format) {
return make_scoped_ptr<TileTaskWorkerPool>(new ZeroCopyTileTaskWorkerPool(
- task_runner, task_graph_runner, resource_provider));
+ task_runner, task_graph_runner, resource_provider,
+ use_rgba_4444_texture_format));
}
ZeroCopyTileTaskWorkerPool::ZeroCopyTileTaskWorkerPool(
base::SequencedTaskRunner* task_runner,
TaskGraphRunner* task_graph_runner,
- ResourceProvider* resource_provider)
+ ResourceProvider* resource_provider,
+ bool use_rgba_4444_texture_format)
: task_runner_(task_runner),
task_graph_runner_(task_graph_runner),
namespace_token_(task_graph_runner->GetNamespaceToken()),
resource_provider_(resource_provider),
- task_set_finished_weak_ptr_factory_(this) {
-}
+ use_rgba_4444_texture_format_(use_rgba_4444_texture_format),
+ task_set_finished_weak_ptr_factory_(this) {}
ZeroCopyTileTaskWorkerPool::~ZeroCopyTileTaskWorkerPool() {
}
@@ -171,18 +178,21 @@ void ZeroCopyTileTaskWorkerPool::CheckForCompletedTasks() {
task->WillComplete();
task->CompleteOnOriginThread(this);
task->DidComplete();
-
- task->RunReplyOnOriginThread();
}
completed_tasks_.clear();
}
-ResourceFormat ZeroCopyTileTaskWorkerPool::GetResourceFormat() const {
- return resource_provider_->best_texture_format();
+ResourceFormat ZeroCopyTileTaskWorkerPool::GetResourceFormat(
+ bool must_support_alpha) const {
+ return use_rgba_4444_texture_format_
+ ? RGBA_4444
+ : resource_provider_->best_texture_format();
}
-bool ZeroCopyTileTaskWorkerPool::GetResourceRequiresSwizzle() const {
- return !PlatformColor::SameComponentOrder(GetResourceFormat());
+bool ZeroCopyTileTaskWorkerPool::GetResourceRequiresSwizzle(
+ bool must_support_alpha) const {
+ return !PlatformColor::SameComponentOrder(
+ GetResourceFormat(must_support_alpha));
}
scoped_ptr<RasterBuffer> ZeroCopyTileTaskWorkerPool::AcquireBufferForRaster(
diff --git a/chromium/cc/raster/zero_copy_tile_task_worker_pool.h b/chromium/cc/raster/zero_copy_tile_task_worker_pool.h
index 7dcdff0a686..b1015593245 100644
--- a/chromium/cc/raster/zero_copy_tile_task_worker_pool.h
+++ b/chromium/cc/raster/zero_copy_tile_task_worker_pool.h
@@ -28,7 +28,8 @@ class CC_EXPORT ZeroCopyTileTaskWorkerPool : public TileTaskWorkerPool,
static scoped_ptr<TileTaskWorkerPool> Create(
base::SequencedTaskRunner* task_runner,
TaskGraphRunner* task_graph_runner,
- ResourceProvider* resource_provider);
+ ResourceProvider* resource_provider,
+ bool use_rgba_4444_texture_format);
// Overridden from TileTaskWorkerPool:
TileTaskRunner* AsTileTaskRunner() override;
@@ -38,8 +39,8 @@ class CC_EXPORT ZeroCopyTileTaskWorkerPool : public TileTaskWorkerPool,
void Shutdown() override;
void ScheduleTasks(TileTaskQueue* queue) override;
void CheckForCompletedTasks() override;
- ResourceFormat GetResourceFormat() const override;
- bool GetResourceRequiresSwizzle() const override;
+ ResourceFormat GetResourceFormat(bool must_support_alpha) const override;
+ bool GetResourceRequiresSwizzle(bool must_support_alpha) const override;
// Overridden from TileTaskClient:
scoped_ptr<RasterBuffer> AcquireBufferForRaster(
@@ -51,7 +52,8 @@ class CC_EXPORT ZeroCopyTileTaskWorkerPool : public TileTaskWorkerPool,
protected:
ZeroCopyTileTaskWorkerPool(base::SequencedTaskRunner* task_runner,
TaskGraphRunner* task_graph_runner,
- ResourceProvider* resource_provider);
+ ResourceProvider* resource_provider,
+ bool use_rgba_4444_texture_format);
private:
void OnTaskSetFinished(TaskSet task_set);
@@ -64,6 +66,8 @@ class CC_EXPORT ZeroCopyTileTaskWorkerPool : public TileTaskWorkerPool,
TileTaskRunnerClient* client_;
ResourceProvider* resource_provider_;
+ bool use_rgba_4444_texture_format_;
+
TaskSetCollection tasks_pending_;
scoped_refptr<TileTask> task_set_finished_tasks_[kNumberOfTaskSets];
diff --git a/chromium/cc/resources/resource.h b/chromium/cc/resources/resource.h
index f9138fbb876..549a314d48e 100644
--- a/chromium/cc/resources/resource.h
+++ b/chromium/cc/resources/resource.h
@@ -5,9 +5,9 @@
#ifndef CC_RESOURCES_RESOURCE_H_
#define CC_RESOURCES_RESOURCE_H_
-#include "base/numerics/safe_math.h"
#include "cc/base/cc_export.h"
#include "cc/resources/resource_provider.h"
+#include "cc/resources/resource_util.h"
#include "ui/gfx/geometry/size.h"
namespace cc {
@@ -24,37 +24,6 @@ class CC_EXPORT Resource {
gfx::Size size() const { return size_; }
ResourceFormat format() const { return format_; }
- // Return true if the call to UncheckedMemorySizeBytes would return a value
- // that fits in a size_t.
- static bool VerifySizeInBytes(const gfx::Size& size, ResourceFormat format) {
- base::CheckedNumeric<size_t> checked_value = BitsPerPixel(format);
- checked_value *= size.width();
- checked_value *= size.height();
- if (!checked_value.IsValid())
- return false;
- size_t value = checked_value.ValueOrDie();
- if ((value % 8) != 0)
- return false;
- return true;
- }
-
- static size_t CheckedMemorySizeBytes(const gfx::Size& size,
- ResourceFormat format) {
- DCHECK(VerifySizeInBytes(size, format));
- base::CheckedNumeric<size_t> checked_value = BitsPerPixel(format);
- checked_value *= size.width();
- checked_value *= size.height();
- checked_value /= 8;
- return checked_value.ValueOrDie();
- }
-
- inline static size_t UncheckedMemorySizeBytes(const gfx::Size& size,
- ResourceFormat format) {
- DCHECK(VerifySizeInBytes(size, format));
- return static_cast<size_t>(BitsPerPixel(format)) * size.width() *
- size.height() / 8;
- }
-
protected:
void set_id(ResourceId id) { id_ = id; }
void set_dimensions(const gfx::Size& size, ResourceFormat format) {
diff --git a/chromium/cc/resources/resource_format.cc b/chromium/cc/resources/resource_format.cc
index 45581b800f1..c62ae934d72 100644
--- a/chromium/cc/resources/resource_format.cc
+++ b/chromium/cc/resources/resource_format.cc
@@ -4,6 +4,9 @@
#include "cc/resources/resource_format.h"
+#include "third_party/khronos/GLES2/gl2.h"
+#include "third_party/khronos/GLES2/gl2ext.h"
+
namespace cc {
SkColorType ResourceFormatToSkColorType(ResourceFormat format) {
@@ -25,4 +28,82 @@ SkColorType ResourceFormatToSkColorType(ResourceFormat format) {
return kN32_SkColorType;
}
+int BitsPerPixel(ResourceFormat format) {
+ switch (format) {
+ case BGRA_8888:
+ case RGBA_8888:
+ return 32;
+ case RGBA_4444:
+ case RGB_565:
+ return 16;
+ case ALPHA_8:
+ case LUMINANCE_8:
+ case RED_8:
+ return 8;
+ case ETC1:
+ return 4;
+ }
+ NOTREACHED();
+ return 0;
+}
+
+GLenum GLDataType(ResourceFormat format) {
+ DCHECK_LE(format, RESOURCE_FORMAT_MAX);
+ static const GLenum format_gl_data_type[] = {
+ GL_UNSIGNED_BYTE, // RGBA_8888
+ GL_UNSIGNED_SHORT_4_4_4_4, // RGBA_4444
+ GL_UNSIGNED_BYTE, // BGRA_8888
+ GL_UNSIGNED_BYTE, // ALPHA_8
+ GL_UNSIGNED_BYTE, // LUMINANCE_8
+ GL_UNSIGNED_SHORT_5_6_5, // RGB_565,
+ GL_UNSIGNED_BYTE, // ETC1
+ GL_UNSIGNED_BYTE // RED_8
+ };
+ static_assert(arraysize(format_gl_data_type) == (RESOURCE_FORMAT_MAX + 1),
+ "format_gl_data_type does not handle all cases.");
+
+ return format_gl_data_type[format];
+}
+
+GLenum GLDataFormat(ResourceFormat format) {
+ DCHECK_LE(format, RESOURCE_FORMAT_MAX);
+ static const GLenum format_gl_data_format[] = {
+ GL_RGBA, // RGBA_8888
+ GL_RGBA, // RGBA_4444
+ GL_BGRA_EXT, // BGRA_8888
+ GL_ALPHA, // ALPHA_8
+ GL_LUMINANCE, // LUMINANCE_8
+ GL_RGB, // RGB_565
+ GL_ETC1_RGB8_OES, // ETC1
+ GL_RED_EXT // RED_8
+ };
+ static_assert(arraysize(format_gl_data_format) == (RESOURCE_FORMAT_MAX + 1),
+ "format_gl_data_format does not handle all cases.");
+
+ return format_gl_data_format[format];
+}
+
+GLenum GLInternalFormat(ResourceFormat format) {
+ return GLDataFormat(format);
+}
+
+gfx::BufferFormat BufferFormat(ResourceFormat format) {
+ switch (format) {
+ case RGBA_8888:
+ return gfx::BufferFormat::RGBA_8888;
+ case BGRA_8888:
+ return gfx::BufferFormat::BGRA_8888;
+ case RGBA_4444:
+ return gfx::BufferFormat::RGBA_4444;
+ case ALPHA_8:
+ case LUMINANCE_8:
+ case RGB_565:
+ case ETC1:
+ case RED_8:
+ break;
+ }
+ NOTREACHED();
+ return gfx::BufferFormat::RGBA_8888;
+}
+
} // namespace cc
diff --git a/chromium/cc/resources/resource_format.h b/chromium/cc/resources/resource_format.h
index d785ab7382b..79b815fcd29 100644
--- a/chromium/cc/resources/resource_format.h
+++ b/chromium/cc/resources/resource_format.h
@@ -6,7 +6,14 @@
#define CC_RESOURCES_RESOURCE_FORMAT_H_
#include "base/logging.h"
+#include "cc/base/cc_export.h"
#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/gpu_memory_buffer.h"
+
+// TODO(prashant.n): Including third_party/khronos/GLES2/gl2.h causes
+// redefinition errors as macros/functions defined in it conflict with
+// macros/functions defined in ui/gl/gl_bindings.h. (http://crbug.com/512833).
+typedef unsigned int GLenum;
namespace cc {
@@ -25,6 +32,12 @@ enum ResourceFormat {
SkColorType ResourceFormatToSkColorType(ResourceFormat format);
+CC_EXPORT int BitsPerPixel(ResourceFormat format);
+CC_EXPORT GLenum GLDataType(ResourceFormat format);
+CC_EXPORT GLenum GLDataFormat(ResourceFormat format);
+CC_EXPORT GLenum GLInternalFormat(ResourceFormat format);
+CC_EXPORT gfx::BufferFormat BufferFormat(ResourceFormat format);
+
} // namespace cc
#endif // CC_RESOURCES_RESOURCE_FORMAT_H_
diff --git a/chromium/cc/resources/resource_pool.cc b/chromium/cc/resources/resource_pool.cc
index 7b65d344ab3..835c37d6c32 100644
--- a/chromium/cc/resources/resource_pool.cc
+++ b/chromium/cc/resources/resource_pool.cc
@@ -4,41 +4,96 @@
#include "cc/resources/resource_pool.h"
+#include <algorithm>
+
+#include "base/format_macros.h"
+#include "base/strings/stringprintf.h"
+#include "base/thread_task_runner_handle.h"
+#include "base/trace_event/memory_dump_manager.h"
#include "cc/resources/resource_provider.h"
+#include "cc/resources/resource_util.h"
#include "cc/resources/scoped_resource.h"
namespace cc {
+namespace {
+
+// Delay before a resource is considered expired.
+const int kResourceExpirationDelayMs = 1000;
+
+} // namespace
+
+void ResourcePool::PoolResource::OnMemoryDump(
+ base::trace_event::ProcessMemoryDump* pmd,
+ const ResourceProvider* resource_provider,
+ bool is_free) const {
+ // Resource IDs are not process-unique, so log with the ResourceProvider's
+ // unique id.
+ std::string parent_node =
+ base::StringPrintf("cc/resource_memory/provider_%d/resource_%d",
+ resource_provider->tracing_id(), id());
+
+ std::string dump_name =
+ base::StringPrintf("cc/tile_memory/provider_%d/resource_%d",
+ resource_provider->tracing_id(), id());
+ base::trace_event::MemoryAllocatorDump* dump =
+ pmd->CreateAllocatorDump(dump_name);
+
+ pmd->AddSuballocation(dump->guid(), parent_node);
+
+ uint64_t total_bytes =
+ ResourceUtil::UncheckedSizeInBytesAligned<size_t>(size(), format());
+ dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+ total_bytes);
-ResourcePool::ResourcePool(ResourceProvider* resource_provider, GLenum target)
+ if (is_free) {
+ dump->AddScalar("free_size",
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+ total_bytes);
+ }
+}
+
+ResourcePool::ResourcePool(ResourceProvider* resource_provider,
+ base::SingleThreadTaskRunner* task_runner,
+ GLenum target)
: resource_provider_(resource_provider),
target_(target),
max_memory_usage_bytes_(0),
- max_unused_memory_usage_bytes_(0),
max_resource_count_(0),
- memory_usage_bytes_(0),
- unused_memory_usage_bytes_(0),
- resource_count_(0) {}
+ in_use_memory_usage_bytes_(0),
+ total_memory_usage_bytes_(0),
+ total_resource_count_(0),
+ task_runner_(task_runner),
+ evict_expired_resources_pending_(false),
+ resource_expiration_delay_(
+ base::TimeDelta::FromMilliseconds(kResourceExpirationDelayMs)),
+ weak_ptr_factory_(this) {
+ base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
+ this, task_runner_.get());
+}
ResourcePool::~ResourcePool() {
+ base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
+ this);
+
+ DCHECK_EQ(0u, in_use_resources_.size());
+
while (!busy_resources_.empty()) {
- auto const& front = busy_resources_.front();
- DidFinishUsingResource(front.resource, front.content_id);
- busy_resources_.pop_front();
+ DidFinishUsingResource(busy_resources_.take_front());
}
- SetResourceUsageLimits(0, 0, 0);
+ SetResourceUsageLimits(0, 0);
DCHECK_EQ(0u, unused_resources_.size());
- DCHECK_EQ(0u, memory_usage_bytes_);
- DCHECK_EQ(0u, unused_memory_usage_bytes_);
- DCHECK_EQ(0u, resource_count_);
+ DCHECK_EQ(0u, in_use_memory_usage_bytes_);
+ DCHECK_EQ(0u, total_memory_usage_bytes_);
+ DCHECK_EQ(0u, total_resource_count_);
}
-scoped_ptr<ScopedResource> ResourcePool::AcquireResource(
- const gfx::Size& size, ResourceFormat format) {
- for (ResourceList::iterator it = unused_resources_.begin();
- it != unused_resources_.end();
- ++it) {
- ScopedResource* resource = it->resource;
+Resource* ResourcePool::AcquireResource(const gfx::Size& size,
+ ResourceFormat format) {
+ for (ResourceDeque::iterator it = unused_resources_.begin();
+ it != unused_resources_.end(); ++it) {
+ ScopedResource* resource = *it;
DCHECK(resource_provider_->CanLockForWrite(resource->id()));
if (resource->format() != format)
@@ -46,53 +101,73 @@ scoped_ptr<ScopedResource> ResourcePool::AcquireResource(
if (resource->size() != size)
continue;
- unused_resources_.erase(it);
- unused_memory_usage_bytes_ -=
- Resource::UncheckedMemorySizeBytes(size, format);
- return make_scoped_ptr(resource);
+ // Transfer resource to |in_use_resources_|.
+ in_use_resources_.set(resource->id(), unused_resources_.take(it));
+ in_use_memory_usage_bytes_ += ResourceUtil::UncheckedSizeInBytes<size_t>(
+ resource->size(), resource->format());
+ return resource;
}
- scoped_ptr<ScopedResource> resource =
- ScopedResource::Create(resource_provider_);
- resource->AllocateManaged(size, target_, format);
+ scoped_ptr<PoolResource> pool_resource =
+ PoolResource::Create(resource_provider_);
+ GLenum target =
+ target_ ? target_ : resource_provider_->GetImageTextureTarget(format);
+ pool_resource->AllocateManaged(size, target, format);
+
+ DCHECK(ResourceUtil::VerifySizeInBytes<size_t>(pool_resource->size(),
+ pool_resource->format()));
+ total_memory_usage_bytes_ += ResourceUtil::UncheckedSizeInBytes<size_t>(
+ pool_resource->size(), pool_resource->format());
+ ++total_resource_count_;
- DCHECK(Resource::VerifySizeInBytes(resource->size(), resource->format()));
- memory_usage_bytes_ +=
- Resource::UncheckedMemorySizeBytes(resource->size(), resource->format());
- ++resource_count_;
- return resource.Pass();
+ Resource* resource = pool_resource.get();
+ in_use_resources_.set(resource->id(), pool_resource.Pass());
+ in_use_memory_usage_bytes_ += ResourceUtil::UncheckedSizeInBytes<size_t>(
+ resource->size(), resource->format());
+ return resource;
}
-scoped_ptr<ScopedResource> ResourcePool::TryAcquireResourceWithContentId(
- uint64_t content_id) {
+Resource* ResourcePool::TryAcquireResourceWithContentId(uint64_t content_id) {
DCHECK(content_id);
auto it = std::find_if(unused_resources_.begin(), unused_resources_.end(),
- [content_id](const PoolResource& pool_resource) {
- return pool_resource.content_id == content_id;
+ [content_id](const PoolResource* pool_resource) {
+ return pool_resource->content_id() == content_id;
});
if (it == unused_resources_.end())
return nullptr;
- ScopedResource* resource = it->resource;
+ Resource* resource = *it;
DCHECK(resource_provider_->CanLockForWrite(resource->id()));
- unused_resources_.erase(it);
- unused_memory_usage_bytes_ -=
- Resource::UncheckedMemorySizeBytes(resource->size(), resource->format());
- return make_scoped_ptr(resource);
+ // Transfer resource to |in_use_resources_|.
+ in_use_resources_.set(resource->id(), unused_resources_.take(it));
+ in_use_memory_usage_bytes_ += ResourceUtil::UncheckedSizeInBytes<size_t>(
+ resource->size(), resource->format());
+ return resource;
}
-void ResourcePool::ReleaseResource(scoped_ptr<ScopedResource> resource,
- uint64_t content_id) {
- busy_resources_.push_back(PoolResource(resource.release(), content_id));
+void ResourcePool::ReleaseResource(Resource* resource, uint64_t content_id) {
+ auto it = in_use_resources_.find(resource->id());
+ DCHECK(it != in_use_resources_.end());
+
+ PoolResource* pool_resource = it->second;
+ pool_resource->set_content_id(content_id);
+ pool_resource->set_last_usage(base::TimeTicks::Now());
+
+ // Transfer resource to |busy_resources_|.
+ busy_resources_.push_back(in_use_resources_.take_and_erase(it));
+ in_use_memory_usage_bytes_ -= ResourceUtil::UncheckedSizeInBytes<size_t>(
+ pool_resource->size(), pool_resource->format());
+
+ // Now that we have evictable resources, schedule an eviction call for this
+ // resource if necessary.
+ ScheduleEvictExpiredResourcesIn(resource_expiration_delay_);
}
void ResourcePool::SetResourceUsageLimits(size_t max_memory_usage_bytes,
- size_t max_unused_memory_usage_bytes,
size_t max_resource_count) {
max_memory_usage_bytes_ = max_memory_usage_bytes;
- max_unused_memory_usage_bytes_ = max_unused_memory_usage_bytes;
max_resource_count_ = max_resource_count;
ReduceResourceUsage();
@@ -110,59 +185,121 @@ void ResourcePool::ReduceResourceUsage() {
// can't be locked for write might also not be truly free-able.
// We can free the resource here but it doesn't mean that the
// memory is necessarily returned to the OS.
- ScopedResource* resource = unused_resources_.front().resource;
- unused_resources_.pop_front();
- unused_memory_usage_bytes_ -= Resource::UncheckedMemorySizeBytes(
- resource->size(), resource->format());
- DeleteResource(resource);
+ DeleteResource(unused_resources_.take_front());
}
}
bool ResourcePool::ResourceUsageTooHigh() {
- if (resource_count_ > max_resource_count_)
+ if (total_resource_count_ > max_resource_count_)
return true;
- if (memory_usage_bytes_ > max_memory_usage_bytes_)
- return true;
- if (unused_memory_usage_bytes_ > max_unused_memory_usage_bytes_)
+ if (total_memory_usage_bytes_ > max_memory_usage_bytes_)
return true;
return false;
}
-void ResourcePool::DeleteResource(ScopedResource* resource) {
- size_t resource_bytes =
- Resource::UncheckedMemorySizeBytes(resource->size(), resource->format());
- memory_usage_bytes_ -= resource_bytes;
- --resource_count_;
- delete resource;
+void ResourcePool::DeleteResource(scoped_ptr<PoolResource> resource) {
+ size_t resource_bytes = ResourceUtil::UncheckedSizeInBytes<size_t>(
+ resource->size(), resource->format());
+ total_memory_usage_bytes_ -= resource_bytes;
+ --total_resource_count_;
}
-void ResourcePool::CheckBusyResources(bool wait_if_needed) {
- ResourceList::iterator it = busy_resources_.begin();
-
- while (it != busy_resources_.end()) {
- ScopedResource* resource = it->resource;
-
- if (wait_if_needed)
- resource_provider_->WaitReadLockIfNeeded(resource->id());
+void ResourcePool::CheckBusyResources() {
+ for (size_t i = 0; i < busy_resources_.size();) {
+ ResourceDeque::iterator it(busy_resources_.begin() + i);
+ PoolResource* resource = *it;
if (resource_provider_->CanLockForWrite(resource->id())) {
- DidFinishUsingResource(resource, it->content_id);
- it = busy_resources_.erase(it);
+ DidFinishUsingResource(busy_resources_.take(it));
} else if (resource_provider_->IsLost(resource->id())) {
// Remove lost resources from pool.
- DeleteResource(resource);
- it = busy_resources_.erase(it);
+ DeleteResource(busy_resources_.take(it));
} else {
- ++it;
+ ++i;
}
}
}
-void ResourcePool::DidFinishUsingResource(ScopedResource* resource,
- uint64_t content_id) {
- unused_memory_usage_bytes_ +=
- Resource::UncheckedMemorySizeBytes(resource->size(), resource->format());
- unused_resources_.push_back(PoolResource(resource, content_id));
+void ResourcePool::DidFinishUsingResource(scoped_ptr<PoolResource> resource) {
+ unused_resources_.push_back(resource.Pass());
+}
+
+void ResourcePool::ScheduleEvictExpiredResourcesIn(
+ base::TimeDelta time_from_now) {
+ if (evict_expired_resources_pending_)
+ return;
+
+ evict_expired_resources_pending_ = true;
+
+ task_runner_->PostDelayedTask(FROM_HERE,
+ base::Bind(&ResourcePool::EvictExpiredResources,
+ weak_ptr_factory_.GetWeakPtr()),
+ time_from_now);
+}
+
+void ResourcePool::EvictExpiredResources() {
+ evict_expired_resources_pending_ = false;
+ base::TimeTicks current_time = base::TimeTicks::Now();
+
+ EvictResourcesNotUsedSince(current_time - resource_expiration_delay_);
+
+ if (unused_resources_.empty() && busy_resources_.empty()) {
+ // Nothing is evictable.
+ return;
+ }
+
+ // If we still have evictable resources, schedule a call to
+ // EvictExpiredResources at the time when the LRU buffer expires.
+ ScheduleEvictExpiredResourcesIn(GetUsageTimeForLRUResource() +
+ resource_expiration_delay_ - current_time);
+}
+
+void ResourcePool::EvictResourcesNotUsedSince(base::TimeTicks time_limit) {
+ while (!unused_resources_.empty()) {
+ // |unused_resources_| is not strictly ordered with regards to last_usage,
+ // as this may not exactly line up with the time a resource became non-busy.
+ // However, this should be roughly ordered, and will only introduce slight
+ // delays in freeing expired resources.
+ if (unused_resources_.front()->last_usage() > time_limit)
+ return;
+
+ DeleteResource(unused_resources_.take_front());
+ }
+
+ // Also free busy resources older than the delay. With a sufficiently large
+ // delay, such as the 1 second used here, any "busy" resources which have
+ // expired are not likely to be busy. Additionally, freeing a "busy" resource
+ // has no downside other than incorrect accounting.
+ while (!busy_resources_.empty()) {
+ if (busy_resources_.front()->last_usage() > time_limit)
+ return;
+
+ DeleteResource(busy_resources_.take_front());
+ }
+}
+
+base::TimeTicks ResourcePool::GetUsageTimeForLRUResource() const {
+ if (!unused_resources_.empty()) {
+ return unused_resources_.front()->last_usage();
+ }
+
+ // This is only called when we have at least one evictable resource.
+ DCHECK(!busy_resources_.empty());
+ return busy_resources_.front()->last_usage();
+}
+
+bool ResourcePool::OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
+ base::trace_event::ProcessMemoryDump* pmd) {
+ for (const auto& resource : unused_resources_) {
+ resource->OnMemoryDump(pmd, resource_provider_, true /* is_free */);
+ }
+ for (const auto& resource : busy_resources_) {
+ resource->OnMemoryDump(pmd, resource_provider_, false /* is_free */);
+ }
+ for (const auto& entry : in_use_resources_) {
+ entry.second->OnMemoryDump(pmd, resource_provider_, false /* is_free */);
+ }
+ return true;
}
} // namespace cc
diff --git a/chromium/cc/resources/resource_pool.h b/chromium/cc/resources/resource_pool.h
index 88816aa73d4..c1db254e052 100644
--- a/chromium/cc/resources/resource_pool.h
+++ b/chromium/cc/resources/resource_pool.h
@@ -7,77 +7,129 @@
#include <deque>
+#include "base/containers/scoped_ptr_map.h"
#include "base/memory/scoped_ptr.h"
+#include "base/trace_event/memory_dump_provider.h"
#include "cc/base/cc_export.h"
+#include "cc/base/scoped_ptr_deque.h"
#include "cc/output/renderer.h"
#include "cc/resources/resource.h"
#include "cc/resources/resource_format.h"
+#include "cc/resources/scoped_resource.h"
namespace cc {
-class ScopedResource;
-class CC_EXPORT ResourcePool {
+class CC_EXPORT ResourcePool : public base::trace_event::MemoryDumpProvider {
public:
- static scoped_ptr<ResourcePool> Create(ResourceProvider* resource_provider,
- GLenum target) {
- return make_scoped_ptr(new ResourcePool(resource_provider, target));
+ static scoped_ptr<ResourcePool> Create(
+ ResourceProvider* resource_provider,
+ base::SingleThreadTaskRunner* task_runner) {
+ return make_scoped_ptr(
+ new ResourcePool(resource_provider, task_runner, 0 /* target */));
}
- virtual ~ResourcePool();
+ static scoped_ptr<ResourcePool> Create(
+ ResourceProvider* resource_provider,
+ base::SingleThreadTaskRunner* task_runner,
+ GLenum target) {
+ DCHECK_NE(0u, target);
+ return make_scoped_ptr(
+ new ResourcePool(resource_provider, task_runner, target));
+ }
+
+ ~ResourcePool() override;
- scoped_ptr<ScopedResource> AcquireResource(const gfx::Size& size,
- ResourceFormat format);
- scoped_ptr<ScopedResource> TryAcquireResourceWithContentId(uint64 content_id);
- void ReleaseResource(scoped_ptr<ScopedResource> resource,
- uint64_t content_id);
+ Resource* AcquireResource(const gfx::Size& size, ResourceFormat format);
+ Resource* TryAcquireResourceWithContentId(uint64 content_id);
+ void ReleaseResource(Resource* resource, uint64_t content_id);
void SetResourceUsageLimits(size_t max_memory_usage_bytes,
- size_t max_unused_memory_usage_bytes,
size_t max_resource_count);
void ReduceResourceUsage();
- // This might block if |wait_if_needed| is true and one of the currently
- // busy resources has a read lock fence that needs to be waited upon before
- // it can be locked for write again.
- void CheckBusyResources(bool wait_if_needed);
-
- size_t total_memory_usage_bytes() const { return memory_usage_bytes_; }
- size_t acquired_memory_usage_bytes() const {
- return memory_usage_bytes_ - unused_memory_usage_bytes_;
+ void CheckBusyResources();
+
+ size_t memory_usage_bytes() const { return in_use_memory_usage_bytes_; }
+ size_t resource_count() const { return in_use_resources_.size(); }
+
+ // Overridden from base::trace_event::MemoryDumpProvider:
+ bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
+ base::trace_event::ProcessMemoryDump* pmd) override;
+
+ size_t GetTotalMemoryUsageForTesting() const {
+ return total_memory_usage_bytes_;
+ }
+ size_t GetTotalResourceCountForTesting() const {
+ return total_resource_count_;
}
- size_t total_resource_count() const { return resource_count_; }
- size_t acquired_resource_count() const {
- return resource_count_ - unused_resources_.size();
+ size_t GetBusyResourceCountForTesting() const {
+ return busy_resources_.size();
+ }
+ void SetResourceExpirationDelayForTesting(base::TimeDelta delay) {
+ resource_expiration_delay_ = delay;
}
- size_t busy_resource_count() const { return busy_resources_.size(); }
protected:
- ResourcePool(ResourceProvider* resource_provider, GLenum target);
+ ResourcePool(ResourceProvider* resource_provider,
+ base::SingleThreadTaskRunner* task_runner,
+ GLenum target);
bool ResourceUsageTooHigh();
private:
- void DidFinishUsingResource(ScopedResource* resource, uint64_t content_id);
- void DeleteResource(ScopedResource* resource);
+ class PoolResource : public ScopedResource {
+ public:
+ static scoped_ptr<PoolResource> Create(
+ ResourceProvider* resource_provider) {
+ return make_scoped_ptr(new PoolResource(resource_provider));
+ }
+ void OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd,
+ const ResourceProvider* resource_provider,
+ bool is_free) const;
+
+ uint64_t content_id() const { return content_id_; }
+ void set_content_id(uint64_t content_id) { content_id_ = content_id; }
+
+ base::TimeTicks last_usage() const { return last_usage_; }
+ void set_last_usage(base::TimeTicks time) { last_usage_ = time; }
+
+ private:
+ explicit PoolResource(ResourceProvider* resource_provider)
+ : ScopedResource(resource_provider), content_id_(0) {}
+ uint64_t content_id_;
+ base::TimeTicks last_usage_;
+ };
+
+ void DidFinishUsingResource(scoped_ptr<PoolResource> resource);
+ void DeleteResource(scoped_ptr<PoolResource> resource);
+
+ // Functions which manage periodic eviction of expired resources.
+ void ScheduleEvictExpiredResourcesIn(base::TimeDelta time_from_now);
+ void EvictExpiredResources();
+ void EvictResourcesNotUsedSince(base::TimeTicks time_limit);
+ bool HasEvictableResources() const;
+ base::TimeTicks GetUsageTimeForLRUResource() const;
ResourceProvider* resource_provider_;
const GLenum target_;
size_t max_memory_usage_bytes_;
- size_t max_unused_memory_usage_bytes_;
size_t max_resource_count_;
- size_t memory_usage_bytes_;
- size_t unused_memory_usage_bytes_;
- size_t resource_count_;
-
- struct PoolResource {
- PoolResource(ScopedResource* resource, uint64_t content_id)
- : resource(resource), content_id(content_id) {}
- ScopedResource* resource;
- uint64_t content_id;
- };
- typedef std::deque<PoolResource> ResourceList;
- ResourceList unused_resources_;
- ResourceList busy_resources_;
+ size_t in_use_memory_usage_bytes_;
+ size_t total_memory_usage_bytes_;
+ size_t total_resource_count_;
+
+ using ResourceDeque = ScopedPtrDeque<PoolResource>;
+ ResourceDeque unused_resources_;
+ ResourceDeque busy_resources_;
+
+ using ResourceMap = base::ScopedPtrMap<ResourceId, scoped_ptr<PoolResource>>;
+ ResourceMap in_use_resources_;
+
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+ bool evict_expired_resources_pending_;
+ base::TimeDelta resource_expiration_delay_;
+
+ base::WeakPtrFactory<ResourcePool> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(ResourcePool);
};
diff --git a/chromium/cc/resources/resource_pool_unittest.cc b/chromium/cc/resources/resource_pool_unittest.cc
index 96e7591ab8c..bde9d748b7e 100644
--- a/chromium/cc/resources/resource_pool_unittest.cc
+++ b/chromium/cc/resources/resource_pool_unittest.cc
@@ -4,6 +4,9 @@
#include "cc/resources/resource_pool.h"
+#include "base/run_loop.h"
+#include "base/thread_task_runner_handle.h"
+#include "cc/resources/resource_util.h"
#include "cc/resources/scoped_resource.h"
#include "cc/test/fake_output_surface.h"
#include "cc/test/fake_output_surface_client.h"
@@ -22,8 +25,9 @@ class ResourcePoolTest : public testing::Test {
shared_bitmap_manager_.reset(new TestSharedBitmapManager());
resource_provider_ = FakeResourceProvider::Create(
output_surface_.get(), shared_bitmap_manager_.get());
- resource_pool_ =
- ResourcePool::Create(resource_provider_.get(), GL_TEXTURE_2D);
+ task_runner_ = base::ThreadTaskRunnerHandle::Get();
+ resource_pool_ = ResourcePool::Create(resource_provider_.get(),
+ task_runner_.get(), GL_TEXTURE_2D);
}
protected:
@@ -31,89 +35,86 @@ class ResourcePoolTest : public testing::Test {
scoped_ptr<FakeOutputSurface> output_surface_;
scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
scoped_ptr<ResourceProvider> resource_provider_;
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
scoped_ptr<ResourcePool> resource_pool_;
};
TEST_F(ResourcePoolTest, AcquireRelease) {
gfx::Size size(100, 100);
ResourceFormat format = RGBA_8888;
- scoped_ptr<ScopedResource> resource =
- resource_pool_->AcquireResource(size, format);
+ Resource* resource = resource_pool_->AcquireResource(size, format);
EXPECT_EQ(size, resource->size());
EXPECT_EQ(format, resource->format());
EXPECT_TRUE(resource_provider_->CanLockForWrite(resource->id()));
- resource_pool_->ReleaseResource(resource.Pass(), 0u);
+ resource_pool_->ReleaseResource(resource, 0u);
}
TEST_F(ResourcePoolTest, AccountingSingleResource) {
// Limits high enough to not be hit by this test.
size_t bytes_limit = 10 * 1024 * 1024;
size_t count_limit = 100;
- resource_pool_->SetResourceUsageLimits(bytes_limit, bytes_limit, count_limit);
+ resource_pool_->SetResourceUsageLimits(bytes_limit, count_limit);
gfx::Size size(100, 100);
ResourceFormat format = RGBA_8888;
- size_t resource_bytes = Resource::UncheckedMemorySizeBytes(size, format);
- scoped_ptr<ScopedResource> resource =
- resource_pool_->AcquireResource(size, format);
-
- EXPECT_EQ(resource_bytes, resource_pool_->total_memory_usage_bytes());
- EXPECT_EQ(resource_bytes, resource_pool_->acquired_memory_usage_bytes());
- EXPECT_EQ(1u, resource_pool_->total_resource_count());
- EXPECT_EQ(1u, resource_pool_->acquired_resource_count());
- EXPECT_EQ(0u, resource_pool_->busy_resource_count());
-
- resource_pool_->ReleaseResource(resource.Pass(), 0u);
- EXPECT_EQ(resource_bytes, resource_pool_->total_memory_usage_bytes());
- EXPECT_EQ(1u, resource_pool_->total_resource_count());
- EXPECT_EQ(1u, resource_pool_->busy_resource_count());
-
- bool wait_if_needed = false;
- resource_pool_->CheckBusyResources(wait_if_needed);
- EXPECT_EQ(resource_bytes, resource_pool_->total_memory_usage_bytes());
- EXPECT_EQ(0u, resource_pool_->acquired_memory_usage_bytes());
- EXPECT_EQ(1u, resource_pool_->total_resource_count());
- EXPECT_EQ(0u, resource_pool_->acquired_resource_count());
- EXPECT_EQ(0u, resource_pool_->busy_resource_count());
-
- resource_pool_->SetResourceUsageLimits(0u, 0u, 0u);
+ size_t resource_bytes =
+ ResourceUtil::UncheckedSizeInBytes<size_t>(size, format);
+ Resource* resource = resource_pool_->AcquireResource(size, format);
+
+ EXPECT_EQ(resource_bytes, resource_pool_->GetTotalMemoryUsageForTesting());
+ EXPECT_EQ(resource_bytes, resource_pool_->memory_usage_bytes());
+ EXPECT_EQ(1u, resource_pool_->GetTotalResourceCountForTesting());
+ EXPECT_EQ(1u, resource_pool_->resource_count());
+ EXPECT_EQ(0u, resource_pool_->GetBusyResourceCountForTesting());
+
+ resource_pool_->ReleaseResource(resource, 0u);
+ EXPECT_EQ(resource_bytes, resource_pool_->GetTotalMemoryUsageForTesting());
+ EXPECT_EQ(1u, resource_pool_->GetTotalResourceCountForTesting());
+ EXPECT_EQ(1u, resource_pool_->GetBusyResourceCountForTesting());
+
+ resource_pool_->CheckBusyResources();
+ EXPECT_EQ(resource_bytes, resource_pool_->GetTotalMemoryUsageForTesting());
+ EXPECT_EQ(0u, resource_pool_->memory_usage_bytes());
+ EXPECT_EQ(1u, resource_pool_->GetTotalResourceCountForTesting());
+ EXPECT_EQ(0u, resource_pool_->resource_count());
+ EXPECT_EQ(0u, resource_pool_->GetBusyResourceCountForTesting());
+
+ resource_pool_->SetResourceUsageLimits(0u, 0u);
resource_pool_->ReduceResourceUsage();
- EXPECT_EQ(0u, resource_pool_->total_memory_usage_bytes());
- EXPECT_EQ(0u, resource_pool_->acquired_memory_usage_bytes());
- EXPECT_EQ(0u, resource_pool_->total_resource_count());
- EXPECT_EQ(0u, resource_pool_->acquired_resource_count());
- EXPECT_EQ(0u, resource_pool_->busy_resource_count());
+ EXPECT_EQ(0u, resource_pool_->GetTotalMemoryUsageForTesting());
+ EXPECT_EQ(0u, resource_pool_->memory_usage_bytes());
+ EXPECT_EQ(0u, resource_pool_->GetTotalResourceCountForTesting());
+ EXPECT_EQ(0u, resource_pool_->resource_count());
+ EXPECT_EQ(0u, resource_pool_->GetBusyResourceCountForTesting());
}
TEST_F(ResourcePoolTest, SimpleResourceReuse) {
// Limits high enough to not be hit by this test.
size_t bytes_limit = 10 * 1024 * 1024;
size_t count_limit = 100;
- resource_pool_->SetResourceUsageLimits(bytes_limit, bytes_limit, count_limit);
+ resource_pool_->SetResourceUsageLimits(bytes_limit, count_limit);
gfx::Size size(100, 100);
ResourceFormat format = RGBA_8888;
- bool wait_if_needed = false;
- scoped_ptr<ScopedResource> resource =
- resource_pool_->AcquireResource(size, format);
- resource_pool_->ReleaseResource(resource.Pass(), 0u);
- resource_pool_->CheckBusyResources(wait_if_needed);
+ Resource* resource = resource_pool_->AcquireResource(size, format);
+ resource_pool_->ReleaseResource(resource, 0u);
+ resource_pool_->CheckBusyResources();
EXPECT_EQ(1u, resource_provider_->num_resources());
// Same size/format should re-use resource.
resource = resource_pool_->AcquireResource(size, format);
EXPECT_EQ(1u, resource_provider_->num_resources());
- resource_pool_->ReleaseResource(resource.Pass(), 0u);
- resource_pool_->CheckBusyResources(wait_if_needed);
+ resource_pool_->ReleaseResource(resource, 0u);
+ resource_pool_->CheckBusyResources();
EXPECT_EQ(1u, resource_provider_->num_resources());
// Different size/format should alloate new resource.
resource = resource_pool_->AcquireResource(gfx::Size(50, 50), LUMINANCE_8);
EXPECT_EQ(2u, resource_provider_->num_resources());
- resource_pool_->ReleaseResource(resource.Pass(), 0u);
- resource_pool_->CheckBusyResources(wait_if_needed);
+ resource_pool_->ReleaseResource(resource, 0u);
+ resource_pool_->CheckBusyResources();
EXPECT_EQ(2u, resource_provider_->num_resources());
}
@@ -121,21 +122,101 @@ TEST_F(ResourcePoolTest, LostResource) {
// Limits high enough to not be hit by this test.
size_t bytes_limit = 10 * 1024 * 1024;
size_t count_limit = 100;
- resource_pool_->SetResourceUsageLimits(bytes_limit, bytes_limit, count_limit);
+ resource_pool_->SetResourceUsageLimits(bytes_limit, count_limit);
gfx::Size size(100, 100);
ResourceFormat format = RGBA_8888;
- bool wait_if_needed = false;
- scoped_ptr<ScopedResource> resource =
- resource_pool_->AcquireResource(size, format);
+ Resource* resource = resource_pool_->AcquireResource(size, format);
EXPECT_EQ(1u, resource_provider_->num_resources());
resource_provider_->LoseResourceForTesting(resource->id());
- resource_pool_->ReleaseResource(resource.Pass(), 0u);
- resource_pool_->CheckBusyResources(wait_if_needed);
+ resource_pool_->ReleaseResource(resource, 0u);
+ resource_pool_->CheckBusyResources();
EXPECT_EQ(0u, resource_provider_->num_resources());
}
+TEST_F(ResourcePoolTest, BusyResourcesEventuallyFreed) {
+ // Limits high enough to not be hit by this test.
+ size_t bytes_limit = 10 * 1024 * 1024;
+ size_t count_limit = 100;
+ resource_pool_->SetResourceUsageLimits(bytes_limit, count_limit);
+
+ // Set a quick resource expiration delay so that this test doesn't take long
+ // to run.
+ resource_pool_->SetResourceExpirationDelayForTesting(
+ base::TimeDelta::FromMilliseconds(10));
+
+ gfx::Size size(100, 100);
+ ResourceFormat format = RGBA_8888;
+
+ Resource* resource = resource_pool_->AcquireResource(size, format);
+ EXPECT_EQ(1u, resource_provider_->num_resources());
+ EXPECT_EQ(40000u, resource_pool_->GetTotalMemoryUsageForTesting());
+ EXPECT_EQ(1u, resource_pool_->resource_count());
+
+ resource_pool_->ReleaseResource(resource, 0u);
+ EXPECT_EQ(1u, resource_provider_->num_resources());
+ EXPECT_EQ(40000u, resource_pool_->GetTotalMemoryUsageForTesting());
+ EXPECT_EQ(0u, resource_pool_->memory_usage_bytes());
+ EXPECT_EQ(1u, resource_pool_->GetBusyResourceCountForTesting());
+
+ // Wait for our resource pool to evict resources. We expect resources to be
+ // released within 10 ms, give the thread up to 200.
+ base::RunLoop run_loop;
+ task_runner_->PostDelayedTask(FROM_HERE, run_loop.QuitClosure(),
+ base::TimeDelta::FromMillisecondsD(200));
+ run_loop.Run();
+
+ EXPECT_EQ(0u, resource_provider_->num_resources());
+ EXPECT_EQ(0u, resource_pool_->GetTotalMemoryUsageForTesting());
+ EXPECT_EQ(0u, resource_pool_->memory_usage_bytes());
+}
+
+TEST_F(ResourcePoolTest, UnusedResourcesEventuallyFreed) {
+ // Limits high enough to not be hit by this test.
+ size_t bytes_limit = 10 * 1024 * 1024;
+ size_t count_limit = 100;
+ resource_pool_->SetResourceUsageLimits(bytes_limit, count_limit);
+
+ // Set a quick resource expiration delay so that this test doesn't take long
+ // to run.
+ resource_pool_->SetResourceExpirationDelayForTesting(
+ base::TimeDelta::FromMilliseconds(100));
+
+ gfx::Size size(100, 100);
+ ResourceFormat format = RGBA_8888;
+
+ Resource* resource = resource_pool_->AcquireResource(size, format);
+ EXPECT_EQ(1u, resource_provider_->num_resources());
+ EXPECT_EQ(40000u, resource_pool_->GetTotalMemoryUsageForTesting());
+ EXPECT_EQ(1u, resource_pool_->GetTotalResourceCountForTesting());
+ EXPECT_EQ(1u, resource_pool_->resource_count());
+
+ resource_pool_->ReleaseResource(resource, 0u);
+ EXPECT_EQ(1u, resource_provider_->num_resources());
+ EXPECT_EQ(40000u, resource_pool_->GetTotalMemoryUsageForTesting());
+ EXPECT_EQ(1u, resource_pool_->GetTotalResourceCountForTesting());
+ EXPECT_EQ(1u, resource_pool_->GetBusyResourceCountForTesting());
+
+ // Transfer the resource from the busy pool to the unused pool.
+ resource_pool_->CheckBusyResources();
+ EXPECT_EQ(1u, resource_provider_->num_resources());
+ EXPECT_EQ(40000u, resource_pool_->GetTotalMemoryUsageForTesting());
+ EXPECT_EQ(1u, resource_pool_->GetTotalResourceCountForTesting());
+ EXPECT_EQ(0u, resource_pool_->resource_count());
+ EXPECT_EQ(0u, resource_pool_->GetBusyResourceCountForTesting());
+
+ // Wait for our resource pool to evict resources. We expect resources to be
+ // released within 100 ms, give the thread up to 200.
+ base::RunLoop run_loop;
+ task_runner_->PostDelayedTask(FROM_HERE, run_loop.QuitClosure(),
+ base::TimeDelta::FromMillisecondsD(200));
+ run_loop.Run();
+
+ EXPECT_EQ(0u, resource_provider_->num_resources());
+ EXPECT_EQ(0u, resource_pool_->GetTotalMemoryUsageForTesting());
+}
+
} // namespace
} // namespace cc
diff --git a/chromium/cc/resources/resource_provider.cc b/chromium/cc/resources/resource_provider.cc
index 9f680669c08..083b4868a5d 100644
--- a/chromium/cc/resources/resource_provider.cc
+++ b/chromium/cc/resources/resource_provider.cc
@@ -7,19 +7,24 @@
#include <algorithm>
#include <limits>
+#include "base/atomic_sequence_num.h"
#include "base/containers/hash_tables.h"
#include "base/metrics/histogram.h"
#include "base/numerics/safe_math.h"
#include "base/stl_util.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "base/thread_task_runner_handle.h"
+#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/trace_event.h"
-#include "cc/base/math_util.h"
#include "cc/resources/platform_color.h"
+#include "cc/resources/resource_util.h"
#include "cc/resources/returned_resource.h"
#include "cc/resources/shared_bitmap_manager.h"
#include "cc/resources/transferable_resource.h"
#include "gpu/GLES2/gl2extchromium.h"
+#include "gpu/command_buffer/client/context_support.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
#include "third_party/khronos/GLES2/gl2.h"
@@ -29,7 +34,7 @@
#include "third_party/skia/include/gpu/GrTextureProvider.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/vector2d.h"
-#include "ui/gfx/gpu_memory_buffer.h"
+#include "ui/gl/trace_util.h"
using gpu::gles2::GLES2Interface;
@@ -113,25 +118,6 @@ GrPixelConfig ToGrPixelConfig(ResourceFormat format) {
return kSkia8888_GrPixelConfig;
}
-gfx::GpuMemoryBuffer::Format ToGpuMemoryBufferFormat(ResourceFormat format) {
- switch (format) {
- case RGBA_8888:
- return gfx::GpuMemoryBuffer::RGBA_8888;
- case BGRA_8888:
- return gfx::GpuMemoryBuffer::BGRA_8888;
- case RGBA_4444:
- return gfx::GpuMemoryBuffer::RGBA_4444;
- case ALPHA_8:
- case LUMINANCE_8:
- case RGB_565:
- case ETC1:
- case RED_8:
- break;
- }
- NOTREACHED();
- return gfx::GpuMemoryBuffer::RGBA_8888;
-}
-
class ScopedSetActiveTexture {
public:
ScopedSetActiveTexture(GLES2Interface* gl, GLenum unit)
@@ -202,45 +188,9 @@ class BufferIdAllocator : public IdAllocator {
DISALLOW_COPY_AND_ASSIGN(BufferIdAllocator);
};
-// Query object based fence implementation used to detect completion of copy
-// texture operations. Fence has passed when query result is available.
-class CopyTextureFence : public ResourceProvider::Fence {
- public:
- CopyTextureFence(gpu::gles2::GLES2Interface* gl, unsigned query_id)
- : gl_(gl), query_id_(query_id) {}
-
- // Overridden from ResourceProvider::Fence:
- void Set() override {}
- bool HasPassed() override {
- unsigned available = 1;
- gl_->GetQueryObjectuivEXT(
- query_id_, GL_QUERY_RESULT_AVAILABLE_EXT, &available);
- if (!available)
- return false;
-
- ProcessResult();
- return true;
- }
- void Wait() override {
- // ProcessResult() will wait for result to become available.
- ProcessResult();
- }
-
- private:
- ~CopyTextureFence() override {}
-
- void ProcessResult() {
- unsigned time_elapsed_us = 0;
- gl_->GetQueryObjectuivEXT(query_id_, GL_QUERY_RESULT_EXT, &time_elapsed_us);
- UMA_HISTOGRAM_CUSTOM_COUNTS("Renderer4.CopyTextureLatency", time_elapsed_us,
- 0, 256000, 50);
- }
-
- gpu::gles2::GLES2Interface* gl_;
- unsigned query_id_;
-
- DISALLOW_COPY_AND_ASSIGN(CopyTextureFence);
-};
+// Generates process-unique IDs to use for tracing a ResourceProvider's
+// resources.
+base::StaticAtomicSequenceNumber g_next_resource_provider_tracing_id;
} // namespace
@@ -268,8 +218,6 @@ ResourceProvider::Resource::Resource(GLuint texture_id,
locked_for_write(false),
lost(false),
marked_for_deletion(false),
- pending_set_pixels(false),
- set_pixels_completion_forced(false),
allocated(false),
read_lock_fences_enabled(false),
has_shared_bitmap_id(false),
@@ -311,8 +259,6 @@ ResourceProvider::Resource::Resource(uint8_t* pixels,
locked_for_write(false),
lost(false),
marked_for_deletion(false),
- pending_set_pixels(false),
- set_pixels_completion_forced(false),
allocated(false),
read_lock_fences_enabled(false),
has_shared_bitmap_id(!!bitmap),
@@ -355,8 +301,6 @@ ResourceProvider::Resource::Resource(const SharedBitmapId& bitmap_id,
locked_for_write(false),
lost(false),
marked_for_deletion(false),
- pending_set_pixels(false),
- set_pixels_completion_forced(false),
allocated(false),
read_lock_fences_enabled(false),
has_shared_bitmap_id(true),
@@ -391,19 +335,20 @@ scoped_ptr<ResourceProvider> ResourceProvider::Create(
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
BlockingTaskRunner* blocking_main_thread_task_runner,
int highp_threshold_min,
- bool use_rgba_4444_texture_format,
size_t id_allocation_chunk_size,
- bool use_persistent_map_for_gpu_memory_buffers) {
+ const std::vector<unsigned>& use_image_texture_targets) {
scoped_ptr<ResourceProvider> resource_provider(new ResourceProvider(
output_surface, shared_bitmap_manager, gpu_memory_buffer_manager,
blocking_main_thread_task_runner, highp_threshold_min,
- use_rgba_4444_texture_format, id_allocation_chunk_size,
- use_persistent_map_for_gpu_memory_buffers));
+ id_allocation_chunk_size, use_image_texture_targets));
resource_provider->Initialize();
return resource_provider;
}
ResourceProvider::~ResourceProvider() {
+ base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
+ this);
+
while (!children_.empty())
DestroyChildInternal(children_.begin(), FOR_SHUTDOWN);
while (!resources_.empty())
@@ -593,7 +538,7 @@ void ResourceProvider::DeleteResource(ResourceId id) {
Resource* resource = &it->second;
DCHECK(!resource->marked_for_deletion);
DCHECK_EQ(resource->imported_count, 0);
- DCHECK(resource->pending_set_pixels || !resource->locked_for_write);
+ DCHECK(!resource->locked_for_write);
if (resource->exported_count > 0 || resource->lock_for_read_count > 0 ||
!ReadLockFenceHasPassed(resource)) {
@@ -717,20 +662,16 @@ void ResourceProvider::CopyToResource(ResourceId id,
dest.writePixels(source_info, image, image_stride, 0, 0);
} else {
DCHECK(resource->gl_id);
- DCHECK(!resource->pending_set_pixels);
DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D));
GLES2Interface* gl = ContextGL();
DCHECK(gl);
gl->BindTexture(GL_TEXTURE_2D, resource->gl_id);
if (resource->format == ETC1) {
- base::CheckedNumeric<int> num_bytes = BitsPerPixel(ETC1);
- num_bytes *= image_size.width();
- num_bytes *= image_size.height();
- num_bytes /= 8;
+ int image_bytes = ResourceUtil::CheckedSizeInBytes<int>(image_size, ETC1);
gl->CompressedTexImage2D(GL_TEXTURE_2D, 0, GLInternalFormat(ETC1),
image_size.width(), image_size.height(), 0,
- num_bytes.ValueOrDie(), image);
+ image_bytes, image);
} else {
gl->TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, image_size.width(),
image_size.height(), GLDataFormat(resource->format),
@@ -758,10 +699,8 @@ ResourceProvider::Resource* ResourceProvider::GetResource(ResourceId id) {
const ResourceProvider::Resource* ResourceProvider::LockForRead(ResourceId id) {
Resource* resource = GetResource(id);
- DCHECK(!resource->locked_for_write ||
- resource->set_pixels_completion_forced) <<
- "locked for write: " << resource->locked_for_write <<
- " pixels completion forced: " << resource->set_pixels_completion_forced;
+ DCHECK(!resource->locked_for_write) << "locked for write: "
+ << resource->locked_for_write;
DCHECK_EQ(resource->exported_count, 0);
// Uninitialized! Call SetPixels or LockForWrite first.
DCHECK(resource->allocated);
@@ -989,13 +928,9 @@ gfx::GpuMemoryBuffer*
ResourceProvider::ScopedWriteLockGpuMemoryBuffer::GetGpuMemoryBuffer() {
if (gpu_memory_buffer_)
return gpu_memory_buffer_;
- gfx::GpuMemoryBuffer::Usage usage =
- resource_provider_->use_persistent_map_for_gpu_memory_buffers()
- ? gfx::GpuMemoryBuffer::PERSISTENT_MAP
- : gfx::GpuMemoryBuffer::MAP;
scoped_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer =
gpu_memory_buffer_manager_->AllocateGpuMemoryBuffer(
- size_, ToGpuMemoryBufferFormat(format_), usage);
+ size_, BufferFormat(format_), gfx::BufferUsage::MAP);
gpu_memory_buffer_ = gpu_memory_buffer.release();
return gpu_memory_buffer_;
}
@@ -1085,9 +1020,8 @@ ResourceProvider::ResourceProvider(
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
BlockingTaskRunner* blocking_main_thread_task_runner,
int highp_threshold_min,
- bool use_rgba_4444_texture_format,
size_t id_allocation_chunk_size,
- bool use_persistent_map_for_gpu_memory_buffers)
+ const std::vector<unsigned>& use_image_texture_targets)
: output_surface_(output_surface),
shared_bitmap_manager_(shared_bitmap_manager),
gpu_memory_buffer_manager_(gpu_memory_buffer_manager),
@@ -1105,11 +1039,10 @@ ResourceProvider::ResourceProvider(
max_texture_size_(0),
best_texture_format_(RGBA_8888),
best_render_buffer_format_(RGBA_8888),
- use_rgba_4444_texture_format_(use_rgba_4444_texture_format),
id_allocation_chunk_size_(id_allocation_chunk_size),
use_sync_query_(false),
- use_persistent_map_for_gpu_memory_buffers_(
- use_persistent_map_for_gpu_memory_buffers) {
+ use_image_texture_targets_(use_image_texture_targets),
+ tracing_id_(g_next_resource_provider_tracing_id.GetNext()) {
DCHECK(output_surface_->HasClient());
DCHECK(id_allocation_chunk_size_);
}
@@ -1117,6 +1050,14 @@ ResourceProvider::ResourceProvider(
void ResourceProvider::Initialize() {
DCHECK(thread_checker_.CalledOnValidThread());
+ // In certain cases, ThreadTaskRunnerHandle isn't set (Android Webview).
+ // Don't register a dump provider in these cases.
+ // TODO(ericrk): Get this working in Android Webview. crbug.com/517156
+ if (base::ThreadTaskRunnerHandle::IsSet()) {
+ base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
+ this, base::ThreadTaskRunnerHandle::Get());
+ }
+
GLES2Interface* gl = ContextGL();
if (!gl) {
default_resource_type_ = RESOURCE_TYPE_BITMAP;
@@ -1514,108 +1455,6 @@ void ResourceProvider::DeleteAndReturnUnusedResourcesToChild(
}
}
-void ResourceProvider::AcquirePixelBuffer(ResourceId id) {
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
- "ResourceProvider::AcquirePixelBuffer");
-
- Resource* resource = GetResource(id);
- DCHECK(resource->origin == Resource::INTERNAL);
- DCHECK_EQ(resource->exported_count, 0);
- DCHECK(!resource->image_id);
- DCHECK_NE(ETC1, resource->format);
-
- DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE, resource->type);
- GLES2Interface* gl = ContextGL();
- DCHECK(gl);
- if (!resource->gl_pixel_buffer_id)
- resource->gl_pixel_buffer_id = buffer_id_allocator_->NextId();
- gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
- resource->gl_pixel_buffer_id);
- unsigned bytes_per_pixel = BitsPerPixel(resource->format) / 8;
- gl->BufferData(
- GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
- resource->size.height() *
- MathUtil::RoundUp(bytes_per_pixel * resource->size.width(), 4u),
- NULL, GL_DYNAMIC_DRAW);
- gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
-}
-
-void ResourceProvider::ReleasePixelBuffer(ResourceId id) {
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
- "ResourceProvider::ReleasePixelBuffer");
-
- Resource* resource = GetResource(id);
- DCHECK(resource->origin == Resource::INTERNAL);
- DCHECK_EQ(resource->exported_count, 0);
- DCHECK(!resource->image_id);
-
- // The pixel buffer can be released while there is a pending "set pixels"
- // if completion has been forced. Any shared memory associated with this
- // pixel buffer will not be freed until the waitAsyncTexImage2DCHROMIUM
- // command has been processed on the service side. It is also safe to
- // reuse any query id associated with this resource before they complete
- // as each new query has a unique submit count.
- if (resource->pending_set_pixels) {
- DCHECK(resource->set_pixels_completion_forced);
- resource->pending_set_pixels = false;
- resource->locked_for_write = false;
- }
-
- DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE, resource->type);
- if (!resource->gl_pixel_buffer_id)
- return;
- GLES2Interface* gl = ContextGL();
- DCHECK(gl);
- gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
- resource->gl_pixel_buffer_id);
- gl->BufferData(
- GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0, NULL, GL_DYNAMIC_DRAW);
- gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
-}
-
-uint8_t* ResourceProvider::MapPixelBuffer(ResourceId id, int* stride) {
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
- "ResourceProvider::MapPixelBuffer");
-
- Resource* resource = GetResource(id);
- DCHECK(resource->origin == Resource::INTERNAL);
- DCHECK_EQ(resource->exported_count, 0);
- DCHECK(!resource->image_id);
-
- *stride = 0;
- DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE, resource->type);
- GLES2Interface* gl = ContextGL();
- DCHECK(gl);
- DCHECK(resource->gl_pixel_buffer_id);
- gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
- resource->gl_pixel_buffer_id);
- uint8_t* image = static_cast<uint8_t*>(gl->MapBufferCHROMIUM(
- GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, GL_WRITE_ONLY));
- gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
- // Buffer is required to be 4-byte aligned.
- CHECK(!(reinterpret_cast<intptr_t>(image) & 3));
- return image;
-}
-
-void ResourceProvider::UnmapPixelBuffer(ResourceId id) {
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
- "ResourceProvider::UnmapPixelBuffer");
-
- Resource* resource = GetResource(id);
- DCHECK(resource->origin == Resource::INTERNAL);
- DCHECK_EQ(resource->exported_count, 0);
- DCHECK(!resource->image_id);
-
- DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE, resource->type);
- GLES2Interface* gl = ContextGL();
- DCHECK(gl);
- DCHECK(resource->gl_pixel_buffer_id);
- gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
- resource->gl_pixel_buffer_id);
- gl->UnmapBufferCHROMIUM(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM);
- gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
-}
-
GLenum ResourceProvider::BindForSampling(ResourceId resource_id,
GLenum unit,
GLenum filter) {
@@ -1625,7 +1464,7 @@ GLenum ResourceProvider::BindForSampling(ResourceId resource_id,
DCHECK(it != resources_.end());
Resource* resource = &it->second;
DCHECK(resource->lock_for_read_count);
- DCHECK(!resource->locked_for_write || resource->set_pixels_completion_forced);
+ DCHECK(!resource->locked_for_write);
ScopedSetActiveTexture scoped_active_tex(gl, unit);
GLenum target = resource->target;
@@ -1642,115 +1481,6 @@ GLenum ResourceProvider::BindForSampling(ResourceId resource_id,
return target;
}
-void ResourceProvider::BeginSetPixels(ResourceId id) {
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
- "ResourceProvider::BeginSetPixels");
-
- Resource* resource = GetResource(id);
- DCHECK(!resource->pending_set_pixels);
-
- LazyCreate(resource);
- DCHECK(resource->origin == Resource::INTERNAL);
- DCHECK(resource->gl_id || resource->allocated);
- DCHECK(ReadLockFenceHasPassed(resource));
- DCHECK(!resource->image_id);
-
- bool allocate = !resource->allocated;
- resource->allocated = true;
- LockForWrite(id);
-
- DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE, resource->type);
- DCHECK(resource->gl_id);
- GLES2Interface* gl = ContextGL();
- DCHECK(gl);
- DCHECK(resource->gl_pixel_buffer_id);
- DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D));
- gl->BindTexture(GL_TEXTURE_2D, resource->gl_id);
- gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
- resource->gl_pixel_buffer_id);
- if (!resource->gl_upload_query_id)
- gl->GenQueriesEXT(1, &resource->gl_upload_query_id);
- gl->BeginQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM,
- resource->gl_upload_query_id);
- if (allocate) {
- gl->AsyncTexImage2DCHROMIUM(GL_TEXTURE_2D,
- 0, /* level */
- GLInternalFormat(resource->format),
- resource->size.width(),
- resource->size.height(),
- 0, /* border */
- GLDataFormat(resource->format),
- GLDataType(resource->format),
- NULL);
- } else {
- gl->AsyncTexSubImage2DCHROMIUM(GL_TEXTURE_2D,
- 0, /* level */
- 0, /* x */
- 0, /* y */
- resource->size.width(),
- resource->size.height(),
- GLDataFormat(resource->format),
- GLDataType(resource->format),
- NULL);
- }
- gl->EndQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM);
- gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
-
- resource->pending_set_pixels = true;
- resource->set_pixels_completion_forced = false;
-}
-
-void ResourceProvider::ForceSetPixelsToComplete(ResourceId id) {
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
- "ResourceProvider::ForceSetPixelsToComplete");
-
- Resource* resource = GetResource(id);
-
- DCHECK(resource->locked_for_write);
- DCHECK(resource->pending_set_pixels);
- DCHECK(!resource->set_pixels_completion_forced);
-
- if (resource->gl_id) {
- GLES2Interface* gl = ContextGL();
- gl->BindTexture(GL_TEXTURE_2D, resource->gl_id);
- gl->WaitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D);
- gl->BindTexture(GL_TEXTURE_2D, 0);
- }
-
- resource->set_pixels_completion_forced = true;
-}
-
-bool ResourceProvider::DidSetPixelsComplete(ResourceId id) {
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
- "ResourceProvider::DidSetPixelsComplete");
-
- Resource* resource = GetResource(id);
-
- DCHECK(resource->locked_for_write);
- DCHECK(resource->pending_set_pixels);
-
- if (resource->gl_id) {
- GLES2Interface* gl = ContextGL();
- DCHECK(gl);
- DCHECK(resource->gl_upload_query_id);
- GLuint complete = 1;
- gl->GetQueryObjectuivEXT(
- resource->gl_upload_query_id, GL_QUERY_RESULT_AVAILABLE_EXT, &complete);
- if (!complete)
- return false;
- }
-
- resource->pending_set_pixels = false;
- UnlockForWrite(resource);
-
- // Async set pixels commands are not necessarily processed in-sequence with
- // drawing commands. Read lock fences are required to ensure that async
- // commands don't access the resource while used for drawing.
- resource->read_lock_fences_enabled = true;
-
- return true;
-}
-
void ResourceProvider::CreateForTesting(ResourceId id) {
LazyCreate(GetResource(id));
}
@@ -1837,79 +1567,6 @@ void ResourceProvider::BindImageForSampling(Resource* resource) {
resource->dirty_image = false;
}
-void ResourceProvider::CopyResource(ResourceId source_id,
- ResourceId dest_id,
- const gfx::Rect& rect) {
- TRACE_EVENT0("cc", "ResourceProvider::CopyResource");
-
- Resource* source_resource = GetResource(source_id);
- DCHECK(!source_resource->lock_for_read_count);
- DCHECK(source_resource->origin == Resource::INTERNAL);
- DCHECK_EQ(source_resource->exported_count, 0);
- DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE, source_resource->type);
- LazyAllocate(source_resource);
-
- Resource* dest_resource = GetResource(dest_id);
- DCHECK(!dest_resource->locked_for_write);
- DCHECK(!dest_resource->lock_for_read_count);
- DCHECK(dest_resource->origin == Resource::INTERNAL);
- DCHECK_EQ(dest_resource->exported_count, 0);
- DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE, dest_resource->type);
- LazyAllocate(dest_resource);
-
- DCHECK_EQ(source_resource->type, dest_resource->type);
- DCHECK_EQ(source_resource->format, dest_resource->format);
- DCHECK(source_resource->size == dest_resource->size);
- DCHECK(gfx::Rect(dest_resource->size).Contains(rect));
-
- GLES2Interface* gl = ContextGL();
- DCHECK(gl);
- if (source_resource->image_id && source_resource->dirty_image) {
- gl->BindTexture(source_resource->target, source_resource->gl_id);
- BindImageForSampling(source_resource);
- }
- if (use_sync_query_) {
- if (!source_resource->gl_read_lock_query_id)
- gl->GenQueriesEXT(1, &source_resource->gl_read_lock_query_id);
-#if defined(OS_CHROMEOS)
- // TODO(reveman): This avoids a performance problem on some ChromeOS
- // devices. This needs to be removed to support native GpuMemoryBuffer
- // implementations. crbug.com/436314
- gl->BeginQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM,
- source_resource->gl_read_lock_query_id);
-#else
- gl->BeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM,
- source_resource->gl_read_lock_query_id);
-#endif
- }
- DCHECK(!dest_resource->image_id);
- dest_resource->allocated = true;
- gl->CopySubTextureCHROMIUM(dest_resource->target, source_resource->gl_id,
- dest_resource->gl_id, rect.x(), rect.y(), rect.x(),
- rect.y(), rect.width(), rect.height(),
- false, false, false);
- if (source_resource->gl_read_lock_query_id) {
- // End query and create a read lock fence that will prevent access to
-// source resource until CopySubTextureCHROMIUM command has completed.
-#if defined(OS_CHROMEOS)
- gl->EndQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM);
-#else
- gl->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM);
-#endif
- source_resource->read_lock_fence = make_scoped_refptr(
- new CopyTextureFence(gl, source_resource->gl_read_lock_query_id));
- } else {
- // Create a SynchronousFence when CHROMIUM_sync_query extension is missing.
- // Try to use one synchronous fence for as many CopyResource operations as
- // possible as that reduce the number of times we have to synchronize with
- // the GL.
- if (!synchronous_fence_.get() || synchronous_fence_->has_synchronized())
- synchronous_fence_ = make_scoped_refptr(new SynchronousFence(gl));
- source_resource->read_lock_fence = synchronous_fence_;
- source_resource->read_lock_fence->Set();
- }
-}
-
void ResourceProvider::WaitSyncPointIfNeeded(ResourceId id) {
Resource* resource = GetResource(id);
DCHECK_EQ(resource->exported_count, 0);
@@ -1925,21 +1582,19 @@ void ResourceProvider::WaitSyncPointIfNeeded(ResourceId id) {
resource->mailbox.set_sync_point(0);
}
-void ResourceProvider::WaitReadLockIfNeeded(ResourceId id) {
- Resource* resource = GetResource(id);
- DCHECK_EQ(resource->exported_count, 0);
- if (!resource->read_lock_fence.get())
- return;
-
- resource->read_lock_fence->Wait();
-}
-
GLint ResourceProvider::GetActiveTextureUnit(GLES2Interface* gl) {
GLint active_unit = 0;
gl->GetIntegerv(GL_ACTIVE_TEXTURE, &active_unit);
return active_unit;
}
+GLenum ResourceProvider::GetImageTextureTarget(ResourceFormat format) {
+ gfx::BufferFormat buffer_format = BufferFormat(format);
+ DCHECK_GT(use_image_texture_targets_.size(),
+ static_cast<size_t>(buffer_format));
+ return use_image_texture_targets_[static_cast<size_t>(buffer_format)];
+}
+
void ResourceProvider::ValidateResource(ResourceId id) const {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(id);
@@ -1958,4 +1613,57 @@ class GrContext* ResourceProvider::GrContext(bool worker_context) const {
return context_provider ? context_provider->GrContext() : NULL;
}
+bool ResourceProvider::OnMemoryDump(
+ const base::trace_event::MemoryDumpArgs& args,
+ base::trace_event::ProcessMemoryDump* pmd) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ const uint64 tracing_process_id =
+ base::trace_event::MemoryDumpManager::GetInstance()
+ ->GetTracingProcessId();
+
+ for (const auto& resource_entry : resources_) {
+ const auto& resource = resource_entry.second;
+
+ // Resource IDs are not process-unique, so log with the ResourceProvider's
+ // unique id.
+ std::string dump_name =
+ base::StringPrintf("cc/resource_memory/provider_%d/resource_%d",
+ tracing_id_, resource_entry.first);
+ base::trace_event::MemoryAllocatorDump* dump =
+ pmd->CreateAllocatorDump(dump_name);
+
+ uint64_t total_bytes = ResourceUtil::UncheckedSizeInBytesAligned<size_t>(
+ resource.size, resource.format);
+ dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+ static_cast<uint64_t>(total_bytes));
+
+ // Resources which are shared across processes require a shared GUID to
+ // prevent double counting the memory. We currently support shared GUIDs for
+ // GpuMemoryBuffer, SharedBitmap, and GL backed resources.
+ base::trace_event::MemoryAllocatorDumpGuid guid;
+ if (resource.gpu_memory_buffer) {
+ guid = gfx::GetGpuMemoryBufferGUIDForTracing(
+ tracing_process_id, resource.gpu_memory_buffer->GetHandle().id);
+ } else if (resource.shared_bitmap) {
+ guid = GetSharedBitmapGUIDForTracing(resource.shared_bitmap->id());
+ } else if (resource.gl_id && resource.allocated) {
+ guid = gfx::GetGLTextureClientGUIDForTracing(
+ output_surface_->context_provider()
+ ->ContextSupport()
+ ->ShareGroupTracingGUID(),
+ resource.gl_id);
+ }
+
+ if (!guid.empty()) {
+ const int kImportance = 2;
+ pmd->CreateSharedGlobalAllocatorDump(guid);
+ pmd->AddOwnershipEdge(dump->guid(), guid, kImportance);
+ }
+ }
+
+ return true;
+}
+
} // namespace cc
diff --git a/chromium/cc/resources/resource_provider.h b/chromium/cc/resources/resource_provider.h
index fbed140aa00..4af135eab57 100644
--- a/chromium/cc/resources/resource_provider.h
+++ b/chromium/cc/resources/resource_provider.h
@@ -17,6 +17,8 @@
#include "base/memory/linked_ptr.h"
#include "base/memory/scoped_ptr.h"
#include "base/threading/thread_checker.h"
+#include "base/trace_event/memory_allocator_dump.h"
+#include "base/trace_event/memory_dump_provider.h"
#include "cc/base/cc_export.h"
#include "cc/base/resource_id.h"
#include "cc/output/context_provider.h"
@@ -33,6 +35,7 @@
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/gpu_memory_buffer.h"
class GrContext;
@@ -44,7 +47,6 @@ class GLES2Interface;
}
namespace gfx {
-class GpuMemoryBuffer;
class Rect;
class Vector2d;
}
@@ -57,7 +59,8 @@ class SharedBitmapManager;
// This class is not thread-safe and can only be called from the thread it was
// created on (in practice, the impl thread).
-class CC_EXPORT ResourceProvider {
+class CC_EXPORT ResourceProvider
+ : public base::trace_event::MemoryDumpProvider {
private:
struct Resource;
@@ -83,25 +86,21 @@ class CC_EXPORT ResourceProvider {
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
BlockingTaskRunner* blocking_main_thread_task_runner,
int highp_threshold_min,
- bool use_rgba_4444_texture_format,
size_t id_allocation_chunk_size,
- bool use_persistent_map_for_gpu_memory_buffers);
- virtual ~ResourceProvider();
+ const std::vector<unsigned>& use_image_texture_targets);
+ ~ResourceProvider() override;
void DidLoseOutputSurface() { lost_output_surface_ = true; }
int max_texture_size() const { return max_texture_size_; }
- ResourceFormat memory_efficient_texture_format() const {
- return use_rgba_4444_texture_format_ ? RGBA_4444 : best_texture_format_;
- }
ResourceFormat best_texture_format() const { return best_texture_format_; }
ResourceFormat best_render_buffer_format() const {
return best_render_buffer_format_;
}
ResourceFormat yuv_resource_format() const { return yuv_resource_format_; }
bool use_sync_query() const { return use_sync_query_; }
- bool use_persistent_map_for_gpu_memory_buffers() const {
- return use_persistent_map_for_gpu_memory_buffers_;
+ gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager() {
+ return gpu_memory_buffer_manager_;
}
size_t num_resources() const { return resources_.size(); }
@@ -423,30 +422,30 @@ class CC_EXPORT ResourceProvider {
// Indicates if we can currently lock this resource for write.
bool CanLockForWrite(ResourceId id);
- // Copy |rect| pixels from source to destination.
- void CopyResource(ResourceId source_id,
- ResourceId dest_id,
- const gfx::Rect& rect);
-
void WaitSyncPointIfNeeded(ResourceId id);
- void WaitReadLockIfNeeded(ResourceId id);
-
static GLint GetActiveTextureUnit(gpu::gles2::GLES2Interface* gl);
OutputSurface* output_surface() { return output_surface_; }
void ValidateResource(ResourceId id) const;
+ GLenum GetImageTextureTarget(ResourceFormat format);
+
+ // base::trace_event::MemoryDumpProvider implementation.
+ bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
+ base::trace_event::ProcessMemoryDump* pmd) override;
+
+ int tracing_id() const { return tracing_id_; }
+
protected:
ResourceProvider(OutputSurface* output_surface,
SharedBitmapManager* shared_bitmap_manager,
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
BlockingTaskRunner* blocking_main_thread_task_runner,
int highp_threshold_min,
- bool use_rgba_4444_texture_format,
size_t id_allocation_chunk_size,
- bool use_persistent_map_for_gpu_memory_buffers);
+ const std::vector<unsigned>& use_image_texture_targets);
void Initialize();
private:
@@ -493,8 +492,6 @@ class CC_EXPORT ResourceProvider {
bool locked_for_write : 1;
bool lost : 1;
bool marked_for_deletion : 1;
- bool pending_set_pixels : 1;
- bool set_pixels_completion_forced : 1;
bool allocated : 1;
bool read_lock_fences_enabled : 1;
bool has_shared_bitmap_id : 1;
@@ -594,75 +591,21 @@ class CC_EXPORT ResourceProvider {
base::ThreadChecker thread_checker_;
scoped_refptr<Fence> current_read_lock_fence_;
- bool use_rgba_4444_texture_format_;
const size_t id_allocation_chunk_size_;
scoped_ptr<IdAllocator> texture_id_allocator_;
scoped_ptr<IdAllocator> buffer_id_allocator_;
bool use_sync_query_;
- bool use_persistent_map_for_gpu_memory_buffers_;
- // Fence used for CopyResource if CHROMIUM_sync_query is not supported.
- scoped_refptr<SynchronousFence> synchronous_fence_;
+ std::vector<unsigned> use_image_texture_targets_;
+
+ // A process-unique ID used for disambiguating memory dumps from different
+ // resource providers.
+ int tracing_id_;
DISALLOW_COPY_AND_ASSIGN(ResourceProvider);
};
-// TODO(epenner): Move these format conversions to resource_format.h
-// once that builds on mac (npapi.h currently #includes OpenGL.h).
-inline int BitsPerPixel(ResourceFormat format) {
- switch (format) {
- case BGRA_8888:
- case RGBA_8888:
- return 32;
- case RGBA_4444:
- case RGB_565:
- return 16;
- case ALPHA_8:
- case LUMINANCE_8:
- case RED_8:
- return 8;
- case ETC1:
- return 4;
- }
- NOTREACHED();
- return 0;
-}
-
-inline GLenum GLDataType(ResourceFormat format) {
- DCHECK_LE(format, RESOURCE_FORMAT_MAX);
- static const unsigned format_gl_data_type[RESOURCE_FORMAT_MAX + 1] = {
- GL_UNSIGNED_BYTE, // RGBA_8888
- GL_UNSIGNED_SHORT_4_4_4_4, // RGBA_4444
- GL_UNSIGNED_BYTE, // BGRA_8888
- GL_UNSIGNED_BYTE, // ALPHA_8
- GL_UNSIGNED_BYTE, // LUMINANCE_8
- GL_UNSIGNED_SHORT_5_6_5, // RGB_565,
- GL_UNSIGNED_BYTE, // ETC1
- GL_UNSIGNED_BYTE // RED_8
- };
- return format_gl_data_type[format];
-}
-
-inline GLenum GLDataFormat(ResourceFormat format) {
- DCHECK_LE(format, RESOURCE_FORMAT_MAX);
- static const unsigned format_gl_data_format[RESOURCE_FORMAT_MAX + 1] = {
- GL_RGBA, // RGBA_8888
- GL_RGBA, // RGBA_4444
- GL_BGRA_EXT, // BGRA_8888
- GL_ALPHA, // ALPHA_8
- GL_LUMINANCE, // LUMINANCE_8
- GL_RGB, // RGB_565
- GL_ETC1_RGB8_OES, // ETC1
- GL_RED_EXT // RED_8
- };
- return format_gl_data_format[format];
-}
-
-inline GLenum GLInternalFormat(ResourceFormat format) {
- return GLDataFormat(format);
-}
-
} // namespace cc
#endif // CC_RESOURCES_RESOURCE_PROVIDER_H_
diff --git a/chromium/cc/resources/resource_provider_unittest.cc b/chromium/cc/resources/resource_provider_unittest.cc
index 136855847db..bc4c89e39ea 100644
--- a/chromium/cc/resources/resource_provider_unittest.cc
+++ b/chromium/cc/resources/resource_provider_unittest.cc
@@ -7,6 +7,7 @@
#include <algorithm>
#include <map>
#include <set>
+#include <vector>
#include "base/bind.h"
#include "base/containers/hash_tables.h"
@@ -420,12 +421,12 @@ class ResourceProviderTest
resource_provider_ = ResourceProvider::Create(
output_surface_.get(), shared_bitmap_manager_.get(),
- gpu_memory_buffer_manager_.get(), main_thread_task_runner_.get(), 0,
- false, 1, false);
+ gpu_memory_buffer_manager_.get(), main_thread_task_runner_.get(), 0, 1,
+ use_image_texture_targets_);
child_resource_provider_ = ResourceProvider::Create(
child_output_surface_.get(), shared_bitmap_manager_.get(),
- gpu_memory_buffer_manager_.get(), main_thread_task_runner_.get(), 0,
- false, 1, false);
+ gpu_memory_buffer_manager_.get(), main_thread_task_runner_.get(), 0, 1,
+ use_image_texture_targets_);
}
ResourceProviderTest() : ResourceProviderTest(true) {}
@@ -485,7 +486,13 @@ class ResourceProviderTest
}
}
+ public:
+ static std::vector<unsigned> use_image_texture_targets() {
+ return use_image_texture_targets_;
+ }
+
protected:
+ static std::vector<unsigned> use_image_texture_targets_;
scoped_ptr<ContextSharedData> shared_data_;
ResourceProviderContext* context3d_;
ResourceProviderContext* child_context_;
@@ -500,6 +507,10 @@ class ResourceProviderTest
scoped_ptr<TestGpuMemoryBufferManager> gpu_memory_buffer_manager_;
};
+std::vector<unsigned> ResourceProviderTest::use_image_texture_targets_ =
+ std::vector<unsigned>(static_cast<size_t>(gfx::BufferFormat::LAST) + 1,
+ GL_TEXTURE_2D);
+
void CheckCreateResource(ResourceProvider::ResourceType expected_default_type,
ResourceProvider* resource_provider,
ResourceProviderContext* context) {
@@ -1367,7 +1378,8 @@ TEST_P(ResourceProviderTest, TransferGLToSoftware) {
scoped_ptr<ResourceProvider> child_resource_provider(ResourceProvider::Create(
child_output_surface.get(), shared_bitmap_manager_.get(),
- gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
+ gpu_memory_buffer_manager_.get(), NULL, 0, 1,
+ use_image_texture_targets_));
gfx::Size size(1, 1);
ResourceFormat format = RGBA_8888;
@@ -1850,8 +1862,8 @@ class ResourceProviderTestTextureFilters : public ResourceProviderTest {
scoped_ptr<ResourceProvider> child_resource_provider(
ResourceProvider::Create(child_output_surface.get(),
- shared_bitmap_manager.get(), NULL, NULL, 0,
- false, 1, false));
+ shared_bitmap_manager.get(), NULL, NULL, 0, 1,
+ use_image_texture_targets_));
scoped_ptr<TextureStateTrackingContext> parent_context_owned(
new TextureStateTrackingContext);
@@ -1864,8 +1876,8 @@ class ResourceProviderTestTextureFilters : public ResourceProviderTest {
scoped_ptr<ResourceProvider> parent_resource_provider(
ResourceProvider::Create(parent_output_surface.get(),
- shared_bitmap_manager.get(), NULL, NULL, 0,
- false, 1, false));
+ shared_bitmap_manager.get(), NULL, NULL, 0, 1,
+ use_image_texture_targets_));
gfx::Size size(1, 1);
ResourceFormat format = RGBA_8888;
@@ -2497,7 +2509,8 @@ TEST_P(ResourceProviderTest, ScopedSampler) {
scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
output_surface.get(), shared_bitmap_manager_.get(),
- gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
+ gpu_memory_buffer_manager_.get(), NULL, 0, 1,
+ use_image_texture_targets_));
gfx::Size size(1, 1);
ResourceFormat format = RGBA_8888;
@@ -2579,7 +2592,8 @@ TEST_P(ResourceProviderTest, ManagedResource) {
scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
output_surface.get(), shared_bitmap_manager_.get(),
- gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
+ gpu_memory_buffer_manager_.get(), NULL, 0, 1,
+ use_image_texture_targets_));
gfx::Size size(1, 1);
ResourceFormat format = RGBA_8888;
@@ -2626,7 +2640,8 @@ TEST_P(ResourceProviderTest, TextureWrapMode) {
scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
output_surface.get(), shared_bitmap_manager_.get(),
- gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
+ gpu_memory_buffer_manager_.get(), NULL, 0, 1,
+ use_image_texture_targets_));
gfx::Size size(1, 1);
ResourceFormat format = RGBA_8888;
@@ -2676,7 +2691,8 @@ TEST_P(ResourceProviderTest, TextureHint) {
scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
output_surface.get(), shared_bitmap_manager_.get(),
- gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
+ gpu_memory_buffer_manager_.get(), NULL, 0, 1,
+ use_image_texture_targets_));
gfx::Size size(1, 1);
ResourceFormat format = RGBA_8888;
@@ -2740,8 +2756,8 @@ TEST_P(ResourceProviderTest, TextureMailbox_SharedMemory) {
scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
output_surface.get(), shared_bitmap_manager_.get(),
- gpu_memory_buffer_manager_.get(), main_thread_task_runner_.get(), 0,
- false, 1, false));
+ gpu_memory_buffer_manager_.get(), main_thread_task_runner_.get(), 0, 1,
+ use_image_texture_targets_));
uint32 release_sync_point = 0;
bool lost_resource = false;
@@ -2790,7 +2806,7 @@ class ResourceProviderTestTextureMailboxGLFilters
scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
output_surface.get(), shared_bitmap_manager, gpu_memory_buffer_manager,
- main_thread_task_runner, 0, false, 1, false));
+ main_thread_task_runner, 0, 1, use_image_texture_targets_));
unsigned texture_id = 1;
uint32 sync_point = 30;
@@ -2933,7 +2949,8 @@ TEST_P(ResourceProviderTest, TextureMailbox_GLTextureExternalOES) {
scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
output_surface.get(), shared_bitmap_manager_.get(),
- gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
+ gpu_memory_buffer_manager_.get(), NULL, 0, 1,
+ use_image_texture_targets_));
uint32 sync_point = 30;
unsigned target = GL_TEXTURE_EXTERNAL_OES;
@@ -3002,7 +3019,8 @@ TEST_P(ResourceProviderTest,
scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
output_surface.get(), shared_bitmap_manager_.get(),
- gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
+ gpu_memory_buffer_manager_.get(), NULL, 0, 1,
+ use_image_texture_targets_));
uint32 sync_point = 30;
unsigned target = GL_TEXTURE_2D;
@@ -3055,7 +3073,8 @@ TEST_P(ResourceProviderTest, TextureMailbox_WaitSyncPointIfNeeded_NoSyncPoint) {
scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
output_surface.get(), shared_bitmap_manager_.get(),
- gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
+ gpu_memory_buffer_manager_.get(), NULL, 0, 1,
+ use_image_texture_targets_));
uint32 sync_point = 0;
unsigned target = GL_TEXTURE_2D;
@@ -3175,7 +3194,8 @@ TEST_P(ResourceProviderTest, TextureAllocation) {
scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
output_surface.get(), shared_bitmap_manager_.get(),
- gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
+ gpu_memory_buffer_manager_.get(), NULL, 0, 1,
+ use_image_texture_targets_));
gfx::Size size(2, 2);
gfx::Vector2d offset(0, 0);
@@ -3211,25 +3231,6 @@ TEST_P(ResourceProviderTest, TextureAllocation) {
resource_provider->DeleteResource(id);
Mock::VerifyAndClearExpectations(context);
-
- // Same for async version.
- id = resource_provider->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
- resource_provider->AcquirePixelBuffer(id);
-
- EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
- EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
- EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
- .Times(1);
- resource_provider->BeginSetPixels(id);
- ASSERT_TRUE(resource_provider->DidSetPixelsComplete(id));
-
- resource_provider->ReleasePixelBuffer(id);
-
- EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
- resource_provider->DeleteResource(id);
-
- Mock::VerifyAndClearExpectations(context);
}
TEST_P(ResourceProviderTest, TextureAllocationHint) {
@@ -3249,7 +3250,8 @@ TEST_P(ResourceProviderTest, TextureAllocationHint) {
scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
output_surface.get(), shared_bitmap_manager_.get(),
- gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
+ gpu_memory_buffer_manager_.get(), NULL, 0, 1,
+ use_image_texture_targets_));
gfx::Size size(2, 2);
@@ -3304,7 +3306,8 @@ TEST_P(ResourceProviderTest, TextureAllocationHint_BGRA) {
scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
output_surface.get(), shared_bitmap_manager_.get(),
- gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
+ gpu_memory_buffer_manager_.get(), NULL, 0, 1,
+ use_image_texture_targets_));
gfx::Size size(2, 2);
const ResourceFormat formats[2] = {RGBA_8888, BGRA_8888};
@@ -3339,126 +3342,6 @@ TEST_P(ResourceProviderTest, TextureAllocationHint_BGRA) {
}
}
-TEST_P(ResourceProviderTest, PixelBuffer_GLTexture) {
- if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
- return;
- scoped_ptr<AllocationTrackingContext3D> context_owned(
- new StrictMock<AllocationTrackingContext3D>);
- AllocationTrackingContext3D* context = context_owned.get();
-
- FakeOutputSurfaceClient output_surface_client;
- scoped_ptr<OutputSurface> output_surface(
- FakeOutputSurface::Create3d(context_owned.Pass()));
- CHECK(output_surface->BindToClient(&output_surface_client));
-
- gfx::Size size(2, 2);
- ResourceFormat format = RGBA_8888;
- ResourceId id = 0;
- int texture_id = 123;
-
- scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
- output_surface.get(), shared_bitmap_manager_.get(),
- gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
-
- id = resource_provider->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
- resource_provider->AcquirePixelBuffer(id);
-
- EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
- EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
- EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
- .Times(1);
- resource_provider->BeginSetPixels(id);
-
- EXPECT_TRUE(resource_provider->DidSetPixelsComplete(id));
-
- resource_provider->ReleasePixelBuffer(id);
-
- EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
- resource_provider->DeleteResource(id);
-
- Mock::VerifyAndClearExpectations(context);
-}
-
-TEST_P(ResourceProviderTest, ForcingAsyncUploadToComplete) {
- // Only for GL textures.
- if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
- return;
- scoped_ptr<AllocationTrackingContext3D> context_owned(
- new StrictMock<AllocationTrackingContext3D>);
- AllocationTrackingContext3D* context = context_owned.get();
-
- FakeOutputSurfaceClient output_surface_client;
- scoped_ptr<OutputSurface> output_surface(
- FakeOutputSurface::Create3d(context_owned.Pass()));
- CHECK(output_surface->BindToClient(&output_surface_client));
-
- gfx::Size size(2, 2);
- ResourceFormat format = RGBA_8888;
- ResourceId id = 0;
- int texture_id = 123;
-
- scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
- output_surface.get(), shared_bitmap_manager_.get(),
- gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
-
- id = resource_provider->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
- resource_provider->AcquirePixelBuffer(id);
-
- EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
- EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
- EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
- .Times(1);
- resource_provider->BeginSetPixels(id);
-
- EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1);
- EXPECT_CALL(*context, waitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D)).Times(1);
- EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, 0)).Times(1);
- resource_provider->ForceSetPixelsToComplete(id);
-
- resource_provider->ReleasePixelBuffer(id);
-
- EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
- resource_provider->DeleteResource(id);
-
- Mock::VerifyAndClearExpectations(context);
-}
-
-TEST_P(ResourceProviderTest, PixelBufferLostContext) {
- scoped_ptr<AllocationTrackingContext3D> context_owned(
- new NiceMock<AllocationTrackingContext3D>);
- AllocationTrackingContext3D* context = context_owned.get();
-
- FakeOutputSurfaceClient output_surface_client;
- scoped_ptr<OutputSurface> output_surface(
- FakeOutputSurface::Create3d(context_owned.Pass()));
- CHECK(output_surface->BindToClient(&output_surface_client));
-
- gfx::Size size(2, 2);
- ResourceFormat format = RGBA_8888;
- ResourceId id = 0;
- int texture_id = 123;
-
- scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
- output_surface.get(), shared_bitmap_manager_.get(),
- gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
-
- EXPECT_CALL(*context, NextTextureId()).WillRepeatedly(Return(texture_id));
-
- id = resource_provider->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
- context->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
- GL_INNOCENT_CONTEXT_RESET_ARB);
-
- resource_provider->AcquirePixelBuffer(id);
- int stride;
- void* buffer = resource_provider->MapPixelBuffer(id, &stride);
- EXPECT_FALSE(buffer);
- resource_provider->UnmapPixelBuffer(id);
- Mock::VerifyAndClearExpectations(context);
-}
-
TEST_P(ResourceProviderTest, Image_GLTexture) {
// Only for GL textures.
if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
@@ -3482,7 +3365,8 @@ TEST_P(ResourceProviderTest, Image_GLTexture) {
scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
output_surface.get(), shared_bitmap_manager_.get(),
- gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
+ gpu_memory_buffer_manager_.get(), NULL, 0, 1,
+ use_image_texture_targets_));
id = resource_provider->CreateResource(
size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
@@ -3542,87 +3426,6 @@ TEST_P(ResourceProviderTest, Image_GLTexture) {
.RetiresOnSaturation();
}
-TEST_P(ResourceProviderTest, CopyResource_GLTexture) {
- if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
- return;
- scoped_ptr<AllocationTrackingContext3D> context_owned(
- new StrictMock<AllocationTrackingContext3D>);
- AllocationTrackingContext3D* context = context_owned.get();
- context_owned->set_support_sync_query(true);
-
- FakeOutputSurfaceClient output_surface_client;
- scoped_ptr<OutputSurface> output_surface(
- FakeOutputSurface::Create3d(context_owned.Pass()));
- ASSERT_TRUE(output_surface->BindToClient(&output_surface_client));
-
- const int kWidth = 2;
- const int kHeight = 2;
- gfx::Size size(kWidth, kHeight);
- ResourceFormat format = RGBA_8888;
- ResourceId source_id = 0;
- ResourceId dest_id = 0;
- const unsigned kSourceTextureId = 123u;
- const unsigned kDestTextureId = 321u;
- const unsigned kImageId = 234u;
-
- scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
- output_surface.get(), shared_bitmap_manager_.get(),
- gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
-
- source_id = resource_provider->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
-
- EXPECT_CALL(*context, NextTextureId())
- .WillOnce(Return(kSourceTextureId))
- .RetiresOnSaturation();
- EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kSourceTextureId))
- .Times(1)
- .RetiresOnSaturation();
- EXPECT_CALL(*context, createImageCHROMIUM(_, kWidth, kHeight, GL_RGBA))
- .WillOnce(Return(kImageId))
- .RetiresOnSaturation();
- {
- ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
- resource_provider.get(), source_id);
- EXPECT_TRUE(lock.GetGpuMemoryBuffer());
- }
- Mock::VerifyAndClearExpectations(context);
-
- dest_id = resource_provider->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
-
- EXPECT_CALL(*context, NextTextureId())
- .WillOnce(Return(kDestTextureId))
- .RetiresOnSaturation();
- EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kDestTextureId))
- .Times(2)
- .RetiresOnSaturation();
- EXPECT_CALL(*context, texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA,
- GL_UNSIGNED_BYTE, nullptr))
- .Times(1)
- .RetiresOnSaturation();
- EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kSourceTextureId))
- .Times(1)
- .RetiresOnSaturation();
- EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
- .Times(1)
- .RetiresOnSaturation();
- resource_provider->CopyResource(source_id, dest_id, gfx::Rect(size));
- Mock::VerifyAndClearExpectations(context);
-
- EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId))
- .Times(1)
- .RetiresOnSaturation();
- EXPECT_CALL(*context, RetireTextureId(kSourceTextureId))
- .Times(1)
- .RetiresOnSaturation();
- EXPECT_CALL(*context, RetireTextureId(kDestTextureId))
- .Times(1)
- .RetiresOnSaturation();
- resource_provider->DeleteResource(source_id);
- resource_provider->DeleteResource(dest_id);
-}
-
TEST_P(ResourceProviderTest, CompressedTextureETC1Allocate) {
if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
return;
@@ -3640,7 +3443,8 @@ TEST_P(ResourceProviderTest, CompressedTextureETC1Allocate) {
gfx::Size size(4, 4);
scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
output_surface.get(), shared_bitmap_manager_.get(),
- gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
+ gpu_memory_buffer_manager_.get(), NULL, 0, 1,
+ use_image_texture_targets_));
int texture_id = 123;
ResourceId id = resource_provider->CreateResource(
@@ -3671,7 +3475,8 @@ TEST_P(ResourceProviderTest, CompressedTextureETC1Upload) {
gfx::Size size(4, 4);
scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
output_surface.get(), shared_bitmap_manager_.get(),
- gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
+ gpu_memory_buffer_manager_.get(), NULL, 0, 1,
+ use_image_texture_targets_));
int texture_id = 123;
uint8_t pixels[8];
@@ -3726,8 +3531,9 @@ TEST(ResourceProviderTest, TextureAllocationChunkSize) {
{
size_t kTextureAllocationChunkSize = 1;
scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
- output_surface.get(), shared_bitmap_manager.get(), NULL, NULL, 0, false,
- kTextureAllocationChunkSize, false));
+ output_surface.get(), shared_bitmap_manager.get(), NULL, NULL, 0,
+ kTextureAllocationChunkSize,
+ ResourceProviderTest::use_image_texture_targets()));
ResourceId id = resource_provider->CreateResource(
size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
@@ -3742,8 +3548,9 @@ TEST(ResourceProviderTest, TextureAllocationChunkSize) {
{
size_t kTextureAllocationChunkSize = 8;
scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
- output_surface.get(), shared_bitmap_manager.get(), NULL, NULL, 0, false,
- kTextureAllocationChunkSize, false));
+ output_surface.get(), shared_bitmap_manager.get(), NULL, NULL, 0,
+ kTextureAllocationChunkSize,
+ ResourceProviderTest::use_image_texture_targets()));
ResourceId id = resource_provider->CreateResource(
size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
diff --git a/chromium/cc/resources/resource_util.h b/chromium/cc/resources/resource_util.h
new file mode 100644
index 00000000000..9d9905b47d5
--- /dev/null
+++ b/chromium/cc/resources/resource_util.h
@@ -0,0 +1,222 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_RESOURCES_RESOURCE_UTIL_H_
+#define CC_RESOURCES_RESOURCE_UTIL_H_
+
+#include <limits>
+
+#include "base/numerics/safe_math.h"
+#include "cc/base/cc_export.h"
+#include "cc/base/math_util.h"
+#include "cc/resources/resource_format.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace cc {
+
+class CC_EXPORT ResourceUtil {
+ public:
+ // Returns true if the width is valid and fits in bytes, false otherwise.
+ template <typename T>
+ static bool VerifyWidthInBytes(int width, ResourceFormat format);
+ // Returns true if the size is valid and fits in bytes, false otherwise.
+ template <typename T>
+ static bool VerifySizeInBytes(const gfx::Size& size, ResourceFormat format);
+
+ // Dies with a CRASH() if the width can not be represented as a positive
+ // number of bytes.
+ template <typename T>
+ static T CheckedWidthInBytes(int width, ResourceFormat format);
+ // Dies with a CRASH() if the size can not be represented as a positive
+ // number of bytes.
+ template <typename T>
+ static T CheckedSizeInBytes(const gfx::Size& size, ResourceFormat format);
+
+ // Returns the width in bytes but may overflow or return 0. Only do this for
+ // computing widths for sizes that have already been checked.
+ template <typename T>
+ static T UncheckedWidthInBytes(int width, ResourceFormat format);
+ // Returns the size in bytes but may overflow or return 0. Only do this for
+ // sizes that have already been checked.
+ template <typename T>
+ static T UncheckedSizeInBytes(const gfx::Size& size, ResourceFormat format);
+ // Returns the width in bytes aligned but may overflow or return 0. Only do
+ // this for computing widths for sizes that have already been checked.
+ template <typename T>
+ static T UncheckedWidthInBytesAligned(int width, ResourceFormat format);
+ // Returns the size in bytes aligned but may overflow or return 0. Only do
+ // this for sizes that have already been checked.
+ template <typename T>
+ static T UncheckedSizeInBytesAligned(const gfx::Size& size,
+ ResourceFormat format);
+
+ private:
+ // TODO(prashant.n): Replace IsSameType with std::is_same once C++11 is used
+ // on all platforms.
+ template <typename T, typename U>
+ struct IsSameType {
+ static const bool value = false;
+ };
+
+ template <typename T>
+ struct IsSameType<T, T> {
+ static const bool value = true;
+ };
+
+ template <typename T>
+ static inline void VerifyType();
+
+ template <typename T>
+ static bool VerifyFitsInBytesInternal(int width,
+ int height,
+ ResourceFormat format,
+ bool verify_size,
+ bool aligned);
+
+ template <typename T>
+ static T BytesInternal(int width,
+ int height,
+ ResourceFormat format,
+ bool verify_size,
+ bool aligned);
+
+ DISALLOW_COPY_AND_ASSIGN(ResourceUtil);
+};
+
+template <typename T>
+bool ResourceUtil::VerifyWidthInBytes(int width, ResourceFormat format) {
+ VerifyType<T>();
+ return VerifyFitsInBytesInternal<T>(width, 0, format, false, false);
+}
+
+template <typename T>
+bool ResourceUtil::VerifySizeInBytes(const gfx::Size& size,
+ ResourceFormat format) {
+ VerifyType<T>();
+ return VerifyFitsInBytesInternal<T>(size.width(), size.height(), format, true,
+ false);
+}
+
+template <typename T>
+T ResourceUtil::CheckedWidthInBytes(int width, ResourceFormat format) {
+ VerifyType<T>();
+ DCHECK(VerifyFitsInBytesInternal<T>(width, 0, format, false, false));
+ base::CheckedNumeric<T> checked_value = BitsPerPixel(format);
+ checked_value *= width;
+ checked_value = MathUtil::CheckedRoundUp<T>(checked_value.ValueOrDie(), 8);
+ checked_value /= 8;
+ return checked_value.ValueOrDie();
+}
+
+template <typename T>
+T ResourceUtil::CheckedSizeInBytes(const gfx::Size& size,
+ ResourceFormat format) {
+ VerifyType<T>();
+ DCHECK(VerifyFitsInBytesInternal<T>(size.width(), size.height(), format, true,
+ false));
+ base::CheckedNumeric<T> checked_value = BitsPerPixel(format);
+ checked_value *= size.width();
+ checked_value = MathUtil::CheckedRoundUp<T>(checked_value.ValueOrDie(), 8);
+ checked_value /= 8;
+ checked_value *= size.height();
+ return checked_value.ValueOrDie();
+}
+
+template <typename T>
+T ResourceUtil::UncheckedWidthInBytes(int width, ResourceFormat format) {
+ VerifyType<T>();
+ DCHECK(VerifyFitsInBytesInternal<T>(width, 0, format, false, false));
+ return BytesInternal<T>(width, 0, format, false, false);
+}
+
+template <typename T>
+T ResourceUtil::UncheckedSizeInBytes(const gfx::Size& size,
+ ResourceFormat format) {
+ VerifyType<T>();
+ DCHECK(VerifyFitsInBytesInternal<T>(size.width(), size.height(), format, true,
+ false));
+ return BytesInternal<T>(size.width(), size.height(), format, true, false);
+}
+
+template <typename T>
+T ResourceUtil::UncheckedWidthInBytesAligned(int width, ResourceFormat format) {
+ VerifyType<T>();
+ DCHECK(VerifyFitsInBytesInternal<T>(width, 0, format, false, true));
+ return BytesInternal<T>(width, 0, format, false, true);
+}
+
+template <typename T>
+T ResourceUtil::UncheckedSizeInBytesAligned(const gfx::Size& size,
+ ResourceFormat format) {
+ VerifyType<T>();
+ DCHECK(VerifyFitsInBytesInternal<T>(size.width(), size.height(), format, true,
+ true));
+ return BytesInternal<T>(size.width(), size.height(), format, true, true);
+}
+
+template <typename T>
+void ResourceUtil::VerifyType() {
+ static_assert(
+ std::numeric_limits<T>::is_integer && !IsSameType<T, bool>::value,
+ "T must be non-bool integer type. Preferred type is size_t.");
+}
+
+template <typename T>
+bool ResourceUtil::VerifyFitsInBytesInternal(int width,
+ int height,
+ ResourceFormat format,
+ bool verify_size,
+ bool aligned) {
+ base::CheckedNumeric<T> checked_value = BitsPerPixel(format);
+ checked_value *= width;
+ if (!checked_value.IsValid())
+ return false;
+
+ // Roundup bits to byte (8 bits) boundary. If width is 3 and BitsPerPixel is
+ // 4, then it should return 16, so that row pixels do not get truncated.
+ checked_value = MathUtil::UncheckedRoundUp<T>(checked_value.ValueOrDie(), 8);
+
+ // If aligned is true, bytes are aligned on 4-bytes boundaries for upload
+ // performance, assuming that GL_PACK_ALIGNMENT or GL_UNPACK_ALIGNMENT have
+ // not changed from default.
+ if (aligned) {
+ checked_value /= 8;
+ if (!checked_value.IsValid())
+ return false;
+ checked_value =
+ MathUtil::UncheckedRoundUp<T>(checked_value.ValueOrDie(), 4);
+ checked_value *= 8;
+ }
+
+ if (verify_size)
+ checked_value *= height;
+ if (!checked_value.IsValid())
+ return false;
+ T value = checked_value.ValueOrDie();
+ if ((value % 8) != 0)
+ return false;
+ return true;
+}
+
+template <typename T>
+T ResourceUtil::BytesInternal(int width,
+ int height,
+ ResourceFormat format,
+ bool verify_size,
+ bool aligned) {
+ T bytes = BitsPerPixel(format);
+ bytes *= width;
+ bytes = MathUtil::UncheckedRoundUp<T>(bytes, 8);
+ bytes /= 8;
+ if (aligned)
+ bytes = MathUtil::UncheckedRoundUp<T>(bytes, 4);
+ if (verify_size)
+ bytes *= height;
+
+ return bytes;
+}
+
+} // namespace cc
+
+#endif // CC_RESOURCES_RESOURCE_UTIL_H_
diff --git a/chromium/cc/resources/resource_util_unittest.cc b/chromium/cc/resources/resource_util_unittest.cc
new file mode 100644
index 00000000000..1fabc3b4f66
--- /dev/null
+++ b/chromium/cc/resources/resource_util_unittest.cc
@@ -0,0 +1,167 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/logging.h"
+#include "cc/resources/resource_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace cc {
+namespace {
+
+struct TestFormat {
+ ResourceFormat format;
+ size_t expected_bytes;
+ size_t expected_bytes_aligned;
+};
+
+// Modify this constant as per TestFormat variables defined in following tests.
+const int kTestFormats = 4;
+
+class ResourceUtilTest : public testing::Test {
+ public:
+ void TestVerifyWidthInBytes(int width, const TestFormat* test_formats) {
+ for (int i = 0; i < kTestFormats; ++i) {
+ EXPECT_TRUE(ResourceUtil::VerifyWidthInBytes<size_t>(
+ width, test_formats[i].format));
+ }
+ }
+
+ void TestCheckedWidthInBytes(int width, const TestFormat* test_formats) {
+ for (int i = 0; i < kTestFormats; ++i) {
+ size_t bytes = ResourceUtil::CheckedWidthInBytes<size_t>(
+ width, test_formats[i].format);
+ EXPECT_EQ(bytes, test_formats[i].expected_bytes);
+ }
+ }
+
+ void TestUncheckedWidthInBytes(int width, const TestFormat* test_formats) {
+ for (int i = 0; i < kTestFormats; ++i) {
+ size_t bytes = ResourceUtil::UncheckedWidthInBytes<size_t>(
+ width, test_formats[i].format);
+ EXPECT_EQ(bytes, test_formats[i].expected_bytes);
+ }
+ }
+
+ void TestUncheckedWidthInBytesAligned(int width,
+ const TestFormat* test_formats) {
+ for (int i = 0; i < kTestFormats; ++i) {
+ size_t bytes = ResourceUtil::UncheckedWidthInBytesAligned<size_t>(
+ width, test_formats[i].format);
+ EXPECT_EQ(bytes, test_formats[i].expected_bytes_aligned);
+ }
+ }
+
+ void TestVerifySizeInBytes(const gfx::Size& size,
+ const TestFormat* test_formats) {
+ for (int i = 0; i < kTestFormats; ++i) {
+ EXPECT_TRUE(ResourceUtil::VerifySizeInBytes<size_t>(
+ size, test_formats[i].format));
+ }
+ }
+
+ void TestCheckedSizeInBytes(const gfx::Size& size,
+ const TestFormat* test_formats) {
+ for (int i = 0; i < kTestFormats; ++i) {
+ size_t bytes = ResourceUtil::CheckedSizeInBytes<size_t>(
+ size, test_formats[i].format);
+ EXPECT_EQ(bytes, test_formats[i].expected_bytes);
+ }
+ }
+
+ void TestUncheckedSizeInBytes(const gfx::Size& size,
+ const TestFormat* test_formats) {
+ for (int i = 0; i < kTestFormats; ++i) {
+ size_t bytes = ResourceUtil::UncheckedSizeInBytes<size_t>(
+ size, test_formats[i].format);
+ EXPECT_EQ(bytes, test_formats[i].expected_bytes);
+ }
+ }
+
+ void TestUncheckedSizeInBytesAligned(const gfx::Size& size,
+ const TestFormat* test_formats) {
+ for (int i = 0; i < kTestFormats; ++i) {
+ size_t bytes = ResourceUtil::UncheckedSizeInBytesAligned<size_t>(
+ size, test_formats[i].format);
+ EXPECT_EQ(bytes, test_formats[i].expected_bytes_aligned);
+ }
+ }
+};
+
+TEST_F(ResourceUtilTest, WidthInBytes) {
+ // Check bytes for even width.
+ int width = 10;
+ TestFormat test_formats[] = {
+ {RGBA_8888, 40, 40}, // for 32 bits
+ {RGBA_4444, 20, 20}, // for 16 bits
+ {ALPHA_8, 10, 12}, // for 8 bits
+ {ETC1, 5, 8} // for 4 bits
+ };
+
+ TestVerifyWidthInBytes(width, test_formats);
+ TestCheckedWidthInBytes(width, test_formats);
+ TestUncheckedWidthInBytes(width, test_formats);
+ TestUncheckedWidthInBytesAligned(width, test_formats);
+
+ // Check bytes for odd width.
+ int width_odd = 11;
+ TestFormat test_formats_odd[] = {
+ {RGBA_8888, 44, 44}, // for 32 bits
+ {RGBA_4444, 22, 24}, // for 16 bits
+ {ALPHA_8, 11, 12}, // for 8 bits
+ {ETC1, 6, 8} // for 4 bits
+ };
+
+ TestVerifyWidthInBytes(width_odd, test_formats_odd);
+ TestCheckedWidthInBytes(width_odd, test_formats_odd);
+ TestUncheckedWidthInBytes(width_odd, test_formats_odd);
+ TestUncheckedWidthInBytesAligned(width_odd, test_formats_odd);
+}
+
+TEST_F(ResourceUtilTest, SizeInBytes) {
+ // Check bytes for even size.
+ gfx::Size size(10, 10);
+ TestFormat test_formats[] = {
+ {RGBA_8888, 400, 400}, // for 32 bits
+ {RGBA_4444, 200, 200}, // for 16 bits
+ {ALPHA_8, 100, 120}, // for 8 bits
+ {ETC1, 50, 80} // for 4 bits
+ };
+
+ TestVerifySizeInBytes(size, test_formats);
+ TestCheckedSizeInBytes(size, test_formats);
+ TestUncheckedSizeInBytes(size, test_formats);
+ TestUncheckedSizeInBytesAligned(size, test_formats);
+
+ // Check bytes for odd size.
+ gfx::Size size_odd(11, 11);
+ TestFormat test_formats_odd[] = {
+ {RGBA_8888, 484, 484}, // for 32 bits
+ {RGBA_4444, 242, 264}, // for 16 bits
+ {ALPHA_8, 121, 132}, // for 8 bits
+ {ETC1, 66, 88} // for 4 bits
+ };
+
+ TestVerifySizeInBytes(size_odd, test_formats_odd);
+ TestCheckedSizeInBytes(size_odd, test_formats_odd);
+ TestUncheckedSizeInBytes(size_odd, test_formats_odd);
+ TestUncheckedSizeInBytesAligned(size_odd, test_formats_odd);
+}
+
+TEST_F(ResourceUtilTest, WidthInBytesOverflow) {
+ int width = 10;
+ // 10 * 16 = 160 bits, overflows in char, but fits in unsigned char.
+ EXPECT_FALSE(ResourceUtil::VerifyWidthInBytes<signed char>(width, RGBA_4444));
+ EXPECT_TRUE(
+ ResourceUtil::VerifyWidthInBytes<unsigned char>(width, RGBA_4444));
+}
+
+TEST_F(ResourceUtilTest, SizeInBytesOverflow) {
+ gfx::Size size(10, 10);
+ // 10 * 16 * 10 = 1600 bits, overflows in char, but fits in int.
+ EXPECT_FALSE(ResourceUtil::VerifySizeInBytes<signed char>(size, RGBA_4444));
+ EXPECT_TRUE(ResourceUtil::VerifySizeInBytes<int>(size, RGBA_4444));
+}
+
+} // namespace
+} // namespace cc
diff --git a/chromium/cc/resources/returned_resource.h b/chromium/cc/resources/returned_resource.h
index 767d16f8dee..94a574e9813 100644
--- a/chromium/cc/resources/returned_resource.h
+++ b/chromium/cc/resources/returned_resource.h
@@ -13,11 +13,30 @@
namespace cc {
+// A ReturnedResource is a struct passed along to a child compositor from a
+// parent compositor that corresponds to a TransferableResource that was
+// first passed to the parent compositor.
struct CC_EXPORT ReturnedResource {
ReturnedResource() : id(0), sync_point(0), count(0), lost(false) {}
+ // |id| is an identifier generated by the child compositor that uniquely
+ // identifies a resource. This is the same ID space as TransferableResource.
ResourceId id;
+
+ // A |sync_point| is an identifier for a point in the parent compositor's
+ // command buffer. The child compositor then issues a WaitSyncPointCHROMIUM
+ // command with this |sync_point| as a parameter into its own command buffer.
+ // This ensures that uses of the resource submitted by the parent compositor
+ // are executed before commands submitted by the child.
unsigned sync_point;
+
+ // |count| is a reference count for this resource. A resource may be used
+ // by mulitple compositor frames submitted to the parent compositor. |count|
+ // is the number of references being returned back to the child compositor.
int count;
+
+ // If the resource is lost, then the returner cannot give a sync point for it,
+ // and so it has taken ownership of the resource. The receiver cannot do
+ // anything with the resource except delete it.
bool lost;
};
diff --git a/chromium/cc/resources/scoped_resource_unittest.cc b/chromium/cc/resources/scoped_resource_unittest.cc
index 197fa1f3b8d..cb41bf6fc8a 100644
--- a/chromium/cc/resources/scoped_resource_unittest.cc
+++ b/chromium/cc/resources/scoped_resource_unittest.cc
@@ -31,8 +31,8 @@ TEST(ScopedResourceTest, NewScopedResource) {
// New scoped textures do not have a size yet.
EXPECT_EQ(gfx::Size(), texture->size());
- EXPECT_EQ(0u, Resource::UncheckedMemorySizeBytes(texture->size(),
- texture->format()));
+ EXPECT_EQ(0u, ResourceUtil::UncheckedSizeInBytes<size_t>(texture->size(),
+ texture->format()));
}
TEST(ScopedResourceTest, CreateScopedResource) {
@@ -51,7 +51,7 @@ TEST(ScopedResourceTest, CreateScopedResource) {
// The texture has an allocated byte-size now.
size_t expected_bytes = 30 * 30 * 4;
- EXPECT_EQ(expected_bytes, Resource::UncheckedMemorySizeBytes(
+ EXPECT_EQ(expected_bytes, ResourceUtil::UncheckedSizeInBytes<size_t>(
texture->size(), texture->format()));
EXPECT_LT(0u, texture->id());
diff --git a/chromium/cc/resources/shared_bitmap.cc b/chromium/cc/resources/shared_bitmap.cc
index 1ac03233dfb..fc15736315b 100644
--- a/chromium/cc/resources/shared_bitmap.cc
+++ b/chromium/cc/resources/shared_bitmap.cc
@@ -7,6 +7,8 @@
#include "base/logging.h"
#include "base/numerics/safe_math.h"
#include "base/rand_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/stringprintf.h"
namespace cc {
@@ -66,4 +68,11 @@ SharedBitmapId SharedBitmap::GenerateId() {
return id;
}
+base::trace_event::MemoryAllocatorDumpGuid GetSharedBitmapGUIDForTracing(
+ const SharedBitmapId& bitmap_id) {
+ auto bitmap_id_hex = base::HexEncode(bitmap_id.name, sizeof(bitmap_id.name));
+ return base::trace_event::MemoryAllocatorDumpGuid(
+ base::StringPrintf("sharedbitmap-x-process/%s", bitmap_id_hex.c_str()));
+}
+
} // namespace cc
diff --git a/chromium/cc/resources/shared_bitmap.h b/chromium/cc/resources/shared_bitmap.h
index 6980afbc112..04dab7456fa 100644
--- a/chromium/cc/resources/shared_bitmap.h
+++ b/chromium/cc/resources/shared_bitmap.h
@@ -6,6 +6,7 @@
#define CC_RESOURCES_SHARED_BITMAP_H_
#include "base/basictypes.h"
+#include "base/trace_event/memory_allocator_dump.h"
#include "cc/base/cc_export.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "ui/gfx/geometry/size.h"
@@ -13,6 +14,9 @@
namespace cc {
typedef gpu::Mailbox SharedBitmapId;
+CC_EXPORT base::trace_event::MemoryAllocatorDumpGuid
+GetSharedBitmapGUIDForTracing(const SharedBitmapId& bitmap_id);
+
class CC_EXPORT SharedBitmap {
public:
SharedBitmap(uint8* pixels, const SharedBitmapId& id);
diff --git a/chromium/cc/resources/video_resource_updater.cc b/chromium/cc/resources/video_resource_updater.cc
index e973a3d5240..3dc89ac79bf 100644
--- a/chromium/cc/resources/video_resource_updater.cc
+++ b/chromium/cc/resources/video_resource_updater.cc
@@ -25,6 +25,50 @@ namespace {
const ResourceFormat kRGBResourceFormat = RGBA_8888;
+VideoFrameExternalResources::ResourceType ResourceTypeForVideoFrame(
+ media::VideoFrame* video_frame) {
+ switch (video_frame->format()) {
+ case media::PIXEL_FORMAT_ARGB:
+ case media::PIXEL_FORMAT_XRGB:
+ case media::PIXEL_FORMAT_UYVY:
+ switch (video_frame->mailbox_holder(0).texture_target) {
+ case GL_TEXTURE_2D:
+ return (video_frame->format() == media::PIXEL_FORMAT_XRGB)
+ ? VideoFrameExternalResources::RGB_RESOURCE
+ : VideoFrameExternalResources::RGBA_RESOURCE;
+ case GL_TEXTURE_EXTERNAL_OES:
+ return VideoFrameExternalResources::STREAM_TEXTURE_RESOURCE;
+ case GL_TEXTURE_RECTANGLE_ARB:
+ return VideoFrameExternalResources::IO_SURFACE;
+ default:
+ NOTREACHED();
+ break;
+ }
+ break;
+ case media::PIXEL_FORMAT_I420:
+ return VideoFrameExternalResources::YUV_RESOURCE;
+ break;
+ case media::PIXEL_FORMAT_NV12:
+ DCHECK_EQ(static_cast<uint32_t>(GL_TEXTURE_RECTANGLE_ARB),
+ video_frame->mailbox_holder(0).texture_target);
+ return VideoFrameExternalResources::IO_SURFACE;
+ break;
+ case media::PIXEL_FORMAT_YV12:
+ case media::PIXEL_FORMAT_YV16:
+ case media::PIXEL_FORMAT_YV24:
+ case media::PIXEL_FORMAT_YV12A:
+ case media::PIXEL_FORMAT_NV21:
+ case media::PIXEL_FORMAT_YUY2:
+ case media::PIXEL_FORMAT_RGB24:
+ case media::PIXEL_FORMAT_RGB32:
+ case media::PIXEL_FORMAT_MJPEG:
+ case media::PIXEL_FORMAT_MT21:
+ case media::PIXEL_FORMAT_UNKNOWN:
+ break;
+ }
+ return VideoFrameExternalResources::NONE;
+}
+
class SyncPointClientImpl : public media::VideoFrame::SyncPointClient {
public:
explicit SyncPointClientImpl(gpu::gles2::GLES2Interface* gl,
@@ -139,7 +183,14 @@ void VideoResourceUpdater::DeleteResource(ResourceList::iterator resource_it) {
VideoFrameExternalResources VideoResourceUpdater::
CreateExternalResourcesFromVideoFrame(
const scoped_refptr<media::VideoFrame>& video_frame) {
- if (video_frame->format() == media::VideoFrame::UNKNOWN)
+#if defined(VIDEO_HOLE)
+ if (video_frame->storage_type() == media::VideoFrame::STORAGE_HOLE) {
+ VideoFrameExternalResources external_resources;
+ external_resources.type = VideoFrameExternalResources::HOLE;
+ return external_resources;
+ }
+#endif // defined(VIDEO_HOLE)
+ if (video_frame->format() == media::PIXEL_FORMAT_UNKNOWN)
return VideoFrameExternalResources();
DCHECK(video_frame->HasTextures() || video_frame->IsMappable());
if (video_frame->HasTextures())
@@ -164,19 +215,11 @@ static gfx::Size SoftwarePlaneDimension(
VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
const scoped_refptr<media::VideoFrame>& video_frame) {
TRACE_EVENT0("cc", "VideoResourceUpdater::CreateForSoftwarePlanes");
- const media::VideoFrame::Format input_frame_format = video_frame->format();
-
-#if defined(VIDEO_HOLE)
- if (video_frame->storage_type() == media::VideoFrame::STORAGE_HOLE) {
- VideoFrameExternalResources external_resources;
- external_resources.type = VideoFrameExternalResources::HOLE;
- return external_resources;
- }
-#endif // defined(VIDEO_HOLE)
+ const media::VideoPixelFormat input_frame_format = video_frame->format();
// Only YUV software video frames are supported.
- if (!media::VideoFrame::IsYuvPlanar(input_frame_format)) {
- NOTREACHED() << media::VideoFrame::FormatToString(input_frame_format);
+ if (!media::IsYuvPlanar(input_frame_format)) {
+ NOTREACHED() << media::VideoPixelFormatToString(input_frame_format);
return VideoFrameExternalResources();
}
@@ -305,16 +348,19 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
gfx::Size resource_size_pixels = plane_resource.resource_size;
// The |video_stride_pixels| is the width of the video frame we are
// uploading (including non-frame data to fill in the stride).
- size_t video_stride_pixels = video_frame->stride(i);
+ int video_stride_pixels = video_frame->stride(i);
- size_t bytes_per_pixel = BitsPerPixel(plane_resource.resource_format) / 8;
+ size_t bytes_per_row = ResourceUtil::UncheckedWidthInBytes<size_t>(
+ resource_size_pixels.width(), plane_resource.resource_format);
// Use 4-byte row alignment (OpenGL default) for upload performance.
// Assuming that GL_UNPACK_ALIGNMENT has not changed from default.
- size_t upload_image_stride = MathUtil::RoundUp<size_t>(
- bytes_per_pixel * resource_size_pixels.width(), 4u);
+ size_t upload_image_stride =
+ MathUtil::UncheckedRoundUp<size_t>(bytes_per_row, 4u);
const uint8_t* pixels;
- if (upload_image_stride == video_stride_pixels * bytes_per_pixel) {
+ size_t video_bytes_per_row = ResourceUtil::UncheckedWidthInBytes<size_t>(
+ video_stride_pixels, plane_resource.resource_format);
+ if (upload_image_stride == video_bytes_per_row) {
pixels = video_frame->data(i);
} else {
// Avoid malloc for each frame/plane if possible.
@@ -324,9 +370,9 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
upload_pixels_.resize(needed_size);
for (int row = 0; row < resource_size_pixels.height(); ++row) {
uint8_t* dst = &upload_pixels_[upload_image_stride * row];
- const uint8_t* src = video_frame->data(i) +
- bytes_per_pixel * video_stride_pixels * row;
- memcpy(dst, src, resource_size_pixels.width() * bytes_per_pixel);
+ const uint8_t* src =
+ video_frame->data(i) + (video_bytes_per_row * row);
+ memcpy(dst, src, bytes_per_row);
}
pixels = &upload_pixels_[0];
}
@@ -372,52 +418,21 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForHardwarePlanes(
if (!context_provider_)
return VideoFrameExternalResources();
- const size_t textures = media::VideoFrame::NumPlanes(video_frame->format());
- DCHECK_GE(textures, 1u);
VideoFrameExternalResources external_resources;
external_resources.read_lock_fences_enabled = true;
- switch (video_frame->format()) {
- case media::VideoFrame::ARGB:
- case media::VideoFrame::XRGB:
- DCHECK_EQ(1u, textures);
- switch (video_frame->mailbox_holder(0).texture_target) {
- case GL_TEXTURE_2D:
- external_resources.type =
- (video_frame->format() == media::VideoFrame::XRGB)
- ? VideoFrameExternalResources::RGB_RESOURCE
- : VideoFrameExternalResources::RGBA_RESOURCE;
- break;
- case GL_TEXTURE_EXTERNAL_OES:
- external_resources.type =
- VideoFrameExternalResources::STREAM_TEXTURE_RESOURCE;
- break;
- case GL_TEXTURE_RECTANGLE_ARB:
- external_resources.type = VideoFrameExternalResources::IO_SURFACE;
- break;
- default:
- NOTREACHED();
- return VideoFrameExternalResources();
- }
- break;
- case media::VideoFrame::I420:
- external_resources.type = VideoFrameExternalResources::YUV_RESOURCE;
- break;
-#if defined(OS_MACOSX) || defined(OS_CHROMEOS)
- case media::VideoFrame::NV12:
-#endif
- case media::VideoFrame::YV12:
- case media::VideoFrame::YV16:
- case media::VideoFrame::YV24:
- case media::VideoFrame::YV12A:
- case media::VideoFrame::UNKNOWN:
- DLOG(ERROR) << "Unsupported Texture format"
- << media::VideoFrame::FormatToString(video_frame->format());
- return external_resources;
+
+ external_resources.type = ResourceTypeForVideoFrame(video_frame.get());
+ if (external_resources.type == VideoFrameExternalResources::NONE) {
+ DLOG(ERROR) << "Unsupported Texture format"
+ << media::VideoPixelFormatToString(video_frame->format());
+ return external_resources;
}
- DCHECK_NE(VideoFrameExternalResources::NONE, external_resources.type);
- for (size_t i = 0; i < textures; ++i) {
+ const size_t num_planes = media::VideoFrame::NumPlanes(video_frame->format());
+ for (size_t i = 0; i < num_planes; ++i) {
const gpu::MailboxHolder& mailbox_holder = video_frame->mailbox_holder(i);
+ if (mailbox_holder.mailbox.IsZero())
+ break;
external_resources.mailboxes.push_back(
TextureMailbox(mailbox_holder.mailbox, mailbox_holder.texture_target,
mailbox_holder.sync_point, video_frame->coded_size(),
diff --git a/chromium/cc/resources/video_resource_updater_unittest.cc b/chromium/cc/resources/video_resource_updater_unittest.cc
index 3e4574d989c..3d4bf1778ba 100644
--- a/chromium/cc/resources/video_resource_updater_unittest.cc
+++ b/chromium/cc/resources/video_resource_updater_unittest.cc
@@ -4,7 +4,6 @@
#include "cc/resources/video_resource_updater.h"
-#include "base/memory/shared_memory.h"
#include "cc/resources/resource_provider.h"
#include "cc/test/fake_output_surface.h"
#include "cc/test/fake_output_surface_client.h"
@@ -87,17 +86,17 @@ class VideoResourceUpdaterTest : public testing::Test {
static uint8 v_data[kDimension * kDimension / 2] = { 0 };
return media::VideoFrame::WrapExternalYuvData(
- media::VideoFrame::YV16, // format
- size, // coded_size
- gfx::Rect(size), // visible_rect
- size, // natural_size
- size.width(), // y_stride
- size.width() / 2, // u_stride
- size.width() / 2, // v_stride
- y_data, // y_data
- u_data, // u_data
- v_data, // v_data
- base::TimeDelta()); // timestamp
+ media::PIXEL_FORMAT_YV16, // format
+ size, // coded_size
+ gfx::Rect(size), // visible_rect
+ size, // natural_size
+ size.width(), // y_stride
+ size.width() / 2, // u_stride
+ size.width() / 2, // v_stride
+ y_data, // y_data
+ u_data, // u_data
+ v_data, // v_data
+ base::TimeDelta()); // timestamp
}
static void ReleaseMailboxCB(unsigned sync_point) {}
@@ -112,7 +111,7 @@ class VideoResourceUpdaterTest : public testing::Test {
const unsigned sync_point = 7;
const unsigned target = GL_TEXTURE_2D;
return media::VideoFrame::WrapNativeTexture(
- media::VideoFrame::ARGB,
+ media::PIXEL_FORMAT_ARGB,
gpu::MailboxHolder(mailbox, target, sync_point),
base::Bind(&ReleaseMailboxCB),
size, // coded_size
diff --git a/chromium/cc/scheduler/begin_frame_source_unittest.cc b/chromium/cc/scheduler/begin_frame_source_unittest.cc
index 1f85622878e..2c12ca90fcc 100644
--- a/chromium/cc/scheduler/begin_frame_source_unittest.cc
+++ b/chromium/cc/scheduler/begin_frame_source_unittest.cc
@@ -6,7 +6,6 @@
#include <string>
#include "base/basictypes.h"
-#include "base/gtest_prod_util.h"
#include "base/test/test_simple_task_runner.h"
#include "cc/scheduler/begin_frame_source.h"
#include "cc/test/begin_frame_args_test.h"
diff --git a/chromium/cc/scheduler/compositor_timing_history.cc b/chromium/cc/scheduler/compositor_timing_history.cc
index b46c8a15cbe..34726d5ddf8 100644
--- a/chromium/cc/scheduler/compositor_timing_history.cc
+++ b/chromium/cc/scheduler/compositor_timing_history.cc
@@ -8,21 +8,194 @@
#include "base/trace_event/trace_event.h"
#include "cc/debug/rendering_stats_instrumentation.h"
-// The estimates that affect the compositors deadline use the 100th percentile
-// to avoid missing the Browser's deadline.
-// The estimates related to main-thread responsiveness affect whether
-// we attempt to recovery latency or not and use the 50th percentile.
+namespace cc {
+
+class CompositorTimingHistory::UMAReporter {
+ public:
+ virtual ~UMAReporter() {}
+
+ virtual void AddBeginMainFrameToCommitDuration(base::TimeDelta duration,
+ base::TimeDelta estimate,
+ bool affects_estimate) = 0;
+ virtual void AddCommitToReadyToActivateDuration(base::TimeDelta duration,
+ base::TimeDelta estimate,
+ bool affects_estimate) = 0;
+ virtual void AddPrepareTilesDuration(base::TimeDelta duration,
+ base::TimeDelta estimate,
+ bool affects_estimate) = 0;
+ virtual void AddActivateDuration(base::TimeDelta duration,
+ base::TimeDelta estimate,
+ bool affects_estimate) = 0;
+ virtual void AddDrawDuration(base::TimeDelta duration,
+ base::TimeDelta estimate,
+ bool affects_estimate) = 0;
+};
+
+namespace {
+
+// Using the 90th percentile will disable latency recovery
+// if we are missing the deadline approximately ~6 times per
+// second.
// TODO(brianderson): Fine tune the percentiles below.
const size_t kDurationHistorySize = 60;
-const double kBeginMainFrameToCommitEstimationPercentile = 50.0;
-const double kCommitToReadyToActivateEstimationPercentile = 50.0;
-const double kPrepareTilesEstimationPercentile = 100.0;
-const double kActivateEstimationPercentile = 100.0;
-const double kDrawEstimationPercentile = 100.0;
+const double kBeginMainFrameToCommitEstimationPercentile = 90.0;
+const double kCommitToReadyToActivateEstimationPercentile = 90.0;
+const double kPrepareTilesEstimationPercentile = 90.0;
+const double kActivateEstimationPercentile = 90.0;
+const double kDrawEstimationPercentile = 90.0;
+
+const int kUmaDurationMinMicros = 1;
+const int64 kUmaDurationMaxMicros = 1 * base::Time::kMicrosecondsPerSecond;
+const size_t kUmaDurationBucketCount = 100;
+
+// Deprecated because they combine Browser and Renderer stats and have low
+// precision.
+// TODO(brianderson): Remove.
+void DeprecatedDrawDurationUMA(base::TimeDelta duration,
+ base::TimeDelta estimate) {
+ base::TimeDelta duration_overestimate;
+ base::TimeDelta duration_underestimate;
+ if (duration > estimate)
+ duration_underestimate = duration - estimate;
+ else
+ duration_overestimate = estimate - duration;
+ UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.DrawDuration", duration,
+ base::TimeDelta::FromMilliseconds(1),
+ base::TimeDelta::FromMilliseconds(100), 50);
+ UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.DrawDurationUnderestimate",
+ duration_underestimate,
+ base::TimeDelta::FromMilliseconds(1),
+ base::TimeDelta::FromMilliseconds(100), 50);
+ UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.DrawDurationOverestimate",
+ duration_overestimate,
+ base::TimeDelta::FromMilliseconds(1),
+ base::TimeDelta::FromMilliseconds(100), 50);
+}
-namespace cc {
+#define UMA_HISTOGRAM_CUSTOM_TIMES_MICROS(name, sample) \
+ UMA_HISTOGRAM_CUSTOM_COUNTS(name, sample.InMicroseconds(), \
+ kUmaDurationMinMicros, kUmaDurationMaxMicros, \
+ kUmaDurationBucketCount);
+
+#define REPORT_COMPOSITOR_TIMING_HISTORY_UMA(category, subcategory) \
+ do { \
+ base::TimeDelta duration_overestimate; \
+ base::TimeDelta duration_underestimate; \
+ if (duration > estimate) \
+ duration_underestimate = duration - estimate; \
+ else \
+ duration_overestimate = estimate - duration; \
+ UMA_HISTOGRAM_CUSTOM_TIMES_MICROS( \
+ "Scheduling." category "." subcategory "Duration", duration); \
+ UMA_HISTOGRAM_CUSTOM_TIMES_MICROS("Scheduling." category "." subcategory \
+ "Duration.Underestimate", \
+ duration_underestimate); \
+ UMA_HISTOGRAM_CUSTOM_TIMES_MICROS("Scheduling." category "." subcategory \
+ "Duration.Overestimate", \
+ duration_overestimate); \
+ if (!affects_estimate) { \
+ UMA_HISTOGRAM_CUSTOM_TIMES_MICROS("Scheduling." category "." subcategory \
+ "Duration.NotUsedForEstimate", \
+ duration); \
+ } \
+ } while (false)
+
+class RendererUMAReporter : public CompositorTimingHistory::UMAReporter {
+ public:
+ ~RendererUMAReporter() override {}
+
+ void AddBeginMainFrameToCommitDuration(base::TimeDelta duration,
+ base::TimeDelta estimate,
+ bool affects_estimate) override {
+ REPORT_COMPOSITOR_TIMING_HISTORY_UMA("Renderer", "BeginMainFrameToCommit");
+ }
+
+ void AddCommitToReadyToActivateDuration(base::TimeDelta duration,
+ base::TimeDelta estimate,
+ bool affects_estimate) override {
+ REPORT_COMPOSITOR_TIMING_HISTORY_UMA("Renderer", "CommitToReadyToActivate");
+ }
+
+ void AddPrepareTilesDuration(base::TimeDelta duration,
+ base::TimeDelta estimate,
+ bool affects_estimate) override {
+ REPORT_COMPOSITOR_TIMING_HISTORY_UMA("Renderer", "PrepareTiles");
+ }
+
+ void AddActivateDuration(base::TimeDelta duration,
+ base::TimeDelta estimate,
+ bool affects_estimate) override {
+ REPORT_COMPOSITOR_TIMING_HISTORY_UMA("Renderer", "Activate");
+ }
+
+ void AddDrawDuration(base::TimeDelta duration,
+ base::TimeDelta estimate,
+ bool affects_estimate) override {
+ REPORT_COMPOSITOR_TIMING_HISTORY_UMA("Renderer", "Draw");
+ DeprecatedDrawDurationUMA(duration, estimate);
+ }
+};
+
+class BrowserUMAReporter : public CompositorTimingHistory::UMAReporter {
+ public:
+ ~BrowserUMAReporter() override {}
+
+ void AddBeginMainFrameToCommitDuration(base::TimeDelta duration,
+ base::TimeDelta estimate,
+ bool affects_estimate) override {
+ REPORT_COMPOSITOR_TIMING_HISTORY_UMA("Browser", "BeginMainFrameToCommit");
+ }
+
+ void AddCommitToReadyToActivateDuration(base::TimeDelta duration,
+ base::TimeDelta estimate,
+ bool affects_estimate) override {
+ REPORT_COMPOSITOR_TIMING_HISTORY_UMA("Browser", "CommitToReadyToActivate");
+ }
+
+ void AddPrepareTilesDuration(base::TimeDelta duration,
+ base::TimeDelta estimate,
+ bool affects_estimate) override {
+ REPORT_COMPOSITOR_TIMING_HISTORY_UMA("Browser", "PrepareTiles");
+ }
+
+ void AddActivateDuration(base::TimeDelta duration,
+ base::TimeDelta estimate,
+ bool affects_estimate) override {
+ REPORT_COMPOSITOR_TIMING_HISTORY_UMA("Browser", "Activate");
+ }
+
+ void AddDrawDuration(base::TimeDelta duration,
+ base::TimeDelta estimate,
+ bool affects_estimate) override {
+ REPORT_COMPOSITOR_TIMING_HISTORY_UMA("Browser", "Draw");
+ DeprecatedDrawDurationUMA(duration, estimate);
+ }
+};
+
+class NullUMAReporter : public CompositorTimingHistory::UMAReporter {
+ public:
+ ~NullUMAReporter() override {}
+ void AddPrepareTilesDuration(base::TimeDelta duration,
+ base::TimeDelta estimate,
+ bool affects_estimate) override {}
+ void AddBeginMainFrameToCommitDuration(base::TimeDelta duration,
+ base::TimeDelta estimate,
+ bool affects_estimate) override {}
+ void AddCommitToReadyToActivateDuration(base::TimeDelta duration,
+ base::TimeDelta estimate,
+ bool affects_estimate) override {}
+ void AddActivateDuration(base::TimeDelta duration,
+ base::TimeDelta estimate,
+ bool affects_estimate) override {}
+ void AddDrawDuration(base::TimeDelta duration,
+ base::TimeDelta estimate,
+ bool affects_estimate) override {}
+};
+
+} // namespace
CompositorTimingHistory::CompositorTimingHistory(
+ UMACategory uma_category,
RenderingStatsInstrumentation* rendering_stats_instrumentation)
: enabled_(false),
begin_main_frame_to_commit_duration_history_(kDurationHistorySize),
@@ -30,23 +203,40 @@ CompositorTimingHistory::CompositorTimingHistory(
prepare_tiles_duration_history_(kDurationHistorySize),
activate_duration_history_(kDurationHistorySize),
draw_duration_history_(kDurationHistorySize),
- rendering_stats_instrumentation_(rendering_stats_instrumentation) {
-}
+ uma_reporter_(CreateUMAReporter(uma_category)),
+ rendering_stats_instrumentation_(rendering_stats_instrumentation) {}
CompositorTimingHistory::~CompositorTimingHistory() {
}
+scoped_ptr<CompositorTimingHistory::UMAReporter>
+CompositorTimingHistory::CreateUMAReporter(UMACategory category) {
+ switch (category) {
+ case RENDERER_UMA:
+ return make_scoped_ptr(new RendererUMAReporter);
+ break;
+ case BROWSER_UMA:
+ return make_scoped_ptr(new BrowserUMAReporter);
+ break;
+ case NULL_UMA:
+ return make_scoped_ptr(new NullUMAReporter);
+ break;
+ }
+ NOTREACHED();
+ return make_scoped_ptr<CompositorTimingHistory::UMAReporter>(nullptr);
+}
+
void CompositorTimingHistory::AsValueInto(
base::trace_event::TracedValue* state) const {
- state->SetDouble("begin_main_frame_to_commit_duration_estimate_ms",
+ state->SetDouble("begin_main_frame_to_commit_estimate_ms",
BeginMainFrameToCommitDurationEstimate().InMillisecondsF());
- state->SetDouble("commit_to_ready_to_activate_duration_estimate_ms",
+ state->SetDouble("commit_to_ready_to_activate_estimate_ms",
CommitToReadyToActivateDurationEstimate().InMillisecondsF());
- state->SetDouble("prepare_tiles_duration_estimate_ms",
+ state->SetDouble("prepare_tiles_estimate_ms",
PrepareTilesDurationEstimate().InMillisecondsF());
- state->SetDouble("activate_duration_estimate_ms",
+ state->SetDouble("activate_estimate_ms",
ActivateDurationEstimate().InMillisecondsF());
- state->SetDouble("draw_duration_estimate_ms",
+ state->SetDouble("draw_estimate_ms",
DrawDurationEstimate().InMillisecondsF());
}
@@ -103,9 +293,13 @@ void CompositorTimingHistory::DidCommit() {
// Before adding the new data point to the timing history, see what we would
// have predicted for this frame. This allows us to keep track of the accuracy
// of our predictions.
+ base::TimeDelta begin_main_frame_to_commit_estimate =
+ BeginMainFrameToCommitDurationEstimate();
+ uma_reporter_->AddBeginMainFrameToCommitDuration(
+ begin_main_frame_to_commit_duration, begin_main_frame_to_commit_estimate,
+ enabled_);
rendering_stats_instrumentation_->AddBeginMainFrameToCommitDuration(
- begin_main_frame_to_commit_duration,
- BeginMainFrameToCommitDurationEstimate());
+ begin_main_frame_to_commit_duration, begin_main_frame_to_commit_estimate);
if (enabled_) {
begin_main_frame_to_commit_duration_history_.InsertSample(
@@ -123,10 +317,11 @@ void CompositorTimingHistory::WillPrepareTiles() {
void CompositorTimingHistory::DidPrepareTiles() {
DCHECK_NE(base::TimeTicks(), start_prepare_tiles_time_);
- if (enabled_) {
- base::TimeDelta prepare_tiles_duration = Now() - start_prepare_tiles_time_;
+ base::TimeDelta prepare_tiles_duration = Now() - start_prepare_tiles_time_;
+ uma_reporter_->AddPrepareTilesDuration(
+ prepare_tiles_duration, PrepareTilesDurationEstimate(), enabled_);
+ if (enabled_)
prepare_tiles_duration_history_.InsertSample(prepare_tiles_duration);
- }
start_prepare_tiles_time_ = base::TimeTicks();
}
@@ -142,8 +337,13 @@ void CompositorTimingHistory::ReadyToActivate() {
// Before adding the new data point to the timing history, see what we would
// have predicted for this frame. This allows us to keep track of the accuracy
// of our predictions.
+
+ base::TimeDelta commit_to_ready_to_activate_estimate =
+ CommitToReadyToActivateDurationEstimate();
+ uma_reporter_->AddCommitToReadyToActivateDuration(
+ time_since_commit, commit_to_ready_to_activate_estimate, enabled_);
rendering_stats_instrumentation_->AddCommitToActivateDuration(
- time_since_commit, CommitToReadyToActivateDurationEstimate());
+ time_since_commit, commit_to_ready_to_activate_estimate);
if (enabled_) {
commit_to_ready_to_activate_duration_history_.InsertSample(
@@ -160,10 +360,13 @@ void CompositorTimingHistory::WillActivate() {
void CompositorTimingHistory::DidActivate() {
DCHECK_NE(base::TimeTicks(), start_activate_time_);
- if (enabled_) {
- base::TimeDelta activate_duration = Now() - start_activate_time_;
+ base::TimeDelta activate_duration = Now() - start_activate_time_;
+
+ uma_reporter_->AddActivateDuration(activate_duration,
+ ActivateDurationEstimate(), enabled_);
+ if (enabled_)
activate_duration_history_.InsertSample(activate_duration);
- }
+
start_activate_time_ = base::TimeTicks();
}
@@ -179,11 +382,11 @@ void CompositorTimingHistory::DidDraw() {
// Before adding the new data point to the timing history, see what we would
// have predicted for this frame. This allows us to keep track of the accuracy
// of our predictions.
- base::TimeDelta draw_duration_estimate = DrawDurationEstimate();
+ base::TimeDelta draw_estimate = DrawDurationEstimate();
rendering_stats_instrumentation_->AddDrawDuration(draw_duration,
- draw_duration_estimate);
+ draw_estimate);
- AddDrawDurationUMA(draw_duration, draw_duration_estimate);
+ uma_reporter_->AddDrawDuration(draw_duration, draw_estimate, enabled_);
if (enabled_) {
draw_duration_history_.InsertSample(draw_duration);
@@ -192,26 +395,4 @@ void CompositorTimingHistory::DidDraw() {
start_draw_time_ = base::TimeTicks();
}
-void CompositorTimingHistory::AddDrawDurationUMA(
- base::TimeDelta draw_duration,
- base::TimeDelta draw_duration_estimate) {
- base::TimeDelta draw_duration_overestimate;
- base::TimeDelta draw_duration_underestimate;
- if (draw_duration > draw_duration_estimate)
- draw_duration_underestimate = draw_duration - draw_duration_estimate;
- else
- draw_duration_overestimate = draw_duration_estimate - draw_duration;
- UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.DrawDuration", draw_duration,
- base::TimeDelta::FromMilliseconds(1),
- base::TimeDelta::FromMilliseconds(100), 50);
- UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.DrawDurationUnderestimate",
- draw_duration_underestimate,
- base::TimeDelta::FromMilliseconds(1),
- base::TimeDelta::FromMilliseconds(100), 50);
- UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.DrawDurationOverestimate",
- draw_duration_overestimate,
- base::TimeDelta::FromMilliseconds(1),
- base::TimeDelta::FromMilliseconds(100), 50);
-}
-
} // namespace cc
diff --git a/chromium/cc/scheduler/compositor_timing_history.h b/chromium/cc/scheduler/compositor_timing_history.h
index d64c38f1cbe..e580c5e3d5b 100644
--- a/chromium/cc/scheduler/compositor_timing_history.h
+++ b/chromium/cc/scheduler/compositor_timing_history.h
@@ -5,6 +5,7 @@
#ifndef CC_SCHEDULER_COMPOSITOR_TIMING_HISTORY_H_
#define CC_SCHEDULER_COMPOSITOR_TIMING_HISTORY_H_
+#include "base/memory/scoped_ptr.h"
#include "cc/base/rolling_time_delta_history.h"
namespace base {
@@ -19,7 +20,15 @@ class RenderingStatsInstrumentation;
class CC_EXPORT CompositorTimingHistory {
public:
- explicit CompositorTimingHistory(
+ enum UMACategory {
+ RENDERER_UMA,
+ BROWSER_UMA,
+ NULL_UMA,
+ };
+ class UMAReporter;
+
+ CompositorTimingHistory(
+ UMACategory uma_category,
RenderingStatsInstrumentation* rendering_stats_instrumentation);
virtual ~CompositorTimingHistory();
@@ -45,11 +54,9 @@ class CC_EXPORT CompositorTimingHistory {
void DidDraw();
protected:
+ static scoped_ptr<UMAReporter> CreateUMAReporter(UMACategory category);
virtual base::TimeTicks Now() const;
- void AddDrawDurationUMA(base::TimeDelta draw_duration,
- base::TimeDelta draw_duration_estimate);
-
bool enabled_;
RollingTimeDeltaHistory begin_main_frame_to_commit_duration_history_;
@@ -64,6 +71,7 @@ class CC_EXPORT CompositorTimingHistory {
base::TimeTicks start_activate_time_;
base::TimeTicks start_draw_time_;
+ scoped_ptr<UMAReporter> uma_reporter_;
RenderingStatsInstrumentation* rendering_stats_instrumentation_;
private:
diff --git a/chromium/cc/scheduler/compositor_timing_history_unittest.cc b/chromium/cc/scheduler/compositor_timing_history_unittest.cc
index 6045e3a960a..5ffd68e95d2 100644
--- a/chromium/cc/scheduler/compositor_timing_history_unittest.cc
+++ b/chromium/cc/scheduler/compositor_timing_history_unittest.cc
@@ -16,7 +16,7 @@ class TestCompositorTimingHistory : public CompositorTimingHistory {
public:
TestCompositorTimingHistory(CompositorTimingHistoryTest* test,
RenderingStatsInstrumentation* rendering_stats)
- : CompositorTimingHistory(rendering_stats), test_(test) {}
+ : CompositorTimingHistory(NULL_UMA, rendering_stats), test_(test) {}
protected:
base::TimeTicks Now() const override;
diff --git a/chromium/cc/scheduler/scheduler.cc b/chromium/cc/scheduler/scheduler.cc
index 2b668e83011..082fbee328e 100644
--- a/chromium/cc/scheduler/scheduler.cc
+++ b/chromium/cc/scheduler/scheduler.cc
@@ -19,6 +19,13 @@
namespace cc {
+namespace {
+// This is a fudge factor we subtract from the deadline to account
+// for message latency and kernel scheduling variability.
+const base::TimeDelta kDeadlineFudgeFactor =
+ base::TimeDelta::FromMicroseconds(1000);
+}
+
scoped_ptr<Scheduler> Scheduler::Create(
SchedulerClient* client,
const SchedulerSettings& settings,
@@ -162,8 +169,8 @@ void Scheduler::SetThrottleFrameProduction(bool throttle) {
ProcessScheduledActions();
}
-void Scheduler::SetNeedsCommit() {
- state_machine_.SetNeedsCommit();
+void Scheduler::SetNeedsBeginMainFrame() {
+ state_machine_.SetNeedsBeginMainFrame();
ProcessScheduledActions();
}
@@ -183,11 +190,6 @@ void Scheduler::SetNeedsPrepareTiles() {
ProcessScheduledActions();
}
-void Scheduler::SetWaitForReadyToDraw() {
- state_machine_.SetWaitForReadyToDraw();
- ProcessScheduledActions();
-}
-
void Scheduler::SetMaxSwapsPending(int max) {
state_machine_.SetMaxSwapsPending(max);
}
@@ -450,15 +452,16 @@ void Scheduler::PostBeginRetroFrameIfNeeded() {
void Scheduler::BeginImplFrameWithDeadline(const BeginFrameArgs& args) {
bool main_thread_is_in_high_latency_mode =
- state_machine_.MainThreadIsInHighLatencyMode();
+ state_machine_.main_thread_missed_last_deadline();
TRACE_EVENT2("cc,benchmark", "Scheduler::BeginImplFrame", "args",
- args.AsValue(), "main_thread_is_high_latency",
+ args.AsValue(), "main_thread_missed_last_deadline",
main_thread_is_in_high_latency_mode);
TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"),
"MainThreadLatency", main_thread_is_in_high_latency_mode);
BeginFrameArgs adjusted_args = args;
adjusted_args.deadline -= compositor_timing_history_->DrawDurationEstimate();
+ adjusted_args.deadline -= kDeadlineFudgeFactor;
if (ShouldRecoverMainLatency(adjusted_args)) {
TRACE_EVENT_INSTANT0("cc", "SkipBeginMainFrameToReduceLatency",
@@ -632,17 +635,18 @@ void Scheduler::ProcessScheduledActions() {
"SchedulerStateMachine",
"state",
AsValue());
- state_machine_.UpdateState(action);
base::AutoReset<SchedulerStateMachine::Action>
mark_inside_action(&inside_action_, action);
switch (action) {
case SchedulerStateMachine::ACTION_NONE:
break;
case SchedulerStateMachine::ACTION_ANIMATE:
+ state_machine_.WillAnimate();
client_->ScheduledActionAnimate();
break;
case SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME:
compositor_timing_history_->WillBeginMainFrame();
+ state_machine_.WillSendBeginMainFrame();
client_->ScheduledActionSendBeginMainFrame();
break;
case SchedulerStateMachine::ACTION_COMMIT: {
@@ -651,11 +655,14 @@ void Scheduler::ProcessScheduledActions() {
tracked_objects::ScopedTracker tracking_profile4(
FROM_HERE_WITH_EXPLICIT_FUNCTION(
"461509 Scheduler::ProcessScheduledActions4"));
+ bool commit_has_no_updates = false;
+ state_machine_.WillCommit(commit_has_no_updates);
client_->ScheduledActionCommit();
break;
}
case SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE:
compositor_timing_history_->WillActivate();
+ state_machine_.WillActivate();
client_->ScheduledActionActivateSyncTree();
compositor_timing_history_->DidActivate();
break;
@@ -665,23 +672,34 @@ void Scheduler::ProcessScheduledActions() {
tracked_objects::ScopedTracker tracking_profile6(
FROM_HERE_WITH_EXPLICIT_FUNCTION(
"461509 Scheduler::ProcessScheduledActions6"));
+ bool did_request_swap = true;
+ state_machine_.WillDraw(did_request_swap);
DrawAndSwapIfPossible();
break;
}
- case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_FORCED:
+ case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_FORCED: {
+ bool did_request_swap = true;
+ state_machine_.WillDraw(did_request_swap);
DrawAndSwapForced();
break;
- case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT:
+ }
+ case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT: {
// No action is actually performed, but this allows the state machine to
// advance out of its waiting to draw state without actually drawing.
+ bool did_request_swap = false;
+ state_machine_.WillDraw(did_request_swap);
break;
+ }
case SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION:
+ state_machine_.WillBeginOutputSurfaceCreation();
client_->ScheduledActionBeginOutputSurfaceCreation();
break;
case SchedulerStateMachine::ACTION_PREPARE_TILES:
+ state_machine_.WillPrepareTiles();
client_->ScheduledActionPrepareTiles();
break;
case SchedulerStateMachine::ACTION_INVALIDATE_OUTPUT_SURFACE: {
+ state_machine_.WillInvalidateOutputSurface();
client_->ScheduledActionInvalidateOutputSurface();
break;
}
@@ -754,7 +772,7 @@ void Scheduler::UpdateCompositorTimingHistoryRecordingEnabled() {
bool Scheduler::ShouldRecoverMainLatency(const BeginFrameArgs& args) const {
DCHECK(!settings_.using_synchronous_renderer_compositor);
- if (!state_machine_.MainThreadIsInHighLatencyMode())
+ if (!state_machine_.main_thread_missed_last_deadline())
return false;
// When prioritizing impl thread latency, we currently put the
@@ -768,6 +786,12 @@ bool Scheduler::ShouldRecoverMainLatency(const BeginFrameArgs& args) const {
bool Scheduler::ShouldRecoverImplLatency(const BeginFrameArgs& args) const {
DCHECK(!settings_.using_synchronous_renderer_compositor);
+ // Disable impl thread latency recovery when using the unthrottled
+ // begin frame source since we will always get a BeginFrame before
+ // the swap ack and our heuristics below will not work.
+ if (!throttle_frame_production_)
+ return false;
+
// If we are swap throttled at the BeginFrame, that means the impl thread is
// very likely in a high latency mode.
bool impl_thread_is_likely_high_latency = state_machine_.SwapThrottled();
@@ -808,10 +832,10 @@ bool Scheduler::CanCommitAndActivateBeforeDeadline(
}
bool Scheduler::IsBeginMainFrameSentOrStarted() const {
- return (state_machine_.commit_state() ==
- SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT ||
- state_machine_.commit_state() ==
- SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED);
+ return (state_machine_.begin_main_frame_state() ==
+ SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_SENT ||
+ state_machine_.begin_main_frame_state() ==
+ SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_STARTED);
}
} // namespace cc
diff --git a/chromium/cc/scheduler/scheduler.h b/chromium/cc/scheduler/scheduler.h
index d6fc074c541..8e9abce8971 100644
--- a/chromium/cc/scheduler/scheduler.h
+++ b/chromium/cc/scheduler/scheduler.h
@@ -83,7 +83,7 @@ class CC_EXPORT Scheduler : public BeginFrameObserverBase {
void NotifyReadyToDraw();
void SetThrottleFrameProduction(bool throttle);
- void SetNeedsCommit();
+ void SetNeedsBeginMainFrame();
void SetNeedsRedraw();
@@ -91,8 +91,6 @@ class CC_EXPORT Scheduler : public BeginFrameObserverBase {
void SetNeedsPrepareTiles();
- void SetWaitForReadyToDraw();
-
void SetMaxSwapsPending(int max);
void DidSwapBuffers();
void DidSwapBuffersComplete();
@@ -136,10 +134,6 @@ class CC_EXPORT Scheduler : public BeginFrameObserverBase {
scoped_refptr<base::trace_event::ConvertableToTraceFormat> AsValue() const;
void AsValueInto(base::trace_event::TracedValue* value) const override;
- void SetContinuousPainting(bool continuous_painting) {
- state_machine_.SetContinuousPainting(continuous_painting);
- }
-
void SetChildrenNeedBeginFrames(bool children_need_begin_frames);
void SetVideoNeedsBeginFrames(bool video_needs_begin_frames);
diff --git a/chromium/cc/scheduler/scheduler_state_machine.cc b/chromium/cc/scheduler/scheduler_state_machine.cc
index d83599c8c71..8c617561858 100644
--- a/chromium/cc/scheduler/scheduler_state_machine.cc
+++ b/chromium/cc/scheduler/scheduler_state_machine.cc
@@ -17,7 +17,7 @@ SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings)
: settings_(settings),
output_surface_state_(OUTPUT_SURFACE_LOST),
begin_impl_frame_state_(BEGIN_IMPL_FRAME_STATE_IDLE),
- commit_state_(COMMIT_STATE_IDLE),
+ begin_main_frame_state_(BEGIN_MAIN_FRAME_STATE_IDLE),
forced_redraw_state_(FORCED_REDRAW_STATE_IDLE),
commit_count_(0),
current_frame_number_(0),
@@ -38,7 +38,7 @@ SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings)
needs_redraw_(false),
needs_animate_(false),
needs_prepare_tiles_(false),
- needs_commit_(false),
+ needs_begin_main_frame_(false),
visible_(false),
can_start_(false),
can_draw_(false),
@@ -47,16 +47,15 @@ SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings)
active_tree_needs_first_draw_(false),
did_create_and_initialize_first_output_surface_(false),
impl_latency_takes_priority_(false),
+ main_thread_missed_last_deadline_(false),
skip_next_begin_main_frame_to_reduce_latency_(false),
- continuous_painting_(false),
children_need_begin_frames_(false),
defer_commits_(false),
video_needs_begin_frames_(false),
last_commit_had_no_updates_(false),
- wait_for_active_tree_ready_to_draw_(false),
+ wait_for_ready_to_draw_(false),
did_request_swap_in_last_frame_(false),
- did_perform_swap_in_last_draw_(false) {
-}
+ did_perform_swap_in_last_draw_(false) {}
const char* SchedulerStateMachine::OutputSurfaceStateToString(
OutputSurfaceState state) {
@@ -110,20 +109,21 @@ const char* SchedulerStateMachine::BeginImplFrameDeadlineModeToString(
return "???";
}
-const char* SchedulerStateMachine::CommitStateToString(CommitState state) {
+const char* SchedulerStateMachine::BeginMainFrameStateToString(
+ BeginMainFrameState state) {
switch (state) {
- case COMMIT_STATE_IDLE:
- return "COMMIT_STATE_IDLE";
- case COMMIT_STATE_BEGIN_MAIN_FRAME_SENT:
- return "COMMIT_STATE_BEGIN_MAIN_FRAME_SENT";
- case COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED:
- return "COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED";
- case COMMIT_STATE_READY_TO_COMMIT:
- return "COMMIT_STATE_READY_TO_COMMIT";
- case COMMIT_STATE_WAITING_FOR_ACTIVATION:
- return "COMMIT_STATE_WAITING_FOR_ACTIVATION";
- case COMMIT_STATE_WAITING_FOR_DRAW:
- return "COMMIT_STATE_WAITING_FOR_DRAW";
+ case BEGIN_MAIN_FRAME_STATE_IDLE:
+ return "BEGIN_MAIN_FRAME_STATE_IDLE";
+ case BEGIN_MAIN_FRAME_STATE_SENT:
+ return "BEGIN_MAIN_FRAME_STATE_SENT";
+ case BEGIN_MAIN_FRAME_STATE_STARTED:
+ return "BEGIN_MAIN_FRAME_STATE_STARTED";
+ case BEGIN_MAIN_FRAME_STATE_READY_TO_COMMIT:
+ return "BEGIN_MAIN_FRAME_STATE_READY_TO_COMMIT";
+ case BEGIN_MAIN_FRAME_STATE_WAITING_FOR_ACTIVATION:
+ return "BEGIN_MAIN_FRAME_STATE_WAITING_FOR_ACTIVATION";
+ case BEGIN_MAIN_FRAME_STATE_WAITING_FOR_DRAW:
+ return "BEGIN_MAIN_FRAME_STATE_WAITING_FOR_DRAW";
}
NOTREACHED();
return "???";
@@ -188,7 +188,8 @@ void SchedulerStateMachine::AsValueInto(
state->SetString("next_action", ActionToString(NextAction()));
state->SetString("begin_impl_frame_state",
BeginImplFrameStateToString(begin_impl_frame_state_));
- state->SetString("commit_state", CommitStateToString(commit_state_));
+ state->SetString("begin_main_frame_state",
+ BeginMainFrameStateToString(begin_main_frame_state_));
state->SetString("output_surface_state_",
OutputSurfaceStateToString(output_surface_state_));
state->SetString("forced_redraw_state",
@@ -222,7 +223,7 @@ void SchedulerStateMachine::AsValueInto(
state->SetBoolean("needs_redraw", needs_redraw_);
state->SetBoolean("needs_animate_", needs_animate_);
state->SetBoolean("needs_prepare_tiles", needs_prepare_tiles_);
- state->SetBoolean("needs_commit", needs_commit_);
+ state->SetBoolean("needs_begin_main_frame", needs_begin_main_frame_);
state->SetBoolean("visible", visible_);
state->SetBoolean("can_start", can_start_);
state->SetBoolean("can_draw", can_draw_);
@@ -231,17 +232,15 @@ void SchedulerStateMachine::AsValueInto(
pending_tree_is_ready_for_activation_);
state->SetBoolean("active_tree_needs_first_draw",
active_tree_needs_first_draw_);
- state->SetBoolean("wait_for_active_tree_ready_to_draw",
- wait_for_active_tree_ready_to_draw_);
+ state->SetBoolean("wait_for_ready_to_draw", wait_for_ready_to_draw_);
state->SetBoolean("did_create_and_initialize_first_output_surface",
did_create_and_initialize_first_output_surface_);
state->SetBoolean("impl_latency_takes_priority",
impl_latency_takes_priority_);
- state->SetBoolean("main_thread_is_in_high_latency_mode",
- MainThreadIsInHighLatencyMode());
+ state->SetBoolean("main_thread_missed_last_deadline",
+ main_thread_missed_last_deadline_);
state->SetBoolean("skip_next_begin_main_frame_to_reduce_latency",
skip_next_begin_main_frame_to_reduce_latency_);
- state->SetBoolean("continuous_painting", continuous_painting_);
state->SetBoolean("children_need_begin_frames", children_need_begin_frames_);
state->SetBoolean("video_needs_begin_frames", video_needs_begin_frames_);
state->SetBoolean("defer_commits", defer_commits_);
@@ -254,19 +253,21 @@ void SchedulerStateMachine::AsValueInto(
}
bool SchedulerStateMachine::PendingDrawsShouldBeAborted() const {
+ // Normally when |visible_| is false, pending activations will be forced and
+ // draws will be aborted. However, when the embedder is Android WebView,
+ // software draws could be scheduled by the Android OS at any time and draws
+ // should not be aborted in this case.
+ bool is_output_surface_lost = (output_surface_state_ == OUTPUT_SURFACE_LOST);
+ if (settings_.using_synchronous_renderer_compositor)
+ return is_output_surface_lost || !can_draw_;
+
// These are all the cases where we normally cannot or do not want to draw
// but, if needs_redraw_ is true and we do not draw to make forward progress,
// we might deadlock with the main thread.
// This should be a superset of PendingActivationsShouldBeForced() since
// activation of the pending tree is blocked by drawing of the active tree and
// the main thread might be blocked on activation of the most recent commit.
- if (PendingActivationsShouldBeForced())
- return true;
-
- // Additional states where we should abort draws.
- if (!can_draw_)
- return true;
- return false;
+ return is_output_surface_lost || !can_draw_ || !visible_;
}
bool SchedulerStateMachine::PendingActivationsShouldBeForced() const {
@@ -290,13 +291,16 @@ bool SchedulerStateMachine::PendingActivationsShouldBeForced() const {
}
bool SchedulerStateMachine::ShouldBeginOutputSurfaceCreation() const {
+ if (!visible_)
+ return false;
+
// Don't try to initialize too early.
if (!can_start_)
return false;
// We only want to start output surface initialization after the
// previous commit is complete.
- if (commit_state_ != COMMIT_STATE_IDLE)
+ if (begin_main_frame_state_ != BEGIN_MAIN_FRAME_STATE_IDLE)
return false;
// Make sure the BeginImplFrame from any previous OutputSurfaces
@@ -387,7 +391,7 @@ bool SchedulerStateMachine::ShouldAnimate() const {
}
bool SchedulerStateMachine::CouldSendBeginMainFrame() const {
- if (!needs_commit_)
+ if (!needs_begin_main_frame_)
return false;
// We can not perform commits if we are not visible.
@@ -426,7 +430,7 @@ bool SchedulerStateMachine::ShouldSendBeginMainFrame() const {
// Other parts of the state machine indirectly defer the BeginMainFrame
// by transitioning to WAITING commit states rather than going
// immediately to IDLE.
- if (commit_state_ != COMMIT_STATE_IDLE)
+ if (begin_main_frame_state_ != BEGIN_MAIN_FRAME_STATE_IDLE)
return false;
// Don't send BeginMainFrame early if we are prioritizing the active tree
@@ -482,7 +486,7 @@ bool SchedulerStateMachine::ShouldSendBeginMainFrame() const {
}
bool SchedulerStateMachine::ShouldCommit() const {
- if (commit_state_ != COMMIT_STATE_READY_TO_COMMIT)
+ if (begin_main_frame_state_ != BEGIN_MAIN_FRAME_STATE_READY_TO_COMMIT)
return false;
// We must not finish the commit until the pending tree is free.
@@ -559,57 +563,7 @@ SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const {
return ACTION_NONE;
}
-void SchedulerStateMachine::UpdateState(Action action) {
- switch (action) {
- case ACTION_NONE:
- return;
-
- case ACTION_ACTIVATE_SYNC_TREE:
- UpdateStateOnActivation();
- return;
-
- case ACTION_ANIMATE:
- UpdateStateOnAnimate();
- return;
-
- case ACTION_SEND_BEGIN_MAIN_FRAME:
- UpdateStateOnSendBeginMainFrame();
- return;
-
- case ACTION_COMMIT: {
- bool commit_has_no_updates = false;
- UpdateStateOnCommit(commit_has_no_updates);
- return;
- }
-
- case ACTION_DRAW_AND_SWAP_FORCED:
- case ACTION_DRAW_AND_SWAP_IF_POSSIBLE: {
- bool did_request_swap = true;
- UpdateStateOnDraw(did_request_swap);
- return;
- }
-
- case ACTION_DRAW_AND_SWAP_ABORT: {
- bool did_request_swap = false;
- UpdateStateOnDraw(did_request_swap);
- return;
- }
-
- case ACTION_BEGIN_OUTPUT_SURFACE_CREATION:
- UpdateStateOnBeginOutputSurfaceCreation();
- return;
-
- case ACTION_PREPARE_TILES:
- UpdateStateOnPrepareTiles();
- return;
-
- case ACTION_INVALIDATE_OUTPUT_SURFACE:
- UpdateStateOnInvalidateOutputSurface();
- return;
- }
-}
-
-void SchedulerStateMachine::UpdateStateOnAnimate() {
+void SchedulerStateMachine::WillAnimate() {
DCHECK(!animate_funnel_);
last_frame_number_animate_performed_ = current_frame_number_;
animate_funnel_ = true;
@@ -618,17 +572,17 @@ void SchedulerStateMachine::UpdateStateOnAnimate() {
SetNeedsRedraw();
}
-void SchedulerStateMachine::UpdateStateOnSendBeginMainFrame() {
+void SchedulerStateMachine::WillSendBeginMainFrame() {
DCHECK(!has_pending_tree_ || settings_.main_frame_before_activation_enabled);
DCHECK(visible_);
DCHECK(!send_begin_main_frame_funnel_);
- commit_state_ = COMMIT_STATE_BEGIN_MAIN_FRAME_SENT;
- needs_commit_ = false;
+ begin_main_frame_state_ = BEGIN_MAIN_FRAME_STATE_SENT;
+ needs_begin_main_frame_ = false;
send_begin_main_frame_funnel_ = true;
last_frame_number_begin_main_frame_sent_ = current_frame_number_;
}
-void SchedulerStateMachine::UpdateStateOnCommit(bool commit_has_no_updates) {
+void SchedulerStateMachine::WillCommit(bool commit_has_no_updates) {
commit_count_++;
// Animate after commit even if we've already animated.
@@ -636,14 +590,17 @@ void SchedulerStateMachine::UpdateStateOnCommit(bool commit_has_no_updates) {
animate_funnel_ = false;
if (commit_has_no_updates || settings_.main_frame_before_activation_enabled) {
- commit_state_ = COMMIT_STATE_IDLE;
+ begin_main_frame_state_ = BEGIN_MAIN_FRAME_STATE_IDLE;
} else {
- commit_state_ = COMMIT_STATE_WAITING_FOR_ACTIVATION;
+ begin_main_frame_state_ = BEGIN_MAIN_FRAME_STATE_WAITING_FOR_ACTIVATION;
}
// If the commit was aborted, then there is no pending tree.
has_pending_tree_ = !commit_has_no_updates;
+ wait_for_ready_to_draw_ =
+ !commit_has_no_updates && settings_.commit_to_active_tree;
+
// Update state related to forced draws.
if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT) {
forced_redraw_state_ = has_pending_tree_
@@ -658,15 +615,14 @@ void SchedulerStateMachine::UpdateStateOnCommit(bool commit_has_no_updates) {
output_surface_state_ = OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION;
} else {
output_surface_state_ = OUTPUT_SURFACE_ACTIVE;
- needs_redraw_ = true;
}
}
- // Update state if we have a new active tree to draw, or if the active tree
- // was unchanged but we need to do a forced draw.
- if (!has_pending_tree_ &&
- (!commit_has_no_updates ||
- forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)) {
+ // Update state if there's no updates heading for the active tree, but we need
+ // to do a forced draw.
+ if (commit_has_no_updates &&
+ forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) {
+ DCHECK(!has_pending_tree_);
needs_redraw_ = true;
active_tree_needs_first_draw_ = true;
}
@@ -674,16 +630,15 @@ void SchedulerStateMachine::UpdateStateOnCommit(bool commit_has_no_updates) {
// This post-commit work is common to both completed and aborted commits.
pending_tree_is_ready_for_activation_ = false;
- if (continuous_painting_)
- needs_commit_ = true;
last_commit_had_no_updates_ = commit_has_no_updates;
}
-void SchedulerStateMachine::UpdateStateOnActivation() {
- if (commit_state_ == COMMIT_STATE_WAITING_FOR_ACTIVATION) {
- commit_state_ = settings_.commit_to_active_tree
- ? COMMIT_STATE_WAITING_FOR_DRAW
- : COMMIT_STATE_IDLE;
+void SchedulerStateMachine::WillActivate() {
+ if (begin_main_frame_state_ ==
+ BEGIN_MAIN_FRAME_STATE_WAITING_FOR_ACTIVATION) {
+ begin_main_frame_state_ = settings_.commit_to_active_tree
+ ? BEGIN_MAIN_FRAME_STATE_WAITING_FOR_DRAW
+ : BEGIN_MAIN_FRAME_STATE_IDLE;
}
if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION)
@@ -698,12 +653,12 @@ void SchedulerStateMachine::UpdateStateOnActivation() {
needs_redraw_ = true;
}
-void SchedulerStateMachine::UpdateStateOnDraw(bool did_request_swap) {
+void SchedulerStateMachine::WillDraw(bool did_request_swap) {
if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)
forced_redraw_state_ = FORCED_REDRAW_STATE_IDLE;
- if (commit_state_ == COMMIT_STATE_WAITING_FOR_DRAW)
- commit_state_ = COMMIT_STATE_IDLE;
+ if (begin_main_frame_state_ == BEGIN_MAIN_FRAME_STATE_WAITING_FOR_DRAW)
+ begin_main_frame_state_ = BEGIN_MAIN_FRAME_STATE_IDLE;
needs_redraw_ = false;
active_tree_needs_first_draw_ = false;
@@ -716,23 +671,23 @@ void SchedulerStateMachine::UpdateStateOnDraw(bool did_request_swap) {
}
}
-void SchedulerStateMachine::UpdateStateOnPrepareTiles() {
+void SchedulerStateMachine::WillPrepareTiles() {
needs_prepare_tiles_ = false;
}
-void SchedulerStateMachine::UpdateStateOnBeginOutputSurfaceCreation() {
+void SchedulerStateMachine::WillBeginOutputSurfaceCreation() {
DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_LOST);
output_surface_state_ = OUTPUT_SURFACE_CREATING;
// The following DCHECKs make sure we are in the proper quiescent state.
// The pipeline should be flushed entirely before we start output
// surface creation to avoid complicated corner cases.
- DCHECK_EQ(commit_state_, COMMIT_STATE_IDLE);
+ DCHECK_EQ(begin_main_frame_state_, BEGIN_MAIN_FRAME_STATE_IDLE);
DCHECK(!has_pending_tree_);
DCHECK(!active_tree_needs_first_draw_);
}
-void SchedulerStateMachine::UpdateStateOnInvalidateOutputSurface() {
+void SchedulerStateMachine::WillInvalidateOutputSurface() {
DCHECK(!invalidate_output_surface_funnel_);
invalidate_output_surface_funnel_ = true;
last_frame_number_invalidate_output_surface_performed_ =
@@ -754,6 +709,7 @@ void SchedulerStateMachine::SetSkipNextBeginMainFrameToReduceLatency() {
bool SchedulerStateMachine::BeginFrameRequiredForChildren() const {
return children_need_begin_frames_;
}
+
bool SchedulerStateMachine::BeginFrameNeededForVideo() const {
return video_needs_begin_frames_;
}
@@ -794,7 +750,8 @@ bool SchedulerStateMachine::BeginFrameRequiredForAction() const {
if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)
return true;
- return needs_animate_ || needs_redraw_ || (needs_commit_ && !defer_commits_);
+ return needs_animate_ || needs_redraw_ ||
+ (needs_begin_main_frame_ && !defer_commits_);
}
// These are cases where we are very likely want a BeginFrame message in the
@@ -813,7 +770,8 @@ bool SchedulerStateMachine::ProactiveBeginFrameWanted() const {
// request frames when commits are disabled, because the frame requests will
// not provide the needed commit (and will wake up the process when it could
// stay idle).
- if ((commit_state_ != COMMIT_STATE_IDLE) && !defer_commits_)
+ if ((begin_main_frame_state_ != BEGIN_MAIN_FRAME_STATE_IDLE) &&
+ !defer_commits_)
return true;
// If the pending tree activates quickly, we'll want a BeginImplFrame soon
@@ -883,6 +841,11 @@ void SchedulerStateMachine::OnBeginImplFrameIdle() {
skip_next_begin_main_frame_to_reduce_latency_ = false;
+ // If a new or undrawn active tree is pending after the deadline,
+ // then the main thread is in a high latency mode.
+ main_thread_missed_last_deadline_ =
+ CommitPending() || has_pending_tree_ || active_tree_needs_first_draw_;
+
// If we're entering a state where we won't get BeginFrames set all the
// funnels so that we don't perform any actions that we shouldn't.
if (!BeginFrameNeeded())
@@ -894,12 +857,12 @@ SchedulerStateMachine::CurrentBeginImplFrameDeadlineMode() const {
if (settings_.using_synchronous_renderer_compositor) {
// No deadline for synchronous compositor.
return BEGIN_IMPL_FRAME_DEADLINE_MODE_NONE;
- } else if (wait_for_active_tree_ready_to_draw_) {
+ } else if (ShouldTriggerBeginImplFrameDeadlineImmediately()) {
+ return BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE;
+ } else if (wait_for_ready_to_draw_) {
// When we are waiting for ready to draw signal, we do not wait to post a
// deadline yet.
return BEGIN_IMPL_FRAME_DEADLINE_MODE_BLOCKED_ON_READY_TO_DRAW;
- } else if (ShouldTriggerBeginImplFrameDeadlineImmediately()) {
- return BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE;
} else if (needs_redraw_ && !SwapThrottled()) {
// We have an animation or fast input path on the impl thread that wants
// to draw, so don't wait too long for a new active tree.
@@ -915,13 +878,15 @@ SchedulerStateMachine::CurrentBeginImplFrameDeadlineMode() const {
bool SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineImmediately()
const {
- if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME)
- return false;
-
// If we just forced activation, we should end the deadline right now.
if (PendingActivationsShouldBeForced() && !has_pending_tree_)
return true;
+ // Do not trigger deadline immediately if we're waiting for READY_TO_DRAW
+ // unless it's one of the forced cases.
+ if (wait_for_ready_to_draw_)
+ return false;
+
// SwapAck throttle the deadline since we wont draw and swap anyway.
if (SwapThrottled())
return false;
@@ -937,7 +902,8 @@ bool SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineImmediately()
// don't have a pending tree -- otherwise we should give it a chance to
// activate.
// TODO(skyostil): Revisit this when we have more accurate deadline estimates.
- if (commit_state_ == COMMIT_STATE_IDLE && !has_pending_tree_)
+ if (begin_main_frame_state_ == BEGIN_MAIN_FRAME_STATE_IDLE &&
+ !has_pending_tree_)
return true;
// Prioritize impl-thread draws in impl_latency_takes_priority_ mode.
@@ -947,45 +913,8 @@ bool SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineImmediately()
return false;
}
-bool SchedulerStateMachine::MainThreadIsInHighLatencyMode() const {
- // If a commit is pending before the previous commit has been drawn, we
- // are definitely in a high latency mode.
- if (CommitPending() && (active_tree_needs_first_draw_ || has_pending_tree_))
- return true;
-
- // If we just sent a BeginMainFrame and haven't hit the deadline yet, the main
- // thread is in a low latency mode.
- if (send_begin_main_frame_funnel_ &&
- (begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING ||
- begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME))
- return false;
-
- // If there's a commit in progress it must either be from the previous frame
- // or it started after the impl thread's deadline. In either case the main
- // thread is in high latency mode.
- if (CommitPending())
- return true;
-
- // Similarly, if there's a pending tree the main thread is in high latency
- // mode, because either
- // it's from the previous frame
- // or
- // we're currently drawing the active tree and the pending tree will thus
- // only be drawn in the next frame.
- if (has_pending_tree_)
- return true;
-
- if (begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) {
- // Even if there's a new active tree to draw at the deadline or we've just
- // swapped it, it may have been triggered by a previous BeginImplFrame, in
- // which case the main thread is in a high latency mode.
- return (active_tree_needs_first_draw_ || did_perform_swap_in_last_draw_) &&
- !send_begin_main_frame_funnel_;
- }
-
- // If the active tree needs its first draw in any other state, we know the
- // main thread is in a high latency mode.
- return active_tree_needs_first_draw_;
+bool SchedulerStateMachine::main_thread_missed_last_deadline() const {
+ return main_thread_missed_last_deadline_;
}
bool SchedulerStateMachine::SwapThrottled() const {
@@ -993,9 +922,17 @@ bool SchedulerStateMachine::SwapThrottled() const {
}
void SchedulerStateMachine::SetVisible(bool visible) {
+ if (visible_ == visible)
+ return;
+
visible_ = visible;
+
+ if (visible)
+ main_thread_missed_last_deadline_ = false;
+
// TODO(sunnyps): Change the funnel to a bool to avoid hacks like this.
prepare_tiles_funnel_ = 0;
+ wait_for_ready_to_draw_ = false;
}
void SchedulerStateMachine::SetCanDraw(bool can_draw) { can_draw_ = can_draw; }
@@ -1006,14 +943,12 @@ void SchedulerStateMachine::SetNeedsAnimate() {
needs_animate_ = true;
}
-void SchedulerStateMachine::SetWaitForReadyToDraw() {
- wait_for_active_tree_ready_to_draw_ = true;
-}
-
bool SchedulerStateMachine::OnlyImplSideUpdatesExpected() const {
bool has_impl_updates = needs_redraw_ || needs_animate_;
bool main_updates_expected =
- needs_commit_ || commit_state_ != COMMIT_STATE_IDLE || has_pending_tree_;
+ needs_begin_main_frame_ ||
+ begin_main_frame_state_ != BEGIN_MAIN_FRAME_STATE_IDLE ||
+ has_pending_tree_;
return has_impl_updates && !main_updates_expected;
}
@@ -1069,7 +1004,7 @@ void SchedulerStateMachine::DidDrawIfPossibleCompleted(DrawResult result) {
if (forced_redraw_state_ != FORCED_REDRAW_STATE_IDLE)
return;
- needs_commit_ = true;
+ needs_begin_main_frame_ = true;
consecutive_checkerboard_animations_++;
if (settings_.timeout_and_draw_when_animation_checkerboards &&
consecutive_checkerboard_animations_ >=
@@ -1085,19 +1020,19 @@ void SchedulerStateMachine::DidDrawIfPossibleCompleted(DrawResult result) {
// pictures (which requires a commit) or because of memory pressure
// removing textures (which might not). To be safe, request a commit
// anyway.
- needs_commit_ = true;
+ needs_begin_main_frame_ = true;
break;
}
}
-void SchedulerStateMachine::SetNeedsCommit() {
- needs_commit_ = true;
+void SchedulerStateMachine::SetNeedsBeginMainFrame() {
+ needs_begin_main_frame_ = true;
}
void SchedulerStateMachine::NotifyReadyToCommit() {
- DCHECK(commit_state_ == COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED)
+ DCHECK(begin_main_frame_state_ == BEGIN_MAIN_FRAME_STATE_STARTED)
<< AsValue()->ToString();
- commit_state_ = COMMIT_STATE_READY_TO_COMMIT;
+ begin_main_frame_state_ = BEGIN_MAIN_FRAME_STATE_READY_TO_COMMIT;
// In commit_to_active_tree mode, commit should happen right after
// BeginFrame, meaning when this function is called, next action should be
// commit.
@@ -1106,17 +1041,17 @@ void SchedulerStateMachine::NotifyReadyToCommit() {
}
void SchedulerStateMachine::BeginMainFrameAborted(CommitEarlyOutReason reason) {
- DCHECK_EQ(commit_state_, COMMIT_STATE_BEGIN_MAIN_FRAME_SENT);
+ DCHECK_EQ(begin_main_frame_state_, BEGIN_MAIN_FRAME_STATE_SENT);
switch (reason) {
case CommitEarlyOutReason::ABORTED_OUTPUT_SURFACE_LOST:
case CommitEarlyOutReason::ABORTED_NOT_VISIBLE:
case CommitEarlyOutReason::ABORTED_DEFERRED_COMMIT:
- commit_state_ = COMMIT_STATE_IDLE;
- SetNeedsCommit();
+ begin_main_frame_state_ = BEGIN_MAIN_FRAME_STATE_IDLE;
+ SetNeedsBeginMainFrame();
return;
case CommitEarlyOutReason::FINISHED_NO_UPDATES:
bool commit_has_no_updates = true;
- UpdateStateOnCommit(commit_has_no_updates);
+ WillCommit(commit_has_no_updates);
return;
}
}
@@ -1133,7 +1068,7 @@ void SchedulerStateMachine::DidLoseOutputSurface() {
return;
output_surface_state_ = OUTPUT_SURFACE_LOST;
needs_redraw_ = false;
- wait_for_active_tree_ready_to_draw_ = false;
+ wait_for_ready_to_draw_ = false;
}
void SchedulerStateMachine::NotifyReadyToActivate() {
@@ -1142,7 +1077,7 @@ void SchedulerStateMachine::NotifyReadyToActivate() {
}
void SchedulerStateMachine::NotifyReadyToDraw() {
- wait_for_active_tree_ready_to_draw_ = false;
+ wait_for_ready_to_draw_ = false;
}
void SchedulerStateMachine::DidCreateAndInitializeOutputSurface() {
@@ -1152,16 +1087,17 @@ void SchedulerStateMachine::DidCreateAndInitializeOutputSurface() {
if (did_create_and_initialize_first_output_surface_) {
// TODO(boliu): See if we can remove this when impl-side painting is always
// on. Does anything on the main thread need to update after recreate?
- needs_commit_ = true;
+ needs_begin_main_frame_ = true;
}
did_create_and_initialize_first_output_surface_ = true;
pending_swaps_ = 0;
swaps_with_current_output_surface_ = 0;
+ main_thread_missed_last_deadline_ = false;
}
void SchedulerStateMachine::NotifyBeginMainFrameStarted() {
- DCHECK_EQ(commit_state_, COMMIT_STATE_BEGIN_MAIN_FRAME_SENT);
- commit_state_ = COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED;
+ DCHECK_EQ(begin_main_frame_state_, BEGIN_MAIN_FRAME_STATE_SENT);
+ begin_main_frame_state_ = BEGIN_MAIN_FRAME_STATE_STARTED;
}
bool SchedulerStateMachine::HasInitializedOutputSurface() const {
diff --git a/chromium/cc/scheduler/scheduler_state_machine.h b/chromium/cc/scheduler/scheduler_state_machine.h
index cf1ab8c5568..d84211abc47 100644
--- a/chromium/cc/scheduler/scheduler_state_machine.h
+++ b/chromium/cc/scheduler/scheduler_state_machine.h
@@ -72,15 +72,15 @@ class CC_EXPORT SchedulerStateMachine {
static const char* BeginImplFrameDeadlineModeToString(
BeginImplFrameDeadlineMode mode);
- enum CommitState {
- COMMIT_STATE_IDLE,
- COMMIT_STATE_BEGIN_MAIN_FRAME_SENT,
- COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED,
- COMMIT_STATE_READY_TO_COMMIT,
- COMMIT_STATE_WAITING_FOR_ACTIVATION,
- COMMIT_STATE_WAITING_FOR_DRAW,
+ enum BeginMainFrameState {
+ BEGIN_MAIN_FRAME_STATE_IDLE,
+ BEGIN_MAIN_FRAME_STATE_SENT,
+ BEGIN_MAIN_FRAME_STATE_STARTED,
+ BEGIN_MAIN_FRAME_STATE_READY_TO_COMMIT,
+ BEGIN_MAIN_FRAME_STATE_WAITING_FOR_ACTIVATION,
+ BEGIN_MAIN_FRAME_STATE_WAITING_FOR_DRAW,
};
- static const char* CommitStateToString(CommitState state);
+ static const char* BeginMainFrameStateToString(BeginMainFrameState state);
enum ForcedRedrawOnTimeoutState {
FORCED_REDRAW_STATE_IDLE,
@@ -92,11 +92,13 @@ class CC_EXPORT SchedulerStateMachine {
ForcedRedrawOnTimeoutState state);
bool CommitPending() const {
- return commit_state_ == COMMIT_STATE_BEGIN_MAIN_FRAME_SENT ||
- commit_state_ == COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED ||
- commit_state_ == COMMIT_STATE_READY_TO_COMMIT;
+ return begin_main_frame_state_ == BEGIN_MAIN_FRAME_STATE_SENT ||
+ begin_main_frame_state_ == BEGIN_MAIN_FRAME_STATE_STARTED ||
+ begin_main_frame_state_ == BEGIN_MAIN_FRAME_STATE_READY_TO_COMMIT;
+ }
+ BeginMainFrameState begin_main_frame_state() const {
+ return begin_main_frame_state_;
}
- CommitState commit_state() const { return commit_state_; }
bool RedrawPending() const { return needs_redraw_; }
bool PrepareTilesPending() const { return needs_prepare_tiles_; }
@@ -120,7 +122,14 @@ class CC_EXPORT SchedulerStateMachine {
void AsValueInto(base::trace_event::TracedValue* dict) const;
Action NextAction() const;
- void UpdateState(Action action);
+ void WillAnimate();
+ void WillSendBeginMainFrame();
+ void WillCommit(bool commit_had_no_updates);
+ void WillActivate();
+ void WillDraw(bool did_request_swap);
+ void WillBeginOutputSurfaceCreation();
+ void WillPrepareTiles();
+ void WillInvalidateOutputSurface();
// Indicates whether the impl thread needs a BeginImplFrame callback in order
// to make progress.
@@ -143,7 +152,7 @@ class CC_EXPORT SchedulerStateMachine {
// If the main thread didn't manage to produce a new frame in time for the
// impl thread to draw, it is in a high latency mode.
- bool MainThreadIsInHighLatencyMode() const;
+ bool main_thread_missed_last_deadline() const;
bool SwapThrottled() const;
@@ -165,9 +174,6 @@ class CC_EXPORT SchedulerStateMachine {
// PrepareTiles will occur shortly (even if no redraw is required).
void SetNeedsPrepareTiles();
- // Make deadline wait for ReadyToDraw signal.
- void SetWaitForReadyToDraw();
-
// Sets how many swaps can be pending to the OutputSurface.
void SetMaxSwapsPending(int max);
@@ -195,11 +201,11 @@ class CC_EXPORT SchedulerStateMachine {
// Indicates whether ACTION_DRAW_AND_SWAP_IF_POSSIBLE drew to the screen.
void DidDrawIfPossibleCompleted(DrawResult result);
- // Indicates that a new commit flow needs to be performed, either to pull
- // updates from the main thread to the impl, or to push deltas from the impl
- // thread to main.
- void SetNeedsCommit();
- bool needs_commit() const { return needs_commit_; }
+ // Indicates that a new begin main frame flow needs to be performed, either
+ // to pull updates from the main thread to the impl, or to push deltas from
+ // the impl thread to main.
+ void SetNeedsBeginMainFrame();
+ bool needs_begin_main_frame() const { return needs_begin_main_frame_; }
// Call this only in response to receiving an ACTION_SEND_BEGIN_MAIN_FRAME
// from NextAction.
@@ -245,10 +251,6 @@ class CC_EXPORT SchedulerStateMachine {
// True if we need to abort draws to make forward progress.
bool PendingDrawsShouldBeAborted() const;
- void SetContinuousPainting(bool continuous_painting) {
- continuous_painting_ = continuous_painting;
- }
-
bool CouldSendBeginMainFrame() const;
void SetDeferCommits(bool defer_commits);
@@ -270,6 +272,7 @@ class CC_EXPORT SchedulerStateMachine {
bool ShouldTriggerBeginImplFrameDeadlineImmediately() const;
// True if we need to force activations to make forward progress.
+ // TODO(sunnyps): Rename this to ShouldAbortCurrentFrame or similar.
bool PendingActivationsShouldBeForced() const;
// TODO(brianderson): Remove this once NPAPI support is removed.
@@ -284,20 +287,11 @@ class CC_EXPORT SchedulerStateMachine {
bool ShouldPrepareTiles() const;
bool ShouldInvalidateOutputSurface() const;
- void UpdateStateOnAnimate();
- void UpdateStateOnSendBeginMainFrame();
- void UpdateStateOnCommit(bool commit_had_no_updates);
- void UpdateStateOnActivation();
- void UpdateStateOnDraw(bool did_request_swap);
- void UpdateStateOnBeginOutputSurfaceCreation();
- void UpdateStateOnPrepareTiles();
- void UpdateStateOnInvalidateOutputSurface();
-
const SchedulerSettings settings_;
OutputSurfaceState output_surface_state_;
BeginImplFrameState begin_impl_frame_state_;
- CommitState commit_state_;
+ BeginMainFrameState begin_main_frame_state_;
ForcedRedrawOnTimeoutState forced_redraw_state_;
// These are used for tracing only.
@@ -328,7 +322,7 @@ class CC_EXPORT SchedulerStateMachine {
bool needs_redraw_;
bool needs_animate_;
bool needs_prepare_tiles_;
- bool needs_commit_;
+ bool needs_begin_main_frame_;
bool visible_;
bool can_start_;
bool can_draw_;
@@ -337,13 +331,13 @@ class CC_EXPORT SchedulerStateMachine {
bool active_tree_needs_first_draw_;
bool did_create_and_initialize_first_output_surface_;
bool impl_latency_takes_priority_;
+ bool main_thread_missed_last_deadline_;
bool skip_next_begin_main_frame_to_reduce_latency_;
- bool continuous_painting_;
bool children_need_begin_frames_;
bool defer_commits_;
bool video_needs_begin_frames_;
bool last_commit_had_no_updates_;
- bool wait_for_active_tree_ready_to_draw_;
+ bool wait_for_ready_to_draw_;
bool did_request_swap_in_last_frame_;
bool did_perform_swap_in_last_draw_;
diff --git a/chromium/cc/scheduler/scheduler_state_machine_unittest.cc b/chromium/cc/scheduler/scheduler_state_machine_unittest.cc
index da40cc15017..6d00594dc86 100644
--- a/chromium/cc/scheduler/scheduler_state_machine_unittest.cc
+++ b/chromium/cc/scheduler/scheduler_state_machine_unittest.cc
@@ -25,8 +25,9 @@
state.begin_impl_frame_state()) \
<< state.AsValue()->ToString()
-#define EXPECT_COMMIT_STATE(expected) \
- EXPECT_ENUM_EQ(CommitStateToString, expected, state.CommitState())
+#define EXPECT_MAIN_FRAME_STATE(expected) \
+ EXPECT_ENUM_EQ(BeginMainFrameStateToString, expected, \
+ state.BeginMainFrameState())
#define EXPECT_ACTION(expected) \
EXPECT_ENUM_EQ(ActionToString, expected, state.NextAction()) \
@@ -39,7 +40,7 @@
EXPECT_IMPL_FRAME_STATE( \
SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE); \
} \
- state.UpdateState(action); \
+ WillPerformAction(&state, action); \
if (action == SchedulerStateMachine::ACTION_NONE) { \
if (state.begin_impl_frame_state() == \
SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING) \
@@ -49,30 +50,83 @@
state.OnBeginImplFrameIdle(); \
}
-#define SET_UP_STATE(state) \
- state.SetCanStart(); \
- state.UpdateState(state.NextAction()); \
- state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); \
- state.SetVisible(true); \
+#define SET_UP_STATE(state) \
+ state.SetCanStart(); \
+ state.SetVisible(true); \
+ EXPECT_ACTION_UPDATE_STATE( \
+ SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION); \
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); \
+ state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); \
state.SetCanDraw(true);
namespace cc {
namespace {
+void WillPerformAction(SchedulerStateMachine* sm,
+ SchedulerStateMachine::Action action) {
+ switch (action) {
+ case SchedulerStateMachine::ACTION_NONE:
+ return;
+
+ case SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE:
+ sm->WillActivate();
+ return;
+
+ case SchedulerStateMachine::ACTION_ANIMATE:
+ sm->WillAnimate();
+ return;
+
+ case SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME:
+ sm->WillSendBeginMainFrame();
+ return;
+
+ case SchedulerStateMachine::ACTION_COMMIT: {
+ bool commit_has_no_updates = false;
+ sm->WillCommit(commit_has_no_updates);
+ return;
+ }
+
+ case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_FORCED:
+ case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE: {
+ bool did_request_swap = true;
+ sm->WillDraw(did_request_swap);
+ return;
+ }
+
+ case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT: {
+ bool did_request_swap = false;
+ sm->WillDraw(did_request_swap);
+ return;
+ }
+
+ case SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION:
+ sm->WillBeginOutputSurfaceCreation();
+ return;
+
+ case SchedulerStateMachine::ACTION_PREPARE_TILES:
+ sm->WillPrepareTiles();
+ return;
+
+ case SchedulerStateMachine::ACTION_INVALIDATE_OUTPUT_SURFACE:
+ sm->WillInvalidateOutputSurface();
+ return;
+ }
+}
+
const SchedulerStateMachine::BeginImplFrameState all_begin_impl_frame_states[] =
{SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE,
SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING,
SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME,
SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE, };
-const SchedulerStateMachine::CommitState all_commit_states[] = {
- SchedulerStateMachine::COMMIT_STATE_IDLE,
- SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT,
- SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED,
- SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT,
- SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_ACTIVATION,
- SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_DRAW};
+const SchedulerStateMachine::BeginMainFrameState begin_main_frame_states[] = {
+ SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_IDLE,
+ SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_SENT,
+ SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_STARTED,
+ SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_READY_TO_COMMIT,
+ SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_WAITING_FOR_ACTIVATION,
+ SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_WAITING_FOR_DRAW};
// Exposes the protected state fields of the SchedulerStateMachine for testing
class StateMachine : public SchedulerStateMachine {
@@ -85,8 +139,12 @@ class StateMachine : public SchedulerStateMachine {
output_surface_state_ = OUTPUT_SURFACE_ACTIVE;
}
- void SetCommitState(CommitState cs) { commit_state_ = cs; }
- CommitState CommitState() const { return commit_state_; }
+ void SetBeginMainFrameState(BeginMainFrameState cs) {
+ begin_main_frame_state_ = cs;
+ }
+ BeginMainFrameState BeginMainFrameState() const {
+ return begin_main_frame_state_;
+ }
ForcedRedrawOnTimeoutState ForcedRedrawState() const {
return forced_redraw_state_;
@@ -104,11 +162,11 @@ class StateMachine : public SchedulerStateMachine {
return output_surface_state_;
}
- void SetNeedsCommitForTest(bool needs_commit) {
- needs_commit_ = needs_commit;
+ void SetNeedsBeginMainFrameForTest(bool needs_begin_main_frame) {
+ needs_begin_main_frame_ = needs_begin_main_frame;
}
- bool NeedsCommit() const { return needs_commit_; }
+ bool NeedsCommit() const { return needs_begin_main_frame_; }
void SetNeedsAnimateForTest(bool needs_animate) {
needs_animate_ = needs_animate;
@@ -141,20 +199,22 @@ class StateMachine : public SchedulerStateMachine {
using SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineImmediately;
using SchedulerStateMachine::ProactiveBeginFrameWanted;
- using SchedulerStateMachine::UpdateStateOnCommit;
+ using SchedulerStateMachine::WillCommit;
};
TEST(SchedulerStateMachineTest, BeginFrameNeeded) {
SchedulerSettings default_scheduler_settings;
StateMachine state(default_scheduler_settings);
state.SetCanStart();
+ state.SetVisible(true);
EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION)
+ SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
- state.SetCommitState(SchedulerStateMachine::COMMIT_STATE_IDLE);
+ state.SetBeginMainFrameState(
+ SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_IDLE);
// Don't request BeginFrames if we are idle.
- state.SetVisible(true);
state.SetNeedsRedraw(false);
state.SetNeedsAnimateForTest(false);
EXPECT_FALSE(state.BeginFrameNeeded());
@@ -175,7 +235,7 @@ TEST(SchedulerStateMachineTest, BeginFrameNeeded) {
state.SetVisible(true);
state.SetNeedsRedraw(false);
state.SetNeedsAnimateForTest(false);
- state.SetNeedsCommitForTest(true);
+ state.SetNeedsBeginMainFrameForTest(true);
EXPECT_TRUE(state.BeginFrameNeeded());
// Don't request BeginFrames when commit is pending if
@@ -183,7 +243,7 @@ TEST(SchedulerStateMachineTest, BeginFrameNeeded) {
state.SetVisible(true);
state.SetNeedsRedraw(false);
state.SetNeedsAnimateForTest(false);
- state.SetNeedsCommitForTest(true);
+ state.SetNeedsBeginMainFrameForTest(true);
state.SetDeferCommits(true);
EXPECT_FALSE(state.BeginFrameNeeded());
}
@@ -195,12 +255,14 @@ TEST(SchedulerStateMachineTest, TestNextActionBeginsMainFrameIfNeeded) {
{
StateMachine state(default_scheduler_settings);
state.SetCanStart();
+ state.SetVisible(true);
EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION)
+ SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
- state.SetCommitState(SchedulerStateMachine::COMMIT_STATE_IDLE);
+ state.SetBeginMainFrameState(
+ SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_IDLE);
state.SetNeedsRedraw(false);
- state.SetVisible(true);
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
EXPECT_FALSE(state.NeedsCommit());
@@ -216,10 +278,11 @@ TEST(SchedulerStateMachineTest, TestNextActionBeginsMainFrameIfNeeded) {
// If commit requested but can_start is still false, do nothing.
{
StateMachine state(default_scheduler_settings);
- state.SetCommitState(SchedulerStateMachine::COMMIT_STATE_IDLE);
+ state.SetBeginMainFrameState(
+ SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_IDLE);
state.SetNeedsRedraw(false);
state.SetVisible(true);
- state.SetNeedsCommit();
+ state.SetNeedsBeginMainFrame();
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
EXPECT_TRUE(state.NeedsCommit());
@@ -235,17 +298,20 @@ TEST(SchedulerStateMachineTest, TestNextActionBeginsMainFrameIfNeeded) {
// If commit requested, begin a main frame.
{
StateMachine state(default_scheduler_settings);
- state.SetCommitState(SchedulerStateMachine::COMMIT_STATE_IDLE);
+ state.SetBeginMainFrameState(
+ SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_IDLE);
state.SetCanStart();
- state.UpdateState(state.NextAction());
+ state.SetVisible(true);
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
state.SetNeedsRedraw(false);
- state.SetVisible(true);
- state.SetNeedsCommit();
+ state.SetNeedsBeginMainFrame();
// Expect nothing to happen until after OnBeginImplFrame.
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE);
+ EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_IDLE);
EXPECT_IMPL_FRAME_STATE(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE);
EXPECT_TRUE(state.NeedsCommit());
EXPECT_TRUE(state.BeginFrameNeeded());
@@ -253,34 +319,35 @@ TEST(SchedulerStateMachineTest, TestNextActionBeginsMainFrameIfNeeded) {
state.OnBeginImplFrame();
EXPECT_ACTION_UPDATE_STATE(
SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
- EXPECT_COMMIT_STATE(
- SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT);
+ EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_SENT);
EXPECT_FALSE(state.NeedsCommit());
}
// If commit requested and can't draw, still begin a main frame.
{
StateMachine state(default_scheduler_settings);
- state.SetCommitState(SchedulerStateMachine::COMMIT_STATE_IDLE);
+ state.SetBeginMainFrameState(
+ SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_IDLE);
state.SetCanStart();
- state.UpdateState(state.NextAction());
+ state.SetVisible(true);
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
state.SetNeedsRedraw(false);
- state.SetVisible(true);
- state.SetNeedsCommit();
+ state.SetNeedsBeginMainFrame();
state.SetCanDraw(false);
// Expect nothing to happen until after OnBeginImplFrame.
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE);
+ EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_IDLE);
EXPECT_IMPL_FRAME_STATE(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE);
EXPECT_TRUE(state.BeginFrameNeeded());
state.OnBeginImplFrame();
EXPECT_ACTION_UPDATE_STATE(
SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
- EXPECT_COMMIT_STATE(
- SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT);
+ EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_SENT);
EXPECT_FALSE(state.NeedsCommit());
}
}
@@ -290,10 +357,11 @@ TEST(SchedulerStateMachineTest, MainFrameBeforeActivationEnabled) {
SchedulerSettings scheduler_settings;
scheduler_settings.main_frame_before_activation_enabled = true;
StateMachine state(scheduler_settings);
- state.SetCommitState(SchedulerStateMachine::COMMIT_STATE_IDLE);
+ state.SetBeginMainFrameState(
+ SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_IDLE);
SET_UP_STATE(state)
state.SetNeedsRedraw(false);
- state.SetNeedsCommit();
+ state.SetNeedsBeginMainFrame();
EXPECT_TRUE(state.BeginFrameNeeded());
@@ -307,13 +375,13 @@ TEST(SchedulerStateMachineTest, MainFrameBeforeActivationEnabled) {
state.NotifyReadyToCommit();
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE);
+ EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_IDLE);
state.OnBeginImplFrameDeadline();
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
// Verify that the next commit starts while there is still a pending tree.
- state.SetNeedsCommit();
+ state.SetNeedsBeginMainFrame();
state.OnBeginImplFrame();
EXPECT_ACTION_UPDATE_STATE(
SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
@@ -340,7 +408,7 @@ TEST(SchedulerStateMachineTest, MainFrameBeforeActivationEnabled) {
state.DidSwapBuffers();
state.DidSwapBuffersComplete();
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE);
+ EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_IDLE);
}
TEST(SchedulerStateMachineTest,
@@ -449,7 +517,7 @@ TEST(SchedulerStateMachineTest,
SET_UP_STATE(state)
// Start a commit.
- state.SetNeedsCommit();
+ state.SetNeedsBeginMainFrame();
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
state.OnBeginImplFrame();
EXPECT_ACTION_UPDATE_STATE(
@@ -508,7 +576,7 @@ TEST(SchedulerStateMachineTest, TestFailedDrawsDoNotRestartForcedDraw) {
SET_UP_STATE(state)
// Start a commit.
- state.SetNeedsCommit();
+ state.SetNeedsBeginMainFrame();
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
state.OnBeginImplFrame();
EXPECT_ACTION_UPDATE_STATE(
@@ -643,30 +711,34 @@ TEST(SchedulerStateMachineTest, TestNextActionDrawsOnBeginImplFrame) {
// When not in BeginImplFrame deadline, or in BeginImplFrame deadline
// but not visible, don't draw.
- size_t num_commit_states =
- sizeof(all_commit_states) / sizeof(SchedulerStateMachine::CommitState);
+ size_t num_begin_main_frame_states =
+ sizeof(begin_main_frame_states) /
+ sizeof(SchedulerStateMachine::BeginMainFrameState);
size_t num_begin_impl_frame_states =
sizeof(all_begin_impl_frame_states) /
sizeof(SchedulerStateMachine::BeginImplFrameState);
- for (size_t i = 0; i < num_commit_states; ++i) {
+ for (size_t i = 0; i < num_begin_main_frame_states; ++i) {
for (size_t j = 0; j < num_begin_impl_frame_states; ++j) {
StateMachine state(default_scheduler_settings);
state.SetCanStart();
- state.UpdateState(state.NextAction());
+ state.SetVisible(true);
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
- state.SetCommitState(all_commit_states[i]);
+ state.SetBeginMainFrameState(begin_main_frame_states[i]);
state.SetBeginImplFrameState(all_begin_impl_frame_states[j]);
bool visible =
(all_begin_impl_frame_states[j] !=
SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE);
state.SetVisible(visible);
- // Case 1: needs_commit=false
+ // Case 1: needs_begin_main_frame=false
EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE,
state.NextAction());
- // Case 2: needs_commit=true
- state.SetNeedsCommit();
+ // Case 2: needs_begin_main_frame=true
+ state.SetNeedsBeginMainFrame();
EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE,
state.NextAction())
<< state.AsValue()->ToString();
@@ -675,51 +747,56 @@ TEST(SchedulerStateMachineTest, TestNextActionDrawsOnBeginImplFrame) {
// When in BeginImplFrame deadline we should always draw for SetNeedsRedraw
// except if we're ready to commit, in which case we expect a commit first.
- for (size_t i = 0; i < num_commit_states; ++i) {
+ for (size_t i = 0; i < num_begin_main_frame_states; ++i) {
StateMachine state(default_scheduler_settings);
state.SetCanStart();
- state.UpdateState(state.NextAction());
+ state.SetVisible(true);
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
state.SetCanDraw(true);
- state.SetCommitState(all_commit_states[i]);
+ state.SetBeginMainFrameState(begin_main_frame_states[i]);
state.SetBeginImplFrameState(
SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE);
state.SetNeedsRedraw(true);
- state.SetVisible(true);
SchedulerStateMachine::Action expected_action;
- if (all_commit_states[i] ==
- SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT) {
+ if (begin_main_frame_states[i] ==
+ SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_READY_TO_COMMIT) {
expected_action = SchedulerStateMachine::ACTION_COMMIT;
} else {
expected_action = SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE;
- EXPECT_ACTION(SchedulerStateMachine::ACTION_ANIMATE);
- state.UpdateState(state.NextAction());
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
}
- // Case 1: needs_commit=false.
+ // Case 1: needs_begin_main_frame=false.
EXPECT_ACTION(expected_action);
- // Case 2: needs_commit=true.
- state.SetNeedsCommit();
+ // Case 2: needs_begin_main_frame=true.
+ state.SetNeedsBeginMainFrame();
EXPECT_ACTION(expected_action);
}
}
-TEST(SchedulerStateMachineTest, TestNoCommitStatesRedrawWhenInvisible) {
+TEST(SchedulerStateMachineTest, TestNoBeginMainFrameStatesRedrawWhenInvisible) {
SchedulerSettings default_scheduler_settings;
- size_t num_commit_states =
- sizeof(all_commit_states) / sizeof(SchedulerStateMachine::CommitState);
- for (size_t i = 0; i < num_commit_states; ++i) {
+ size_t num_begin_main_frame_states =
+ sizeof(begin_main_frame_states) /
+ sizeof(SchedulerStateMachine::BeginMainFrameState);
+ for (size_t i = 0; i < num_begin_main_frame_states; ++i) {
// There shouldn't be any drawing regardless of BeginImplFrame.
for (size_t j = 0; j < 2; ++j) {
StateMachine state(default_scheduler_settings);
state.SetCanStart();
- state.UpdateState(state.NextAction());
+ state.SetVisible(true);
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
- state.SetCommitState(all_commit_states[i]);
+ state.SetBeginMainFrameState(begin_main_frame_states[i]);
state.SetVisible(false);
state.SetNeedsRedraw(true);
if (j == 1) {
@@ -727,12 +804,12 @@ TEST(SchedulerStateMachineTest, TestNoCommitStatesRedrawWhenInvisible) {
SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE);
}
- // Case 1: needs_commit=false.
+ // Case 1: needs_begin_main_frame=false.
EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE,
state.NextAction());
- // Case 2: needs_commit=true.
- state.SetNeedsCommit();
+ // Case 2: needs_begin_main_frame=true.
+ state.SetNeedsBeginMainFrame();
EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE,
state.NextAction())
<< state.AsValue()->ToString();
@@ -743,16 +820,20 @@ TEST(SchedulerStateMachineTest, TestNoCommitStatesRedrawWhenInvisible) {
TEST(SchedulerStateMachineTest, TestCanRedraw_StopsDraw) {
SchedulerSettings default_scheduler_settings;
- size_t num_commit_states =
- sizeof(all_commit_states) / sizeof(SchedulerStateMachine::CommitState);
- for (size_t i = 0; i < num_commit_states; ++i) {
+ size_t num_begin_main_frame_states =
+ sizeof(begin_main_frame_states) /
+ sizeof(SchedulerStateMachine::BeginMainFrameState);
+ for (size_t i = 0; i < num_begin_main_frame_states; ++i) {
// There shouldn't be any drawing regardless of BeginImplFrame.
for (size_t j = 0; j < 2; ++j) {
StateMachine state(default_scheduler_settings);
state.SetCanStart();
- state.UpdateState(state.NextAction());
+ state.SetVisible(true);
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
- state.SetCommitState(all_commit_states[i]);
+ state.SetBeginMainFrameState(begin_main_frame_states[i]);
state.SetVisible(false);
state.SetNeedsRedraw(true);
if (j == 1)
@@ -770,13 +851,15 @@ TEST(SchedulerStateMachineTest,
SchedulerSettings default_scheduler_settings;
StateMachine state(default_scheduler_settings);
state.SetCanStart();
- state.UpdateState(state.NextAction());
+ state.SetVisible(true);
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
state.SetActiveTreeNeedsFirstDraw(true);
- state.SetNeedsCommit();
+ state.SetNeedsBeginMainFrame();
state.SetNeedsRedraw(true);
- state.SetVisible(true);
state.SetCanDraw(false);
state.OnBeginImplFrame();
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
@@ -795,11 +878,11 @@ TEST(SchedulerStateMachineTest,
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
}
-TEST(SchedulerStateMachineTest, TestSetNeedsCommitIsNotLost) {
+TEST(SchedulerStateMachineTest, TestSetNeedsBeginMainFrameIsNotLost) {
SchedulerSettings scheduler_settings;
StateMachine state(scheduler_settings);
SET_UP_STATE(state)
- state.SetNeedsCommit();
+ state.SetNeedsBeginMainFrame();
EXPECT_TRUE(state.BeginFrameNeeded());
@@ -807,17 +890,17 @@ TEST(SchedulerStateMachineTest, TestSetNeedsCommitIsNotLost) {
state.OnBeginImplFrame();
EXPECT_ACTION_UPDATE_STATE(
SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
- EXPECT_COMMIT_STATE(
- SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT);
+ EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_SENT);
// Now, while the frame is in progress, set another commit.
- state.SetNeedsCommit();
+ state.SetNeedsBeginMainFrame();
EXPECT_TRUE(state.NeedsCommit());
// Let the frame finish.
state.NotifyBeginMainFrameStarted();
state.NotifyReadyToCommit();
- EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT);
+ EXPECT_MAIN_FRAME_STATE(
+ SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_READY_TO_COMMIT);
// Expect to commit regardless of BeginImplFrame state.
EXPECT_IMPL_FRAME_STATE(
@@ -870,21 +953,21 @@ TEST(SchedulerStateMachineTest, TestFullCycle) {
SET_UP_STATE(state)
// Start clean and set commit.
- state.SetNeedsCommit();
+ state.SetNeedsBeginMainFrame();
// Begin the frame.
state.OnBeginImplFrame();
EXPECT_ACTION_UPDATE_STATE(
SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
- EXPECT_COMMIT_STATE(
- SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT);
+ EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_SENT);
EXPECT_FALSE(state.NeedsCommit());
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
// Tell the scheduler the frame finished.
state.NotifyBeginMainFrameStarted();
state.NotifyReadyToCommit();
- EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT);
+ EXPECT_MAIN_FRAME_STATE(
+ SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_READY_TO_COMMIT);
// Commit.
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
@@ -909,7 +992,7 @@ TEST(SchedulerStateMachineTest, TestFullCycle) {
// Should be synchronized, no draw needed, no action needed.
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE);
+ EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_IDLE);
EXPECT_FALSE(state.needs_redraw());
}
@@ -919,7 +1002,7 @@ TEST(SchedulerStateMachineTest, CommitWithoutDrawWithPendingTree) {
SET_UP_STATE(state)
// Start clean and set commit.
- state.SetNeedsCommit();
+ state.SetNeedsBeginMainFrame();
// Make a main frame, commit and activate it. But don't draw it.
state.OnBeginImplFrame();
@@ -934,7 +1017,7 @@ TEST(SchedulerStateMachineTest, CommitWithoutDrawWithPendingTree) {
// Try to make a new main frame before drawing. Since we will commit it to a
// pending tree and not clobber the active tree, we're able to start a new
// begin frame and commit it.
- state.SetNeedsCommit();
+ state.SetNeedsBeginMainFrame();
state.OnBeginImplFrame();
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
EXPECT_ACTION_UPDATE_STATE(
@@ -951,7 +1034,7 @@ TEST(SchedulerStateMachineTest, DontCommitWithoutDrawWithoutPendingTree) {
SET_UP_STATE(state)
// Start clean and set commit.
- state.SetNeedsCommit();
+ state.SetNeedsBeginMainFrame();
// Make a main frame, commit and activate it. But don't draw it.
state.OnBeginImplFrame();
@@ -965,7 +1048,7 @@ TEST(SchedulerStateMachineTest, DontCommitWithoutDrawWithoutPendingTree) {
// Try to make a new main frame before drawing, but since we would clobber the
// active tree, we will not do so.
- state.SetNeedsCommit();
+ state.SetNeedsBeginMainFrame();
state.OnBeginImplFrame();
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
@@ -978,33 +1061,33 @@ TEST(SchedulerStateMachineTest, TestFullCycleWithCommitToActive) {
SET_UP_STATE(state)
// Start clean and set commit.
- state.SetNeedsCommit();
+ state.SetNeedsBeginMainFrame();
// Begin the frame.
state.OnBeginImplFrame();
EXPECT_ACTION_UPDATE_STATE(
SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
- EXPECT_COMMIT_STATE(
- SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT);
+ EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_SENT);
EXPECT_FALSE(state.NeedsCommit());
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
// Tell the scheduler the frame finished.
state.NotifyBeginMainFrameStarted();
state.NotifyReadyToCommit();
- EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT);
+ EXPECT_MAIN_FRAME_STATE(
+ SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_READY_TO_COMMIT);
// Commit.
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
// Now commit should wait for activation.
- EXPECT_COMMIT_STATE(
- SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_ACTIVATION);
+ EXPECT_MAIN_FRAME_STATE(
+ SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_WAITING_FOR_ACTIVATION);
// No activation yet, so this commit is not drawn yet. Force to draw this
// frame, and still block BeginMainFrame.
state.SetNeedsRedraw(true);
- state.SetNeedsCommit();
+ state.SetNeedsBeginMainFrame();
state.OnBeginImplFrameDeadline();
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
EXPECT_ACTION_UPDATE_STATE(
@@ -1013,8 +1096,8 @@ TEST(SchedulerStateMachineTest, TestFullCycleWithCommitToActive) {
// Cannot BeginMainFrame yet since last commit is not yet activated and drawn.
state.OnBeginImplFrame();
- EXPECT_COMMIT_STATE(
- SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_ACTIVATION);
+ EXPECT_MAIN_FRAME_STATE(
+ SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_WAITING_FOR_ACTIVATION);
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
// Now activate sync tree.
@@ -1023,7 +1106,8 @@ TEST(SchedulerStateMachineTest, TestFullCycleWithCommitToActive) {
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
EXPECT_TRUE(state.active_tree_needs_first_draw());
EXPECT_TRUE(state.needs_redraw());
- EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_DRAW);
+ EXPECT_MAIN_FRAME_STATE(
+ SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_WAITING_FOR_DRAW);
// Swap throttled. Do not draw.
state.DidSwapBuffers();
@@ -1046,7 +1130,7 @@ TEST(SchedulerStateMachineTest, TestFullCycleWithCommitToActive) {
state.DidSwapBuffersComplete();
// Now will be able to start main frame.
- EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE);
+ EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_IDLE);
EXPECT_FALSE(state.needs_redraw());
EXPECT_ACTION_UPDATE_STATE(
SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
@@ -1058,25 +1142,25 @@ TEST(SchedulerStateMachineTest, TestFullCycleWithCommitRequestInbetween) {
SET_UP_STATE(state)
// Start clean and set commit.
- state.SetNeedsCommit();
+ state.SetNeedsBeginMainFrame();
// Begin the frame.
state.OnBeginImplFrame();
EXPECT_ACTION_UPDATE_STATE(
SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
- EXPECT_COMMIT_STATE(
- SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT);
+ EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_SENT);
EXPECT_FALSE(state.NeedsCommit());
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
// Request another commit while the commit is in flight.
- state.SetNeedsCommit();
+ state.SetNeedsBeginMainFrame();
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
// Tell the scheduler the frame finished.
state.NotifyBeginMainFrameStarted();
state.NotifyReadyToCommit();
- EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT);
+ EXPECT_MAIN_FRAME_STATE(
+ SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_READY_TO_COMMIT);
// First commit and activate.
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
@@ -1099,7 +1183,7 @@ TEST(SchedulerStateMachineTest, TestFullCycleWithCommitRequestInbetween) {
// Should be synchronized, no draw needed, no action needed.
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE);
+ EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_IDLE);
EXPECT_FALSE(state.needs_redraw());
// Next BeginImplFrame should initiate second commit.
@@ -1108,16 +1192,40 @@ TEST(SchedulerStateMachineTest, TestFullCycleWithCommitRequestInbetween) {
SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
}
-TEST(SchedulerStateMachineTest, TestRequestCommitInvisible) {
+TEST(SchedulerStateMachineTest, TestNoRequestCommitWhenInvisible) {
SchedulerSettings default_scheduler_settings;
StateMachine state(default_scheduler_settings);
state.SetCanStart();
- state.UpdateState(state.NextAction());
+ state.SetVisible(true);
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
- state.SetNeedsCommit();
+ state.SetVisible(false);
+ state.SetNeedsBeginMainFrame();
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
}
+TEST(SchedulerStateMachineTest, TestNoRequestOutputSurfaceWhenInvisible) {
+ SchedulerSettings default_scheduler_settings;
+ StateMachine state(default_scheduler_settings);
+ state.SetCanStart();
+ // We should not request an OutputSurface when we are still invisible.
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ state.SetVisible(true);
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
+ state.SetVisible(false);
+ state.DidLoseOutputSurface();
+ state.SetNeedsBeginMainFrame();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ state.SetVisible(true);
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION);
+}
+
// See ThreadProxy::BeginMainFrame "EarlyOut_NotVisible" /
// "EarlyOut_OutputSurfaceLost" cases.
TEST(SchedulerStateMachineTest, TestAbortBeginMainFrameBecauseInvisible) {
@@ -1126,14 +1234,13 @@ TEST(SchedulerStateMachineTest, TestAbortBeginMainFrameBecauseInvisible) {
SET_UP_STATE(state)
// Start clean and set commit.
- state.SetNeedsCommit();
+ state.SetNeedsBeginMainFrame();
// Begin the frame while visible.
state.OnBeginImplFrame();
EXPECT_ACTION_UPDATE_STATE(
SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
- EXPECT_COMMIT_STATE(
- SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT);
+ EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_SENT);
EXPECT_FALSE(state.NeedsCommit());
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
@@ -1146,7 +1253,7 @@ TEST(SchedulerStateMachineTest, TestAbortBeginMainFrameBecauseInvisible) {
EXPECT_TRUE(state.NeedsCommit());
// We should now be back in the idle state as if we never started the frame.
- EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE);
+ EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_IDLE);
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
// We shouldn't do anything on the BeginImplFrame deadline.
@@ -1158,7 +1265,7 @@ TEST(SchedulerStateMachineTest, TestAbortBeginMainFrameBecauseInvisible) {
// Although we have aborted on this frame and haven't cancelled the commit
// (i.e. need another), don't send another BeginMainFrame yet.
- EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE);
+ EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_IDLE);
EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE);
EXPECT_TRUE(state.NeedsCommit());
@@ -1168,8 +1275,7 @@ TEST(SchedulerStateMachineTest, TestAbortBeginMainFrameBecauseInvisible) {
SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
// We should be starting the commit now.
- EXPECT_COMMIT_STATE(
- SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT);
+ EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_SENT);
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
}
@@ -1178,18 +1284,19 @@ TEST(SchedulerStateMachineTest, TestAbortBeginMainFrameBecauseCommitNotNeeded) {
SchedulerSettings default_scheduler_settings;
StateMachine state(default_scheduler_settings);
state.SetCanStart();
- state.UpdateState(state.NextAction());
- state.DidCreateAndInitializeOutputSurface();
state.SetVisible(true);
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ state.DidCreateAndInitializeOutputSurface();
state.SetCanDraw(true);
// Get into a begin frame / commit state.
- state.SetNeedsCommit();
+ state.SetNeedsBeginMainFrame();
state.OnBeginImplFrame();
EXPECT_ACTION_UPDATE_STATE(
SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
- EXPECT_COMMIT_STATE(
- SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT);
+ EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_SENT);
EXPECT_FALSE(state.NeedsCommit());
EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE);
@@ -1200,19 +1307,14 @@ TEST(SchedulerStateMachineTest, TestAbortBeginMainFrameBecauseCommitNotNeeded) {
// NeedsCommit should now be false because the commit was actually handled.
EXPECT_FALSE(state.NeedsCommit());
- // Even though the commit was aborted, we still expect to draw the new frame.
- EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
+ // Since the commit was aborted, we don't need to try and draw.
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
state.OnBeginImplFrameDeadline();
- EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
- state.DidSwapBuffers();
- state.DidSwapBuffersComplete();
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
// Verify another commit doesn't start on another frame either.
EXPECT_FALSE(state.NeedsCommit());
- EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE);
+ EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_IDLE);
state.OnBeginImplFrame();
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
@@ -1220,8 +1322,8 @@ TEST(SchedulerStateMachineTest, TestAbortBeginMainFrameBecauseCommitNotNeeded) {
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
// Verify another commit can start if requested, though.
- state.SetNeedsCommit();
- EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE);
+ state.SetNeedsBeginMainFrame();
+ EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_IDLE);
state.OnBeginImplFrame();
EXPECT_ACTION(SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
}
@@ -1238,14 +1340,14 @@ TEST(SchedulerStateMachineTest, TestFirstContextCreation) {
state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- // Check that the first init does not SetNeedsCommit.
+ // Check that the first init does not SetNeedsBeginMainFrame.
state.OnBeginImplFrame();
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
state.OnBeginImplFrameDeadline();
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
// Check that a needs commit initiates a BeginMainFrame.
- state.SetNeedsCommit();
+ state.SetNeedsBeginMainFrame();
state.OnBeginImplFrame();
EXPECT_ACTION_UPDATE_STATE(
SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
@@ -1260,8 +1362,9 @@ TEST(SchedulerStateMachineTest, TestContextLostWhenCompletelyIdle) {
state.NextAction());
state.DidLoseOutputSurface();
- EXPECT_ACTION(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION);
- state.UpdateState(state.NextAction());
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
// Once context recreation begins, nothing should happen.
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
@@ -1298,7 +1401,7 @@ TEST(SchedulerStateMachineTest,
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
// While context is recreating, commits shouldn't begin.
- state.SetNeedsCommit();
+ state.SetNeedsBeginMainFrame();
state.OnBeginImplFrame();
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
state.OnBeginImplFrameDeadline();
@@ -1319,8 +1422,7 @@ TEST(SchedulerStateMachineTest,
EXPECT_ACTION_UPDATE_STATE(
SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- EXPECT_COMMIT_STATE(
- SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT);
+ EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_SENT);
// Until that commit finishes, we shouldn't be drawing or animate.
state.OnBeginImplFrameDeadline();
@@ -1374,7 +1476,7 @@ TEST(SchedulerStateMachineTest,
// Once the context is recreated, whether we draw should be based on
// SetCanDraw if waiting on first draw after activate.
state.SetNeedsRedraw(true);
- state.SetNeedsCommit();
+ state.SetNeedsBeginMainFrame();
state.OnBeginImplFrame();
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
EXPECT_ACTION_UPDATE_STATE(
@@ -1405,7 +1507,7 @@ TEST(SchedulerStateMachineTest, TestContextLostWhileCommitInProgress) {
SET_UP_STATE(state)
// Get a commit in flight.
- state.SetNeedsCommit();
+ state.SetNeedsBeginMainFrame();
// Set damage and expect a draw.
state.SetNeedsRedraw(true);
@@ -1467,7 +1569,7 @@ TEST(SchedulerStateMachineTest,
SET_UP_STATE(state)
// Get a commit in flight.
- state.SetNeedsCommit();
+ state.SetNeedsBeginMainFrame();
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
// Set damage and expect a draw.
@@ -1489,7 +1591,7 @@ TEST(SchedulerStateMachineTest,
// Ask for another draw and also set needs commit. Expect nothing happens.
state.SetNeedsRedraw(true);
- state.SetNeedsCommit();
+ state.SetNeedsBeginMainFrame();
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
// Finish the frame, and commit and activate.
@@ -1557,8 +1659,9 @@ TEST(SchedulerStateMachineTest, DontDrawBeforeCommitAfterLostOutputSurface) {
// Cause a lost output surface, and restore it.
state.DidLoseOutputSurface();
- EXPECT_ACTION(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION);
- state.UpdateState(state.NextAction());
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
state.DidCreateAndInitializeOutputSurface();
EXPECT_FALSE(state.RedrawPending());
@@ -1572,8 +1675,8 @@ TEST(SchedulerStateMachineTest,
StateMachine state(default_scheduler_settings);
SET_UP_STATE(state)
- state.SetCommitState(
- SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT);
+ state.SetBeginMainFrameState(
+ SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_SENT);
// Cause a lost context.
state.DidLoseOutputSurface();
@@ -1593,9 +1696,11 @@ TEST(SchedulerStateMachineTest, TestNoBeginFrameNeededWhenInvisible) {
SchedulerSettings default_scheduler_settings;
StateMachine state(default_scheduler_settings);
state.SetCanStart();
- state.UpdateState(state.NextAction());
- state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
state.SetVisible(true);
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
EXPECT_FALSE(state.BeginFrameNeeded());
state.SetNeedsRedraw(true);
@@ -1612,10 +1717,13 @@ TEST(SchedulerStateMachineTest, TestNoBeginMainFrameWhenInvisible) {
SchedulerSettings default_scheduler_settings;
StateMachine state(default_scheduler_settings);
state.SetCanStart();
- state.UpdateState(state.NextAction());
+ state.SetVisible(true);
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
state.SetVisible(false);
- state.SetNeedsCommit();
+ state.SetNeedsBeginMainFrame();
EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE);
EXPECT_FALSE(state.BeginFrameNeeded());
@@ -1631,30 +1739,32 @@ TEST(SchedulerStateMachineTest, TestFinishCommitWhenCommitInProgress) {
SchedulerSettings default_scheduler_settings;
StateMachine state(default_scheduler_settings);
state.SetCanStart();
- state.UpdateState(state.NextAction());
+ state.SetVisible(true);
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
state.SetVisible(false);
- state.SetCommitState(
- SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT);
- state.SetNeedsCommit();
+ state.SetBeginMainFrameState(
+ SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_SENT);
+ state.SetNeedsBeginMainFrame();
+ // After the commit completes, activation and draw happen immediately
+ // because we are not visible.
state.NotifyBeginMainFrameStarted();
state.NotifyReadyToCommit();
- EXPECT_ACTION(SchedulerStateMachine::ACTION_COMMIT);
- state.UpdateState(state.NextAction());
- state.NotifyReadyToActivate();
- EXPECT_ACTION(SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE);
- state.UpdateState(state.NextAction());
-
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE);
EXPECT_TRUE(state.active_tree_needs_first_draw());
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
}
TEST(SchedulerStateMachineTest, TestInitialActionsWhenContextLost) {
SchedulerSettings default_scheduler_settings;
StateMachine state(default_scheduler_settings);
SET_UP_STATE(state)
- state.SetNeedsCommit();
+ state.SetNeedsBeginMainFrame();
state.DidLoseOutputSurface();
// When we are visible, we normally want to begin output surface creation
@@ -1696,6 +1806,35 @@ TEST(SchedulerStateMachineTest, ReportIfNotDrawing) {
EXPECT_FALSE(state.PendingDrawsShouldBeAborted());
}
+TEST(SchedulerStateMachineTest, ForceDrawForSynchronousCompositor) {
+ SchedulerSettings scheduler_settings;
+ scheduler_settings.using_synchronous_renderer_compositor = true;
+ StateMachine state(scheduler_settings);
+ SET_UP_STATE(state)
+ EXPECT_FALSE(state.PendingDrawsShouldBeAborted());
+
+ state.SetVisible(false);
+ state.DidLoseOutputSurface();
+
+ state.SetCanDraw(false);
+ state.WillBeginOutputSurfaceCreation();
+ state.DidCreateAndInitializeOutputSurface();
+ EXPECT_TRUE(state.PendingDrawsShouldBeAborted());
+
+ state.SetCanDraw(true);
+ state.DidLoseOutputSurface();
+ EXPECT_TRUE(state.PendingDrawsShouldBeAborted());
+
+ state.SetCanDraw(true);
+ state.WillBeginOutputSurfaceCreation();
+ state.DidCreateAndInitializeOutputSurface();
+ EXPECT_FALSE(state.PendingDrawsShouldBeAborted());
+
+ state.SetCanDraw(false);
+ state.DidLoseOutputSurface();
+ EXPECT_TRUE(state.PendingDrawsShouldBeAborted());
+}
+
TEST(SchedulerStateMachineTest,
TestTriggerDeadlineImmediatelyAfterAbortedCommit) {
SchedulerSettings default_scheduler_settings;
@@ -1709,7 +1848,7 @@ TEST(SchedulerStateMachineTest,
// As a response the compositor requests a redraw and a commit to tell the
// main thread about the new scroll offset.
state.SetNeedsRedraw(true);
- state.SetNeedsCommit();
+ state.SetNeedsBeginMainFrame();
// We should start the commit normally.
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
@@ -1758,7 +1897,7 @@ TEST(SchedulerStateMachineTest, TestImplLatencyTakesPriority) {
// This test ensures that impl-draws are prioritized over main thread updates
// in prefer impl latency mode.
state.SetNeedsRedraw(true);
- state.SetNeedsCommit();
+ state.SetNeedsBeginMainFrame();
state.OnBeginImplFrame();
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
EXPECT_ACTION_UPDATE_STATE(
@@ -1780,7 +1919,7 @@ TEST(SchedulerStateMachineTest, TestImplLatencyTakesPriority) {
state.DidSwapBuffersComplete();
// Request a new commit and finish the previous one.
- state.SetNeedsCommit();
+ state.SetNeedsBeginMainFrame();
FinishPreviousCommitAndDrawWithoutExitingDeadline(&state);
EXPECT_ACTION_UPDATE_STATE(
SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
@@ -1794,7 +1933,7 @@ TEST(SchedulerStateMachineTest, TestImplLatencyTakesPriority) {
// Verify we do not send another BeginMainFrame if was are swap throttled
// and did not just swap.
- state.SetNeedsCommit();
+ state.SetNeedsBeginMainFrame();
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
state.OnBeginImplFrame();
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
@@ -1809,7 +1948,7 @@ TEST(SchedulerStateMachineTest,
StateMachine state(default_scheduler_settings);
SET_UP_STATE(state)
- state.SetNeedsCommit();
+ state.SetNeedsBeginMainFrame();
state.OnBeginImplFrame();
EXPECT_ACTION_UPDATE_STATE(
@@ -1828,7 +1967,7 @@ TEST(SchedulerStateMachineTest, TestTriggerDeadlineImmediatelyWhenInvisible) {
StateMachine state(default_scheduler_settings);
SET_UP_STATE(state)
- state.SetNeedsCommit();
+ state.SetNeedsBeginMainFrame();
state.OnBeginImplFrame();
EXPECT_ACTION_UPDATE_STATE(
@@ -1868,7 +2007,7 @@ TEST(SchedulerStateMachineTest, TestAnimateBeforeCommit) {
// Check that animations are updated before we start a commit.
state.SetNeedsAnimate();
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- state.SetNeedsCommit();
+ state.SetNeedsBeginMainFrame();
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
EXPECT_TRUE(state.BeginFrameNeeded());
@@ -1891,7 +2030,7 @@ TEST(SchedulerStateMachineTest, TestAnimateAfterCommitBeforeDraw) {
// Check that animations are updated before we start a commit.
state.SetNeedsAnimate();
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- state.SetNeedsCommit();
+ state.SetNeedsBeginMainFrame();
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
EXPECT_TRUE(state.BeginFrameNeeded());
@@ -1950,7 +2089,7 @@ TEST(SchedulerStateMachineTest, TestDeferCommit) {
state.SetDeferCommits(true);
- state.SetNeedsCommit();
+ state.SetNeedsBeginMainFrame();
EXPECT_FALSE(state.BeginFrameNeeded());
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
@@ -1973,7 +2112,7 @@ TEST(SchedulerStateMachineTest, EarlyOutCommitWantsProactiveBeginFrame) {
EXPECT_FALSE(state.ProactiveBeginFrameWanted());
bool commit_has_no_updates = true;
- state.UpdateStateOnCommit(commit_has_no_updates);
+ state.WillCommit(commit_has_no_updates);
EXPECT_TRUE(state.ProactiveBeginFrameWanted());
state.OnBeginImplFrame();
EXPECT_FALSE(state.ProactiveBeginFrameWanted());
diff --git a/chromium/cc/scheduler/scheduler_unittest.cc b/chromium/cc/scheduler/scheduler_unittest.cc
index 42a23d423e6..669ed3b5d99 100644
--- a/chromium/cc/scheduler/scheduler_unittest.cc
+++ b/chromium/cc/scheduler/scheduler_unittest.cc
@@ -8,7 +8,6 @@
#include <vector>
#include "base/logging.h"
-#include "base/memory/scoped_vector.h"
#include "base/message_loop/message_loop.h"
#include "base/numerics/safe_conversions.h"
#include "base/run_loop.h"
@@ -300,7 +299,7 @@ class SchedulerTest : public testing::Test {
// We don't see anything happening until the first impl frame.
scheduler_->DidCreateAndInitializeOutputSurface();
- scheduler_->SetNeedsCommit();
+ scheduler_->SetNeedsBeginMainFrame();
EXPECT_TRUE(client_->needs_begin_frames());
EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
client_->Reset();
@@ -312,6 +311,7 @@ class SchedulerTest : public testing::Test {
scheduler_->NotifyBeginMainFrameStarted();
scheduler_->NotifyReadyToCommit();
scheduler_->NotifyReadyToActivate();
+ scheduler_->NotifyReadyToDraw();
EXPECT_FALSE(scheduler_->CommitPending());
@@ -426,7 +426,7 @@ TEST_F(SchedulerTest, SendBeginFramesToChildren) {
SetUpScheduler(true);
EXPECT_FALSE(client_->begin_frame_is_sent_to_children());
- scheduler_->SetNeedsCommit();
+ scheduler_->SetNeedsBeginMainFrame();
EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
EXPECT_TRUE(client_->needs_begin_frames());
@@ -518,8 +518,8 @@ TEST_F(SchedulerTest, RequestCommit) {
scheduler_settings_.use_external_begin_frame_source = true;
SetUpScheduler(true);
- // SetNeedsCommit should begin the frame on the next BeginImplFrame.
- scheduler_->SetNeedsCommit();
+ // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
+ scheduler_->SetNeedsBeginMainFrame();
EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
client_->Reset();
@@ -584,7 +584,7 @@ TEST_F(SchedulerTest, RequestCommitAfterSetDeferCommit) {
scheduler_->SetDeferCommits(true);
- scheduler_->SetNeedsCommit();
+ scheduler_->SetNeedsBeginMainFrame();
EXPECT_NO_ACTION(client_);
client_->Reset();
@@ -611,7 +611,7 @@ TEST_F(SchedulerTest, DeferCommitWithRedraw) {
scheduler_->SetDeferCommits(true);
- scheduler_->SetNeedsCommit();
+ scheduler_->SetNeedsBeginMainFrame();
EXPECT_NO_ACTION(client_);
// The SetNeedsRedraw will override the SetDeferCommits(true), to allow a
@@ -641,8 +641,8 @@ TEST_F(SchedulerTest, RequestCommitAfterBeginMainFrameSent) {
scheduler_settings_.use_external_begin_frame_source = true;
SetUpScheduler(true);
- // SetNeedsCommit should begin the frame.
- scheduler_->SetNeedsCommit();
+ // SetNeedsBeginMainFrame should begin the frame.
+ scheduler_->SetNeedsBeginMainFrame();
EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
client_->Reset();
@@ -654,8 +654,9 @@ TEST_F(SchedulerTest, RequestCommitAfterBeginMainFrameSent) {
EXPECT_TRUE(client_->needs_begin_frames());
client_->Reset();
- // Now SetNeedsCommit again. Calling here means we need a second commit.
- scheduler_->SetNeedsCommit();
+ // Now SetNeedsBeginMainFrame again. Calling here means we need a second
+ // commit.
+ scheduler_->SetNeedsBeginMainFrame();
EXPECT_EQ(client_->num_actions_(), 0);
client_->Reset();
@@ -824,15 +825,16 @@ TEST_F(SchedulerTest, RequestRedrawInsideFailedDraw) {
EXPECT_TRUE(client->needs_begin_frames());
}
-class SchedulerClientThatSetNeedsCommitInsideDraw : public FakeSchedulerClient {
+class SchedulerClientThatSetNeedsBeginMainFrameInsideDraw
+ : public FakeSchedulerClient {
public:
- SchedulerClientThatSetNeedsCommitInsideDraw()
+ SchedulerClientThatSetNeedsBeginMainFrameInsideDraw()
: set_needs_commit_on_next_draw_(false) {}
DrawResult ScheduledActionDrawAndSwapIfPossible() override {
- // Only SetNeedsCommit the first time this is called
+ // Only SetNeedsBeginMainFrame the first time this is called
if (set_needs_commit_on_next_draw_) {
- scheduler_->SetNeedsCommit();
+ scheduler_->SetNeedsBeginMainFrame();
set_needs_commit_on_next_draw_ = false;
}
return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
@@ -843,17 +845,19 @@ class SchedulerClientThatSetNeedsCommitInsideDraw : public FakeSchedulerClient {
return DRAW_SUCCESS;
}
- void SetNeedsCommitOnNextDraw() { set_needs_commit_on_next_draw_ = true; }
+ void SetNeedsBeginMainFrameOnNextDraw() {
+ set_needs_commit_on_next_draw_ = true;
+ }
private:
bool set_needs_commit_on_next_draw_;
};
-// Tests for the scheduler infinite-looping on SetNeedsCommit requests that
-// happen inside a ScheduledActionDrawAndSwap
+// Tests for the scheduler infinite-looping on SetNeedsBeginMainFrame requests
+// that happen inside a ScheduledActionDrawAndSwap
TEST_F(SchedulerTest, RequestCommitInsideDraw) {
- SchedulerClientThatSetNeedsCommitInsideDraw* client =
- new SchedulerClientThatSetNeedsCommitInsideDraw;
+ SchedulerClientThatSetNeedsBeginMainFrameInsideDraw* client =
+ new SchedulerClientThatSetNeedsBeginMainFrameInsideDraw;
scheduler_settings_.use_external_begin_frame_source = true;
SetUpScheduler(make_scoped_ptr(client).Pass(), true);
@@ -864,9 +868,9 @@ TEST_F(SchedulerTest, RequestCommitInsideDraw) {
EXPECT_EQ(0, client->num_draws());
EXPECT_TRUE(client->needs_begin_frames());
- client->SetNeedsCommitOnNextDraw();
+ client->SetNeedsBeginMainFrameOnNextDraw();
EXPECT_SCOPED(AdvanceFrame());
- client->SetNeedsCommitOnNextDraw();
+ client->SetNeedsBeginMainFrameOnNextDraw();
task_runner().RunPendingTasks(); // Run posted deadline.
EXPECT_EQ(1, client->num_draws());
EXPECT_TRUE(scheduler_->CommitPending());
@@ -938,8 +942,8 @@ TEST_F(SchedulerTest, RequestCommitInsideFailedDraw) {
}
TEST_F(SchedulerTest, NoSwapWhenDrawFails) {
- SchedulerClientThatSetNeedsCommitInsideDraw* client =
- new SchedulerClientThatSetNeedsCommitInsideDraw;
+ SchedulerClientThatSetNeedsBeginMainFrameInsideDraw* client =
+ new SchedulerClientThatSetNeedsBeginMainFrameInsideDraw;
scheduler_settings_.use_external_begin_frame_source = true;
SetUpScheduler(make_scoped_ptr(client).Pass(), true);
@@ -949,7 +953,7 @@ TEST_F(SchedulerTest, NoSwapWhenDrawFails) {
EXPECT_EQ(0, client->num_draws());
// Draw successfully, this starts a new frame.
- client->SetNeedsCommitOnNextDraw();
+ client->SetNeedsBeginMainFrameOnNextDraw();
EXPECT_SCOPED(AdvanceFrame());
task_runner().RunPendingTasks(); // Run posted deadline.
EXPECT_EQ(1, client->num_draws());
@@ -960,7 +964,7 @@ TEST_F(SchedulerTest, NoSwapWhenDrawFails) {
// Fail to draw, this should not start a frame.
client->SetDrawWillHappen(false);
- client->SetNeedsCommitOnNextDraw();
+ client->SetNeedsBeginMainFrameOnNextDraw();
EXPECT_SCOPED(AdvanceFrame());
task_runner().RunPendingTasks(); // Run posted deadline.
EXPECT_EQ(2, client->num_draws());
@@ -1247,10 +1251,11 @@ TEST_F(SchedulerTest, WaitForReadyToDrawDoNotPostDeadline) {
SchedulerClientNeedsPrepareTilesInDraw* client =
new SchedulerClientNeedsPrepareTilesInDraw;
scheduler_settings_.use_external_begin_frame_source = true;
+ scheduler_settings_.commit_to_active_tree = true;
SetUpScheduler(make_scoped_ptr(client).Pass(), true);
- // SetNeedsCommit should begin the frame on the next BeginImplFrame.
- scheduler_->SetNeedsCommit();
+ // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
+ scheduler_->SetNeedsBeginMainFrame();
EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
client_->Reset();
@@ -1268,9 +1273,7 @@ TEST_F(SchedulerTest, WaitForReadyToDrawDoNotPostDeadline) {
scheduler_->NotifyReadyToActivate();
EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
- // Set scheduler to wait for ready to draw. Schedule won't post deadline in
- // the mode.
- scheduler_->SetWaitForReadyToDraw();
+ // Scheduler won't post deadline in the mode.
client_->Reset();
task_runner().RunPendingTasks(); // Try to run posted deadline.
// There is no posted deadline.
@@ -1288,10 +1291,11 @@ TEST_F(SchedulerTest, WaitForReadyToDrawCancelledWhenLostOutputSurface) {
SchedulerClientNeedsPrepareTilesInDraw* client =
new SchedulerClientNeedsPrepareTilesInDraw;
scheduler_settings_.use_external_begin_frame_source = true;
+ scheduler_settings_.commit_to_active_tree = true;
SetUpScheduler(make_scoped_ptr(client).Pass(), true);
- // SetNeedsCommit should begin the frame on the next BeginImplFrame.
- scheduler_->SetNeedsCommit();
+ // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
+ scheduler_->SetNeedsBeginMainFrame();
EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
client_->Reset();
@@ -1309,9 +1313,7 @@ TEST_F(SchedulerTest, WaitForReadyToDrawCancelledWhenLostOutputSurface) {
scheduler_->NotifyReadyToActivate();
EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
- // Set scheduler to wait for ready to draw. Schedule won't post deadline in
- // the mode.
- scheduler_->SetWaitForReadyToDraw();
+ // Scheduler won't post deadline in the mode.
client_->Reset();
task_runner().RunPendingTasks(); // Try to run posted deadline.
// There is no posted deadline.
@@ -1330,12 +1332,12 @@ TEST_F(SchedulerTest, WaitForReadyToDrawCancelledWhenLostOutputSurface) {
void SchedulerTest::CheckMainFrameSkippedAfterLateCommit(
bool expect_send_begin_main_frame) {
// Impl thread hits deadline before commit finishes.
- scheduler_->SetNeedsCommit();
- EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
+ scheduler_->SetNeedsBeginMainFrame();
+ EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
EXPECT_SCOPED(AdvanceFrame());
- EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
+ EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
- EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
+ EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
scheduler_->NotifyBeginMainFrameStarted();
scheduler_->NotifyReadyToCommit();
scheduler_->NotifyReadyToActivate();
@@ -1344,16 +1346,16 @@ void SchedulerTest::CheckMainFrameSkippedAfterLateCommit(
EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 5);
EXPECT_ACTION("ScheduledActionCommit", client_, 3, 5);
EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 4, 5);
- EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
+ EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
client_->Reset();
- scheduler_->SetNeedsCommit();
- EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
+ scheduler_->SetNeedsBeginMainFrame();
+ EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
EXPECT_SCOPED(AdvanceFrame());
- EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
+ EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
EXPECT_EQ(expect_send_begin_main_frame,
- scheduler_->MainThreadIsInHighLatencyMode());
+ scheduler_->MainThreadMissedLastDeadline());
EXPECT_EQ(expect_send_begin_main_frame,
client_->HasAction("ScheduledActionSendBeginMainFrame"));
}
@@ -1449,9 +1451,9 @@ void SchedulerTest::ImplFrameSkippedAfterLateSwapAck(
// Draw and swap for first BeginFrame
client_->Reset();
- scheduler_->SetNeedsCommit();
+ scheduler_->SetNeedsBeginMainFrame();
scheduler_->SetNeedsRedraw();
- EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
+ EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
SendNextBeginFrame();
EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 4);
EXPECT_ACTION("WillBeginImplFrame", client_, 1, 4);
@@ -1462,7 +1464,7 @@ void SchedulerTest::ImplFrameSkippedAfterLateSwapAck(
scheduler_->NotifyBeginMainFrameStarted();
scheduler_->NotifyReadyToCommit();
scheduler_->NotifyReadyToActivate();
- EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
+ EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
EXPECT_ACTION("ScheduledActionCommit", client_, 0, 4);
EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 4);
@@ -1475,14 +1477,14 @@ void SchedulerTest::ImplFrameSkippedAfterLateSwapAck(
// Not calling scheduler_->DidSwapBuffersComplete() until after next
// BeginImplFrame puts the impl thread in high latency mode.
client_->Reset();
- scheduler_->SetNeedsCommit();
+ scheduler_->SetNeedsBeginMainFrame();
scheduler_->SetNeedsRedraw();
- EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
+ EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
SendNextBeginFrame();
// Verify that we skip the BeginImplFrame
EXPECT_NO_ACTION(client_);
EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
- EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
+ EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
// Verify that we do not perform any actions after we are no longer
// swap throttled.
@@ -1501,7 +1503,7 @@ void SchedulerTest::ImplFrameSkippedAfterLateSwapAck(
// Verify that we start the next BeginImplFrame and continue normally
// after having just skipped a BeginImplFrame.
client_->Reset();
- EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
+ EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
SendNextBeginFrame();
EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
@@ -1582,14 +1584,14 @@ TEST_F(SchedulerTest,
// Draw and swap for first BeginFrame
client_->Reset();
scheduler_->SetNeedsRedraw();
- EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
+ EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
SendNextBeginFrame();
EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 3);
EXPECT_ACTION("WillBeginImplFrame", client_, 1, 3);
EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 3);
client_->Reset();
- EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
+ EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
@@ -1600,12 +1602,12 @@ TEST_F(SchedulerTest,
// BeginImplFrame puts the impl thread in high latency mode.
client_->Reset();
scheduler_->SetNeedsRedraw();
- EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
+ EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
SendNextBeginFrame();
// Verify that we skip the BeginImplFrame
EXPECT_NO_ACTION(client_);
EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
- EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
+ EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
// Verify that we do not perform any actions after we are no longer
// swap throttled.
@@ -1616,7 +1618,7 @@ TEST_F(SchedulerTest,
// Verify that we start the next BeginImplFrame and continue normally
// after having just skipped a BeginImplFrame.
client_->Reset();
- EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
+ EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
SendNextBeginFrame();
EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
@@ -1637,8 +1639,8 @@ void SchedulerTest::ImplFrameIsNotSkippedAfterLateSwapAck() {
// Draw and swap for first BeginFrame
client_->Reset();
- scheduler_->SetNeedsCommit();
- EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
+ scheduler_->SetNeedsBeginMainFrame();
+ EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
SendNextBeginFrame();
EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 3);
EXPECT_ACTION("WillBeginImplFrame", client_, 1, 3);
@@ -1648,7 +1650,7 @@ void SchedulerTest::ImplFrameIsNotSkippedAfterLateSwapAck() {
scheduler_->NotifyBeginMainFrameStarted();
scheduler_->NotifyReadyToCommit();
scheduler_->NotifyReadyToActivate();
- EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
+ EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
EXPECT_ACTION("ScheduledActionCommit", client_, 0, 4);
EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 4);
@@ -1661,12 +1663,12 @@ void SchedulerTest::ImplFrameIsNotSkippedAfterLateSwapAck() {
// Not calling scheduler_->DidSwapBuffersComplete() until after next frame
// puts the impl thread in high latency mode.
client_->Reset();
- scheduler_->SetNeedsCommit();
- EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
+ scheduler_->SetNeedsBeginMainFrame();
+ EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
SendNextBeginFrame();
EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
- EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
+ EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
client_->Reset();
scheduler_->DidSwapBuffersComplete();
@@ -1747,18 +1749,18 @@ TEST_F(SchedulerTest,
client_->SetAutomaticSwapAck(false);
// Impl thread hits deadline before commit finishes to make
- // MainThreadIsInHighLatencyMode true
+ // MainThreadMissedLastDeadline true
client_->Reset();
- scheduler_->SetNeedsCommit();
- EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
+ scheduler_->SetNeedsBeginMainFrame();
+ EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
EXPECT_SCOPED(AdvanceFrame());
- EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
+ EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
- EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
+ EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
scheduler_->NotifyBeginMainFrameStarted();
scheduler_->NotifyReadyToCommit();
scheduler_->NotifyReadyToActivate();
- EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
+ EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 5);
EXPECT_ACTION("WillBeginImplFrame", client_, 1, 5);
@@ -1768,10 +1770,10 @@ TEST_F(SchedulerTest,
// Draw and swap for first commit, start second commit.
client_->Reset();
- scheduler_->SetNeedsCommit();
- EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
+ scheduler_->SetNeedsBeginMainFrame();
+ EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
EXPECT_SCOPED(AdvanceFrame());
- EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
+ EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
scheduler_->NotifyBeginMainFrameStarted();
scheduler_->NotifyReadyToCommit();
@@ -1787,11 +1789,10 @@ TEST_F(SchedulerTest,
// Don't call scheduler_->DidSwapBuffersComplete() until after next frame
// to put the impl thread in a high latency mode.
client_->Reset();
- scheduler_->SetNeedsCommit();
- EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
- EXPECT_TRUE(scheduler_->SwapThrottled());
+ scheduler_->SetNeedsBeginMainFrame();
+ EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
EXPECT_SCOPED(AdvanceFrame());
- EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
+ EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
@@ -1800,7 +1801,7 @@ TEST_F(SchedulerTest,
// swap ack backpressure, not because of latency recovery.
EXPECT_FALSE(client_->HasAction("ScheduledActionSendBeginMainFrame"));
EXPECT_FALSE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
- EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
+ EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
// Lower estimates so that the scheduler will attempt latency recovery.
auto fast_duration = base::TimeDelta::FromMilliseconds(1);
@@ -1813,14 +1814,14 @@ TEST_F(SchedulerTest,
// Verify we skip BeginMainFrame first.
client_->Reset();
// Previous commit request is still outstanding.
- EXPECT_TRUE(scheduler_->NeedsCommit());
+ EXPECT_TRUE(scheduler_->NeedsBeginMainFrame());
EXPECT_TRUE(scheduler_->SwapThrottled());
SendNextBeginFrame();
- EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
+ EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
scheduler_->DidSwapBuffersComplete();
task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
- EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
+ EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 2, 3);
@@ -1828,30 +1829,30 @@ TEST_F(SchedulerTest,
// Verify we skip the BeginImplFrame second.
client_->Reset();
// Previous commit request is still outstanding.
- EXPECT_TRUE(scheduler_->NeedsCommit());
- EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
+ EXPECT_TRUE(scheduler_->NeedsBeginMainFrame());
+ EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
SendNextBeginFrame();
task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
- EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
+ EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
scheduler_->DidSwapBuffersComplete();
- EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
+ EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
EXPECT_NO_ACTION(client_);
// Then verify we operate in a low latency mode.
client_->Reset();
// Previous commit request is still outstanding.
- EXPECT_TRUE(scheduler_->NeedsCommit());
- EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
+ EXPECT_TRUE(scheduler_->NeedsBeginMainFrame());
+ EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
SendNextBeginFrame();
- EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
+ EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
scheduler_->NotifyBeginMainFrameStarted();
scheduler_->NotifyReadyToCommit();
scheduler_->NotifyReadyToActivate();
task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
- EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
+ EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
scheduler_->DidSwapBuffersComplete();
- EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
+ EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
EXPECT_ACTION("WillBeginImplFrame", client_, 0, 6);
EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 6);
@@ -1880,7 +1881,7 @@ TEST_F(
// in a swap throttled state.
client_->Reset();
EXPECT_FALSE(scheduler_->CommitPending());
- scheduler_->SetNeedsCommit();
+ scheduler_->SetNeedsBeginMainFrame();
scheduler_->SetNeedsRedraw();
EXPECT_SCOPED(AdvanceFrame());
EXPECT_TRUE(scheduler_->CommitPending());
@@ -1902,7 +1903,7 @@ TEST_F(
// Make sure that we can finish the next commit even while swap throttled.
client_->Reset();
EXPECT_FALSE(scheduler_->CommitPending());
- scheduler_->SetNeedsCommit();
+ scheduler_->SetNeedsBeginMainFrame();
EXPECT_SCOPED(AdvanceFrame());
scheduler_->NotifyBeginMainFrameStarted();
scheduler_->NotifyReadyToCommit();
@@ -1920,7 +1921,7 @@ TEST_F(
// we have both a pending tree and an active tree.
client_->Reset();
EXPECT_FALSE(scheduler_->CommitPending());
- scheduler_->SetNeedsCommit();
+ scheduler_->SetNeedsBeginMainFrame();
EXPECT_SCOPED(AdvanceFrame());
EXPECT_FALSE(scheduler_->CommitPending());
task_runner().RunPendingTasks(); // Run posted deadline.
@@ -1951,7 +1952,7 @@ TEST_F(SchedulerTest,
// activation.
client_->Reset();
EXPECT_FALSE(scheduler_->CommitPending());
- scheduler_->SetNeedsCommit();
+ scheduler_->SetNeedsBeginMainFrame();
scheduler_->SetNeedsRedraw();
EXPECT_SCOPED(AdvanceFrame());
EXPECT_TRUE(scheduler_->CommitPending());
@@ -1973,7 +1974,7 @@ TEST_F(SchedulerTest,
// Enter a swap throttled state.
client_->Reset();
EXPECT_FALSE(scheduler_->CommitPending());
- scheduler_->SetNeedsCommit();
+ scheduler_->SetNeedsBeginMainFrame();
scheduler_->SetNeedsRedraw();
EXPECT_SCOPED(AdvanceFrame());
EXPECT_TRUE(scheduler_->CommitPending());
@@ -2002,7 +2003,7 @@ TEST_F(SchedulerTest,
// it's first draw.
client_->Reset();
EXPECT_FALSE(scheduler_->CommitPending());
- scheduler_->SetNeedsCommit();
+ scheduler_->SetNeedsBeginMainFrame();
EXPECT_SCOPED(AdvanceFrame());
EXPECT_FALSE(scheduler_->CommitPending());
task_runner().RunPendingTasks(); // Run posted deadline.
@@ -2032,7 +2033,7 @@ TEST_F(
// activation.
client_->Reset();
EXPECT_FALSE(scheduler_->CommitPending());
- scheduler_->SetNeedsCommit();
+ scheduler_->SetNeedsBeginMainFrame();
scheduler_->SetNeedsRedraw();
EXPECT_SCOPED(AdvanceFrame());
EXPECT_TRUE(scheduler_->CommitPending());
@@ -2053,7 +2054,7 @@ TEST_F(
// Start another commit while we still have an active tree.
client_->Reset();
EXPECT_FALSE(scheduler_->CommitPending());
- scheduler_->SetNeedsCommit();
+ scheduler_->SetNeedsBeginMainFrame();
scheduler_->SetNeedsRedraw();
EXPECT_SCOPED(AdvanceFrame());
EXPECT_TRUE(scheduler_->CommitPending());
@@ -2084,8 +2085,8 @@ TEST_F(SchedulerTest, BeginRetroFrame) {
scheduler_settings_.use_external_begin_frame_source = true;
SetUpScheduler(true);
- // SetNeedsCommit should begin the frame on the next BeginImplFrame.
- scheduler_->SetNeedsCommit();
+ // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
+ scheduler_->SetNeedsBeginMainFrame();
EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
client_->Reset();
@@ -2165,9 +2166,9 @@ TEST_F(SchedulerTest, BeginRetroFrame_SwapThrottled) {
scheduler_->SetMaxSwapsPending(1);
client_->SetAutomaticSwapAck(false);
- // SetNeedsCommit should begin the frame on the next BeginImplFrame.
+ // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
client_->Reset();
- scheduler_->SetNeedsCommit();
+ scheduler_->SetNeedsBeginMainFrame();
EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
client_->Reset();
@@ -2209,7 +2210,7 @@ TEST_F(SchedulerTest, BeginRetroFrame_SwapThrottled) {
// While swap throttled, BeginRetroFrames should trigger BeginImplFrames
// but not a BeginMainFrame or draw.
- scheduler_->SetNeedsCommit();
+ scheduler_->SetNeedsBeginMainFrame();
scheduler_->SetNeedsRedraw();
// Run posted BeginRetroFrame.
task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(false));
@@ -2245,7 +2246,7 @@ TEST_F(SchedulerTest, RetroFrameDoesNotExpireTooEarly) {
scheduler_settings_.use_external_begin_frame_source = true;
SetUpScheduler(true);
- scheduler_->SetNeedsCommit();
+ scheduler_->SetNeedsBeginMainFrame();
EXPECT_TRUE(client_->needs_begin_frames());
EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
@@ -2306,7 +2307,7 @@ TEST_F(SchedulerTest, RetroFrameExpiresOnTime) {
scheduler_settings_.use_external_begin_frame_source = true;
SetUpScheduler(true);
- scheduler_->SetNeedsCommit();
+ scheduler_->SetNeedsBeginMainFrame();
EXPECT_TRUE(client_->needs_begin_frames());
EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
@@ -2359,7 +2360,7 @@ TEST_F(SchedulerTest, MissedFrameDoesNotExpireTooEarly) {
scheduler_settings_.use_external_begin_frame_source = true;
SetUpScheduler(true);
- scheduler_->SetNeedsCommit();
+ scheduler_->SetNeedsBeginMainFrame();
EXPECT_TRUE(client_->needs_begin_frames());
EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
@@ -2384,7 +2385,7 @@ TEST_F(SchedulerTest, MissedFrameExpiresOnTime) {
scheduler_settings_.use_external_begin_frame_source = true;
SetUpScheduler(true);
- scheduler_->SetNeedsCommit();
+ scheduler_->SetNeedsBeginMainFrame();
EXPECT_TRUE(client_->needs_begin_frames());
EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
@@ -2413,9 +2414,9 @@ void SchedulerTest::BeginFramesNotFromClient(
scheduler_settings_.throttle_frame_production = throttle_frame_production;
SetUpScheduler(true);
- // SetNeedsCommit should begin the frame on the next BeginImplFrame
+ // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame
// without calling SetNeedsBeginFrame.
- scheduler_->SetNeedsCommit();
+ scheduler_->SetNeedsBeginMainFrame();
EXPECT_NO_ACTION(client_);
client_->Reset();
@@ -2506,9 +2507,9 @@ void SchedulerTest::BeginFramesNotFromClient_SwapThrottled(
scheduler_->SetMaxSwapsPending(1);
client_->SetAutomaticSwapAck(false);
- // SetNeedsCommit should begin the frame on the next BeginImplFrame.
+ // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
client_->Reset();
- scheduler_->SetNeedsCommit();
+ scheduler_->SetNeedsBeginMainFrame();
EXPECT_NO_ACTION(client_);
client_->Reset();
@@ -2540,7 +2541,7 @@ void SchedulerTest::BeginFramesNotFromClient_SwapThrottled(
// While swap throttled, BeginFrames should trigger BeginImplFrames,
// but not a BeginMainFrame or draw.
- scheduler_->SetNeedsCommit();
+ scheduler_->SetNeedsBeginMainFrame();
scheduler_->SetNeedsRedraw();
EXPECT_SCOPED(AdvanceFrame()); // Run posted BeginFrame.
EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
@@ -2615,8 +2616,8 @@ TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterBeginFrameStarted) {
scheduler_settings_.use_external_begin_frame_source = true;
SetUpScheduler(true);
- // SetNeedsCommit should begin the frame.
- scheduler_->SetNeedsCommit();
+ // SetNeedsBeginMainFrame should begin the frame.
+ scheduler_->SetNeedsBeginMainFrame();
EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
client_->Reset();
@@ -2648,8 +2649,8 @@ TEST_F(SchedulerTest,
scheduler_settings_.use_external_begin_frame_source = true;
SetUpScheduler(true);
- // SetNeedsCommit should begin the frame.
- scheduler_->SetNeedsCommit();
+ // SetNeedsBeginMainFrame should begin the frame.
+ scheduler_->SetNeedsBeginMainFrame();
EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
client_->Reset();
@@ -2692,8 +2693,8 @@ TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterReadyToCommit) {
scheduler_settings_.use_external_begin_frame_source = true;
SetUpScheduler(true);
- // SetNeedsCommit should begin the frame.
- scheduler_->SetNeedsCommit();
+ // SetNeedsBeginMainFrame should begin the frame.
+ scheduler_->SetNeedsBeginMainFrame();
EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
client_->Reset();
@@ -2751,8 +2752,8 @@ TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterBeginRetroFramePosted) {
scheduler_settings_.use_external_begin_frame_source = true;
SetUpScheduler(true);
- // SetNeedsCommit should begin the frame on the next BeginImplFrame.
- scheduler_->SetNeedsCommit();
+ // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
+ scheduler_->SetNeedsBeginMainFrame();
EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
// Create a BeginFrame with a long deadline to avoid race conditions.
@@ -2811,8 +2812,8 @@ TEST_F(SchedulerTest, DidLoseOutputSurfaceDuringBeginRetroFrameRunning) {
scheduler_settings_.use_external_begin_frame_source = true;
SetUpScheduler(true);
- // SetNeedsCommit should begin the frame on the next BeginImplFrame.
- scheduler_->SetNeedsCommit();
+ // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
+ scheduler_->SetNeedsBeginMainFrame();
EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
// Create a BeginFrame with a long deadline to avoid race conditions.
@@ -2885,9 +2886,9 @@ TEST_F(SchedulerTest, DidLoseOutputSurfaceDuringBeginRetroFrameRunning) {
TEST_F(SchedulerTest, DidLoseOutputSurfaceWithSyntheticBeginFrameSource) {
SetUpScheduler(true);
- // SetNeedsCommit should begin the frame on the next BeginImplFrame.
+ // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
EXPECT_FALSE(scheduler_->frame_source().NeedsBeginFrames());
- scheduler_->SetNeedsCommit();
+ scheduler_->SetNeedsBeginMainFrame();
EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames());
client_->Reset();
@@ -2927,8 +2928,8 @@ TEST_F(SchedulerTest, DidLoseOutputSurfaceWhenIdle) {
scheduler_settings_.use_external_begin_frame_source = true;
SetUpScheduler(true);
- // SetNeedsCommit should begin the frame.
- scheduler_->SetNeedsCommit();
+ // SetNeedsBeginMainFrame should begin the frame.
+ scheduler_->SetNeedsBeginMainFrame();
EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
client_->Reset();
@@ -2963,8 +2964,8 @@ TEST_F(SchedulerTest, ScheduledActionActivateAfterBecomingInvisible) {
scheduler_settings_.use_external_begin_frame_source = true;
SetUpScheduler(true);
- // SetNeedsCommit should begin the frame.
- scheduler_->SetNeedsCommit();
+ // SetNeedsBeginMainFrame should begin the frame.
+ scheduler_->SetNeedsBeginMainFrame();
EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
client_->Reset();
@@ -3111,8 +3112,8 @@ TEST_F(SchedulerTest, SendBeginMainFrameNotExpectedSoon) {
scheduler_settings_.use_external_begin_frame_source = true;
SetUpScheduler(true);
- // SetNeedsCommit should begin the frame on the next BeginImplFrame.
- scheduler_->SetNeedsCommit();
+ // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
+ scheduler_->SetNeedsBeginMainFrame();
EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
client_->Reset();
@@ -3222,7 +3223,7 @@ TEST_F(SchedulerTest, SynchronousCompositorCommit) {
scheduler_settings_.use_external_begin_frame_source = true;
SetUpScheduler(true);
- scheduler_->SetNeedsCommit();
+ scheduler_->SetNeedsBeginMainFrame();
EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
client_->Reset();
@@ -3279,7 +3280,7 @@ TEST_F(SchedulerTest, SynchronousCompositorDoubleCommitWithoutDraw) {
scheduler_settings_.use_external_begin_frame_source = true;
SetUpScheduler(true);
- scheduler_->SetNeedsCommit();
+ scheduler_->SetNeedsBeginMainFrame();
EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
client_->Reset();
@@ -3302,7 +3303,7 @@ TEST_F(SchedulerTest, SynchronousCompositorDoubleCommitWithoutDraw) {
client_->Reset();
// Ask for another commit.
- scheduler_->SetNeedsCommit();
+ scheduler_->SetNeedsBeginMainFrame();
AdvanceFrame();
EXPECT_ACTION("WillBeginImplFrame", client_, 0, 4);
@@ -3404,8 +3405,8 @@ TEST_F(SchedulerTest, SynchronousCompositorSendBeginMainFrameWhileIdle) {
EXPECT_FALSE(scheduler_->PrepareTilesPending());
client_->Reset();
- // Simulate SetNeedsCommit due to input event.
- scheduler_->SetNeedsCommit();
+ // Simulate SetNeedsBeginMainFrame due to input event.
+ scheduler_->SetNeedsBeginMainFrame();
EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client_);
client_->Reset();
@@ -3433,19 +3434,36 @@ TEST_F(SchedulerTest, SynchronousCompositorSendBeginMainFrameWhileIdle) {
EXPECT_FALSE(scheduler_->PrepareTilesPending());
client_->Reset();
- // Simulate SetNeedsCommit due to input event.
- scheduler_->SetNeedsCommit();
+ // Simulate SetNeedsBeginMainFrame due to input event.
+ scheduler_->SetNeedsBeginMainFrame();
EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client_);
client_->Reset();
}
+TEST_F(SchedulerTest, SynchronousCompositorOnDrawWhenInvisible) {
+ scheduler_settings_.using_synchronous_renderer_compositor = true;
+ scheduler_settings_.use_external_begin_frame_source = true;
+ SetUpScheduler(true);
+
+ scheduler_->SetVisible(false);
+
+ scheduler_->SetNeedsRedraw();
+ scheduler_->OnDrawForOutputSurface();
+ // Action animate is the result of SetNeedsRedraw.
+ EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
+ // SynchronousCompositor has to draw regardless of visibility.
+ EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
+ EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
+ client_->Reset();
+}
+
TEST_F(SchedulerTest, AuthoritativeVSyncInterval) {
SetUpScheduler(true);
base::TimeDelta initial_interval = scheduler_->BeginImplFrameInterval();
base::TimeDelta authoritative_interval =
base::TimeDelta::FromMilliseconds(33);
- scheduler_->SetNeedsCommit();
+ scheduler_->SetNeedsBeginMainFrame();
EXPECT_SCOPED(AdvanceFrame());
EXPECT_EQ(initial_interval, scheduler_->BeginImplFrameInterval());
diff --git a/chromium/cc/surfaces/BUILD.gn b/chromium/cc/surfaces/BUILD.gn
index 0f2c9509f4b..6dd7240bc1f 100644
--- a/chromium/cc/surfaces/BUILD.gn
+++ b/chromium/cc/surfaces/BUILD.gn
@@ -31,6 +31,8 @@ component("surfaces") {
"surface_factory.cc",
"surface_factory.h",
"surface_factory_client.h",
+ "surface_hittest.cc",
+ "surface_hittest.h",
"surface_id_allocator.cc",
"surface_id_allocator.h",
"surface_manager.cc",
@@ -55,7 +57,7 @@ component("surfaces") {
]
if (is_android && !is_debug) {
- configs -= [ "//build/config/compiler:optimize" ]
+ configs -= [ "//build/config/compiler:default_optimization" ]
configs += [ "//build/config/compiler:optimize_max" ]
}
}
diff --git a/chromium/cc/surfaces/display.cc b/chromium/cc/surfaces/display.cc
index 37a9756950c..dd776fb1bc4 100644
--- a/chromium/cc/surfaces/display.cc
+++ b/chromium/cc/surfaces/display.cc
@@ -20,6 +20,7 @@
#include "cc/surfaces/surface_aggregator.h"
#include "cc/surfaces/surface_manager.h"
#include "gpu/command_buffer/client/gles2_interface.h"
+#include "ui/gfx/buffer_types.h"
namespace cc {
@@ -62,17 +63,22 @@ void Display::SetSurfaceId(SurfaceId id, float device_scale_factor) {
if (current_surface_id_ == id && device_scale_factor_ == device_scale_factor)
return;
+ TRACE_EVENT0("cc", "Display::SetSurfaceId");
+
current_surface_id_ = id;
device_scale_factor_ = device_scale_factor;
UpdateRootSurfaceResourcesLocked();
if (scheduler_)
- scheduler_->EntireDisplayDamaged(id);
+ scheduler_->SetNewRootSurface(id);
}
void Display::Resize(const gfx::Size& size) {
if (size == current_surface_size_)
return;
+
+ TRACE_EVENT0("cc", "Display::Resize");
+
// Need to ensure all pending swaps have executed before the window is
// resized, or D3D11 will scale the swap output.
if (settings_.finish_rendering_on_resize) {
@@ -85,7 +91,7 @@ void Display::Resize(const gfx::Size& size) {
swapped_since_resize_ = false;
current_surface_size_ = size;
if (scheduler_)
- scheduler_->EntireDisplayDamaged(current_surface_id_);
+ scheduler_->DisplayResized();
}
void Display::SetExternalClip(const gfx::Rect& clip) {
@@ -96,13 +102,12 @@ void Display::InitializeRenderer() {
if (resource_provider_)
return;
- // Display does not use GpuMemoryBuffers, so persistent map is not relevant.
- bool use_persistent_map_for_gpu_memory_buffers = false;
scoped_ptr<ResourceProvider> resource_provider = ResourceProvider::Create(
output_surface_.get(), bitmap_manager_, gpu_memory_buffer_manager_,
- nullptr, settings_.highp_threshold_min, settings_.use_rgba_4444_textures,
+ nullptr, settings_.highp_threshold_min,
settings_.texture_id_allocation_chunk_size,
- use_persistent_map_for_gpu_memory_buffers);
+ std::vector<unsigned>(static_cast<size_t>(gfx::BufferFormat::LAST) + 1,
+ GL_TEXTURE_2D));
if (!resource_provider)
return;
@@ -122,7 +127,12 @@ void Display::InitializeRenderer() {
}
resource_provider_ = resource_provider.Pass();
- aggregator_.reset(new SurfaceAggregator(manager_, resource_provider_.get()));
+ // TODO(jbauman): Outputting an incomplete quad list doesn't work when using
+ // overlays.
+ bool output_partial_list = renderer_->Capabilities().using_partial_swap &&
+ !output_surface_->GetOverlayCandidateValidator();
+ aggregator_.reset(new SurfaceAggregator(manager_, resource_provider_.get(),
+ output_partial_list));
}
void Display::DidLoseOutputSurface() {
@@ -141,19 +151,26 @@ void Display::UpdateRootSurfaceResourcesLocked() {
}
bool Display::DrawAndSwap() {
- if (current_surface_id_.is_null())
+ TRACE_EVENT0("cc", "Display::DrawAndSwap");
+
+ if (current_surface_id_.is_null()) {
+ TRACE_EVENT_INSTANT0("cc", "No root surface.", TRACE_EVENT_SCOPE_THREAD);
return false;
+ }
InitializeRenderer();
- if (!output_surface_)
+ if (!output_surface_) {
+ TRACE_EVENT_INSTANT0("cc", "No output surface", TRACE_EVENT_SCOPE_THREAD);
return false;
+ }
scoped_ptr<CompositorFrame> frame =
aggregator_->Aggregate(current_surface_id_);
- if (!frame)
+ if (!frame) {
+ TRACE_EVENT_INSTANT0("cc", "Empty aggregated frame.",
+ TRACE_EVENT_SCOPE_THREAD);
return false;
-
- TRACE_EVENT0("cc", "Display::DrawAndSwap");
+ }
// Run callbacks early to allow pipelining.
for (const auto& id_entry : aggregator_->previous_contained_surfaces()) {
@@ -161,6 +178,7 @@ bool Display::DrawAndSwap() {
if (surface)
surface->RunDrawCallbacks(SurfaceDrawStatus::DRAWN);
}
+
DelegatedFrameData* frame_data = frame->delegated_frame_data.get();
frame->metadata.latency_info.insert(frame->metadata.latency_info.end(),
@@ -179,9 +197,13 @@ bool Display::DrawAndSwap() {
have_damage =
!frame_data->render_pass_list.back()->damage_rect.size().IsEmpty();
}
- bool avoid_swap = surface_size != current_surface_size_;
+
+ bool size_matches = surface_size == current_surface_size_;
+ if (!size_matches)
+ TRACE_EVENT_INSTANT0("cc", "Size missmatch.", TRACE_EVENT_SCOPE_THREAD);
+
bool should_draw = !frame->metadata.latency_info.empty() ||
- have_copy_requests || (have_damage && !avoid_swap);
+ have_copy_requests || (have_damage && size_matches);
// If the surface is suspended then the resources to be used by the draw are
// likely destroyed.
@@ -202,20 +224,25 @@ bool Display::DrawAndSwap() {
renderer_->DrawFrame(&frame_data->render_pass_list, device_scale_factor_,
device_viewport_rect, device_clip_rect,
disable_picture_quad_image_filtering);
+ } else {
+ TRACE_EVENT_INSTANT0("cc", "Draw skipped.", TRACE_EVENT_SCOPE_THREAD);
}
- if (should_draw && !avoid_swap) {
+ bool should_swap = should_draw && size_matches;
+ if (should_swap) {
swapped_since_resize_ = true;
for (auto& latency : frame->metadata.latency_info) {
- TRACE_EVENT_FLOW_STEP0(
- "input,benchmark",
- "LatencyInfo.Flow",
- TRACE_ID_DONT_MANGLE(latency.trace_id),
- "Display::DrawAndSwap");
+ TRACE_EVENT_WITH_FLOW1("input,benchmark", "LatencyInfo.Flow",
+ TRACE_ID_DONT_MANGLE(latency.trace_id()),
+ TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
+ "step", "Display::DrawAndSwap");
}
benchmark_instrumentation::IssueDisplayRenderingStatsEvent();
renderer_->SwapBuffers(frame->metadata);
} else {
+ if (have_damage && !size_matches)
+ aggregator_->SetFullDamageForSurface(current_surface_id_);
+ TRACE_EVENT_INSTANT0("cc", "Swap skipped.", TRACE_EVENT_SCOPE_THREAD);
stored_latency_info_.insert(stored_latency_info_.end(),
frame->metadata.latency_info.begin(),
frame->metadata.latency_info.end());
@@ -250,7 +277,9 @@ void Display::OnDraw() {
}
void Display::SetNeedsRedrawRect(const gfx::Rect& damage_rect) {
- NOTREACHED();
+ aggregator_->SetFullDamageForSurface(current_surface_id_);
+ if (scheduler_)
+ scheduler_->SurfaceDamaged(current_surface_id_);
}
void Display::ReclaimResources(const CompositorFrameAck* ack) {
diff --git a/chromium/cc/surfaces/display_scheduler.cc b/chromium/cc/surfaces/display_scheduler.cc
index 3810e148864..033632ec9ca 100644
--- a/chromium/cc/surfaces/display_scheduler.cc
+++ b/chromium/cc/surfaces/display_scheduler.cc
@@ -23,7 +23,7 @@ DisplayScheduler::DisplayScheduler(DisplaySchedulerClient* client,
root_surface_resources_locked_(true),
inside_begin_frame_deadline_interval_(false),
needs_draw_(false),
- entire_display_damaged_(false),
+ expecting_root_surface_damage_because_of_resize_(false),
all_active_child_surfaces_ready_to_draw_(false),
pending_swaps_(0),
max_pending_swaps_(max_pending_swaps),
@@ -42,28 +42,34 @@ DisplayScheduler::~DisplayScheduler() {
// If we try to draw when the root surface resources are locked, the
// draw will fail.
void DisplayScheduler::SetRootSurfaceResourcesLocked(bool locked) {
+ TRACE_EVENT1("cc", "DisplayScheduler::SetRootSurfaceResourcesLocked",
+ "locked", locked);
root_surface_resources_locked_ = locked;
ScheduleBeginFrameDeadline();
}
// This is used to force an immediate swap before a resize.
void DisplayScheduler::ForceImmediateSwapIfPossible() {
+ TRACE_EVENT0("cc", "DisplayScheduler::ForceImmediateSwapIfPossible");
bool in_begin = inside_begin_frame_deadline_interval_;
AttemptDrawAndSwap();
if (in_begin)
begin_frame_source_->DidFinishFrame(0);
}
+void DisplayScheduler::DisplayResized() {
+ expecting_root_surface_damage_because_of_resize_ = true;
+ expect_damage_from_root_surface_ = true;
+ needs_draw_ = true;
+ ScheduleBeginFrameDeadline();
+}
+
// Notification that there was a resize or the root surface changed and
// that we should just draw immediately.
-void DisplayScheduler::EntireDisplayDamaged(SurfaceId root_surface_id) {
- TRACE_EVENT0("cc", "DisplayScheduler::EntireDisplayDamaged");
- needs_draw_ = true;
- entire_display_damaged_ = true;
+void DisplayScheduler::SetNewRootSurface(SurfaceId root_surface_id) {
+ TRACE_EVENT0("cc", "DisplayScheduler::SetNewRootSurface");
root_surface_id_ = root_surface_id;
-
- begin_frame_source_->SetNeedsBeginFrames(!output_surface_lost_);
- ScheduleBeginFrameDeadline();
+ SurfaceDamaged(root_surface_id);
}
// Indicates that there was damage to one of the surfaces.
@@ -77,6 +83,7 @@ void DisplayScheduler::SurfaceDamaged(SurfaceId surface_id) {
if (surface_id == root_surface_id_) {
root_surface_damaged_ = true;
+ expecting_root_surface_damage_because_of_resize_ = false;
} else {
child_surface_ids_damaged_.insert(surface_id);
@@ -113,7 +120,6 @@ void DisplayScheduler::DrawAndSwap() {
child_surface_ids_damaged_.clear();
needs_draw_ = false;
- entire_display_damaged_ = false;
all_active_child_surfaces_ready_to_draw_ =
child_surface_ids_to_expect_damage_from_.empty();
@@ -150,7 +156,8 @@ base::TimeTicks DisplayScheduler::DesiredBeginFrameDeadlineTime() {
if (pending_swaps_ >= max_pending_swaps_) {
TRACE_EVENT_INSTANT0("cc", "Swap throttled", TRACE_EVENT_SCOPE_THREAD);
- return current_begin_frame_args_.deadline;
+ return current_begin_frame_args_.frame_time +
+ current_begin_frame_args_.interval;
}
if (!needs_draw_) {
@@ -166,13 +173,6 @@ base::TimeTicks DisplayScheduler::DesiredBeginFrameDeadlineTime() {
current_begin_frame_args_.interval;
}
- // TODO(mithro): Be smarter about resize deadlines.
- if (entire_display_damaged_) {
- TRACE_EVENT_INSTANT0("cc", "Entire display damaged",
- TRACE_EVENT_SCOPE_THREAD);
- return base::TimeTicks();
- }
-
bool root_ready_to_draw =
!expect_damage_from_root_surface_ || root_surface_damaged_;
@@ -182,6 +182,14 @@ base::TimeTicks DisplayScheduler::DesiredBeginFrameDeadlineTime() {
return base::TimeTicks();
}
+ // TODO(mithro): Be smarter about resize deadlines.
+ if (expecting_root_surface_damage_because_of_resize_) {
+ TRACE_EVENT_INSTANT0("cc", "Entire display damaged",
+ TRACE_EVENT_SCOPE_THREAD);
+ return current_begin_frame_args_.frame_time +
+ current_begin_frame_args_.interval;
+ }
+
// Use an earlier deadline if we are only waiting for the root surface
// in case our expect_damage_from_root_surface heuristic is incorrect.
// TODO(mithro): Replace this with SetNeedsBeginFrame and SwapAbort
diff --git a/chromium/cc/surfaces/display_scheduler.h b/chromium/cc/surfaces/display_scheduler.h
index bc509c7b1ca..4ffc6ea8d56 100644
--- a/chromium/cc/surfaces/display_scheduler.h
+++ b/chromium/cc/surfaces/display_scheduler.h
@@ -36,7 +36,8 @@ class CC_SURFACES_EXPORT DisplayScheduler : public BeginFrameObserverBase {
void SetRootSurfaceResourcesLocked(bool locked);
void ForceImmediateSwapIfPossible();
- virtual void EntireDisplayDamaged(SurfaceId root_surface_id);
+ virtual void DisplayResized();
+ virtual void SetNewRootSurface(SurfaceId root_surface_id);
virtual void SurfaceDamaged(SurfaceId surface_id);
virtual void DidSwapBuffers();
@@ -68,7 +69,7 @@ class CC_SURFACES_EXPORT DisplayScheduler : public BeginFrameObserverBase {
bool inside_begin_frame_deadline_interval_;
bool needs_draw_;
- bool entire_display_damaged_;
+ bool expecting_root_surface_damage_because_of_resize_;
bool all_active_child_surfaces_ready_to_draw_;
int pending_swaps_;
diff --git a/chromium/cc/surfaces/display_scheduler_unittest.cc b/chromium/cc/surfaces/display_scheduler_unittest.cc
index 43a0c9a5cba..0f2725dbc71 100644
--- a/chromium/cc/surfaces/display_scheduler_unittest.cc
+++ b/chromium/cc/surfaces/display_scheduler_unittest.cc
@@ -107,14 +107,73 @@ class DisplaySchedulerTest : public testing::Test {
scoped_ptr<TestDisplayScheduler> scheduler_;
};
-TEST_F(DisplaySchedulerTest, EntireDisplayDamagedDrawsImmediately) {
+TEST_F(DisplaySchedulerTest, ResizeHasLateDeadlineUntilNewRootSurface) {
+ SurfaceId root_surface_id1(1);
+ SurfaceId root_surface_id2(2);
+ SurfaceId sid1(3);
+ base::TimeTicks late_deadline;
+
+ // Go trough an initial BeginFrame cycle with the root surface.
+ BeginFrameForTest();
+ scheduler_->SetNewRootSurface(root_surface_id1);
+ scheduler_->BeginFrameDeadlineForTest();
+
+ // Resize on the next begin frame cycle should cause the deadline to wait
+ // for a new root surface.
+ late_deadline = now_src().NowTicks() + BeginFrameArgs::DefaultInterval();
+ BeginFrameForTest();
+ scheduler_->SurfaceDamaged(sid1);
+ EXPECT_GT(late_deadline, scheduler_->DesiredBeginFrameDeadlineTimeForTest());
+ scheduler_->DisplayResized();
+ EXPECT_EQ(late_deadline, scheduler_->DesiredBeginFrameDeadlineTimeForTest());
+ scheduler_->SetNewRootSurface(root_surface_id2);
+ EXPECT_GE(now_src().NowTicks(),
+ scheduler_->DesiredBeginFrameDeadlineTimeForTest());
+ scheduler_->BeginFrameDeadlineForTest();
+
+ // Verify deadline goes back to normal after resize.
+ late_deadline = now_src().NowTicks() + BeginFrameArgs::DefaultInterval();
+ BeginFrameForTest();
+ scheduler_->SurfaceDamaged(sid1);
+ EXPECT_GT(late_deadline, scheduler_->DesiredBeginFrameDeadlineTimeForTest());
+ scheduler_->SurfaceDamaged(root_surface_id2);
+ EXPECT_GE(now_src().NowTicks(),
+ scheduler_->DesiredBeginFrameDeadlineTimeForTest());
+ scheduler_->BeginFrameDeadlineForTest();
+}
+
+TEST_F(DisplaySchedulerTest, ResizeHasLateDeadlineUntilDamagedSurface) {
SurfaceId root_surface_id(1);
+ SurfaceId sid1(2);
+ base::TimeTicks late_deadline;
+
+ // Go trough an initial BeginFrame cycle with the root surface.
BeginFrameForTest();
- EXPECT_LT(now_src().NowTicks(),
+ scheduler_->SetNewRootSurface(root_surface_id);
+ scheduler_->BeginFrameDeadlineForTest();
+
+ // Resize on the next begin frame cycle should cause the deadline to wait
+ // for a new root surface.
+ late_deadline = now_src().NowTicks() + BeginFrameArgs::DefaultInterval();
+ BeginFrameForTest();
+ scheduler_->SurfaceDamaged(sid1);
+ EXPECT_GT(late_deadline, scheduler_->DesiredBeginFrameDeadlineTimeForTest());
+ scheduler_->DisplayResized();
+ EXPECT_EQ(late_deadline, scheduler_->DesiredBeginFrameDeadlineTimeForTest());
+ scheduler_->SurfaceDamaged(root_surface_id);
+ EXPECT_GE(now_src().NowTicks(),
scheduler_->DesiredBeginFrameDeadlineTimeForTest());
- scheduler_->EntireDisplayDamaged(root_surface_id);
+ scheduler_->BeginFrameDeadlineForTest();
+
+ // Verify deadline goes back to normal after resize.
+ late_deadline = now_src().NowTicks() + BeginFrameArgs::DefaultInterval();
+ BeginFrameForTest();
+ scheduler_->SurfaceDamaged(sid1);
+ EXPECT_GT(late_deadline, scheduler_->DesiredBeginFrameDeadlineTimeForTest());
+ scheduler_->SurfaceDamaged(root_surface_id);
EXPECT_GE(now_src().NowTicks(),
scheduler_->DesiredBeginFrameDeadlineTimeForTest());
+ scheduler_->BeginFrameDeadlineForTest();
}
TEST_F(DisplaySchedulerTest, SurfaceDamaged) {
@@ -123,7 +182,7 @@ TEST_F(DisplaySchedulerTest, SurfaceDamaged) {
SurfaceId sid2(2);
// Set the root surface
- scheduler_->EntireDisplayDamaged(root_surface_id);
+ scheduler_->SetNewRootSurface(root_surface_id);
// Get scheduler to detect surface 1 as active by drawing
// two frames in a row with damage from surface 1.
@@ -208,6 +267,25 @@ TEST_F(DisplaySchedulerTest, OutputSurfaceLost) {
EXPECT_EQ(1, client_->draw_and_swap_count());
}
+TEST_F(DisplaySchedulerTest, ResizeCausesSwap) {
+ SurfaceId sid1(1);
+
+ // DrawAndSwap normally.
+ BeginFrameForTest();
+ EXPECT_LT(now_src().NowTicks(),
+ scheduler_->DesiredBeginFrameDeadlineTimeForTest());
+ EXPECT_EQ(0, client_->draw_and_swap_count());
+ scheduler_->SurfaceDamaged(sid1);
+ scheduler_->BeginFrameDeadlineForTest();
+ EXPECT_EQ(1, client_->draw_and_swap_count());
+
+ scheduler_->DisplayResized();
+ BeginFrameForTest();
+ // DisplayResized should trigger a swap to happen.
+ scheduler_->BeginFrameDeadlineForTest();
+ EXPECT_EQ(2, client_->draw_and_swap_count());
+}
+
TEST_F(DisplaySchedulerTest, RootSurfaceResourcesLocked) {
SurfaceId sid1(1);
base::TimeTicks late_deadline;
@@ -252,7 +330,6 @@ TEST_F(DisplaySchedulerTest, RootSurfaceResourcesLocked) {
TEST_F(DisplaySchedulerTest, DidSwapBuffers) {
SurfaceId sid1(1);
SurfaceId sid2(2);
- base::TimeTicks expected_deadline;
// Get scheduler to detect surface 1 and 2 as active.
BeginFrameForTest();
@@ -275,16 +352,14 @@ TEST_F(DisplaySchedulerTest, DidSwapBuffers) {
EXPECT_EQ(3, client_->draw_and_swap_count());
scheduler_->DidSwapBuffers();
- // Deadline triggers normally when swap throttled.
- expected_deadline =
- fake_begin_frame_source_.TestLastUsedBeginFrameArgs().deadline -
- BeginFrameArgs::DefaultEstimatedParentDrawTime();
+ // Deadline triggers late when swap throttled.
+ base::TimeTicks late_deadline =
+ now_src().NowTicks() + BeginFrameArgs::DefaultInterval();
BeginFrameForTest();
// Damage surface 1, but not surface 2 so we avoid triggering deadline
// early because all surfaces are ready.
scheduler_->SurfaceDamaged(sid1);
- EXPECT_EQ(expected_deadline,
- scheduler_->DesiredBeginFrameDeadlineTimeForTest());
+ EXPECT_EQ(late_deadline, scheduler_->DesiredBeginFrameDeadlineTimeForTest());
// Don't draw and swap in deadline while swap throttled.
EXPECT_EQ(3, client_->draw_and_swap_count());
@@ -293,7 +368,7 @@ TEST_F(DisplaySchedulerTest, DidSwapBuffers) {
// Deadline triggers normally once not swap throttled.
// Damage from previous BeginFrame should cary over, so don't damage again.
- expected_deadline =
+ base::TimeTicks expected_deadline =
fake_begin_frame_source_.TestLastUsedBeginFrameArgs().deadline -
BeginFrameArgs::DefaultEstimatedParentDrawTime();
scheduler_->DidSwapBuffersComplete();
@@ -330,7 +405,10 @@ TEST_F(DisplaySchedulerTest, ScheduleBeginFrameDeadline) {
scheduler_->DidSwapBuffersComplete();
EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count());
- scheduler_->EntireDisplayDamaged(root_surface_id);
+ scheduler_->DisplayResized();
+ EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count());
+
+ scheduler_->SetNewRootSurface(root_surface_id);
EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count());
scheduler_->SurfaceDamaged(sid1);
diff --git a/chromium/cc/surfaces/display_unittest.cc b/chromium/cc/surfaces/display_unittest.cc
index 93ff0f85af1..6058f159b22 100644
--- a/chromium/cc/surfaces/display_unittest.cc
+++ b/chromium/cc/surfaces/display_unittest.cc
@@ -31,10 +31,19 @@ class EmptySurfaceFactoryClient : public SurfaceFactoryClient {
void ReturnResources(const ReturnedResourceArray& resources) override {}
};
+class TestSoftwareOutputDevice : public SoftwareOutputDevice {
+ public:
+ TestSoftwareOutputDevice() {}
+
+ gfx::Rect damage_rect() const { return damage_rect_; }
+ gfx::Size viewport_pixel_size() const { return viewport_pixel_size_; }
+};
+
class DisplayTest : public testing::Test {
public:
DisplayTest()
: factory_(&manager_, &empty_client_),
+ software_output_device_(nullptr),
task_runner_(new base::NullTaskRunner) {}
protected:
@@ -43,27 +52,30 @@ class DisplayTest : public testing::Test {
output_surface_ = FakeOutputSurface::Create3d(
TestContextProvider::Create(context.Pass()));
} else {
- output_surface_ = FakeOutputSurface::CreateSoftware(
- make_scoped_ptr(new SoftwareOutputDevice));
+ scoped_ptr<TestSoftwareOutputDevice> output_device(
+ new TestSoftwareOutputDevice);
+ software_output_device_ = output_device.get();
+ output_surface_ = FakeOutputSurface::CreateSoftware(output_device.Pass());
}
shared_bitmap_manager_.reset(new TestSharedBitmapManager);
output_surface_ptr_ = output_surface_.get();
}
- void SubmitFrame(RenderPassList* pass_list, SurfaceId surface_id) {
+ void SubmitCompositorFrame(RenderPassList* pass_list, SurfaceId surface_id) {
scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
pass_list->swap(frame_data->render_pass_list);
scoped_ptr<CompositorFrame> frame(new CompositorFrame);
frame->delegated_frame_data = frame_data.Pass();
- factory_.SubmitFrame(surface_id, frame.Pass(),
- SurfaceFactory::DrawCallback());
+ factory_.SubmitCompositorFrame(surface_id, frame.Pass(),
+ SurfaceFactory::DrawCallback());
}
SurfaceManager manager_;
EmptySurfaceFactoryClient empty_client_;
SurfaceFactory factory_;
+ TestSoftwareOutputDevice* software_output_device_;
scoped_ptr<FakeOutputSurface> output_surface_;
FakeOutputSurface* output_surface_ptr_;
FakeBeginFrameSource fake_begin_frame_source_;
@@ -89,13 +101,16 @@ class TestDisplayScheduler : public DisplayScheduler {
base::NullTaskRunner* task_runner)
: DisplayScheduler(client, begin_frame_source, task_runner, 1),
damaged(false),
- entire_display_damaged(false),
+ display_resized_(false),
+ has_new_root_surface(false),
swapped(false) {}
~TestDisplayScheduler() override {}
- void EntireDisplayDamaged(SurfaceId root_surface_id) override {
- entire_display_damaged = true;
+ void DisplayResized() override { display_resized_ = true; }
+
+ void SetNewRootSurface(SurfaceId root_surface_id) override {
+ has_new_root_surface = true;
}
void SurfaceDamaged(SurfaceId surface_id) override {
@@ -107,11 +122,13 @@ class TestDisplayScheduler : public DisplayScheduler {
void ResetDamageForTest() {
damaged = false;
- entire_display_damaged = false;
+ display_resized_ = false;
+ has_new_root_surface = false;
}
bool damaged;
- bool entire_display_damaged;
+ bool display_resized_;
+ bool has_new_root_surface;
bool swapped;
};
@@ -135,15 +152,17 @@ TEST_F(DisplayTest, DisplayDamaged) {
SurfaceId surface_id(7u);
EXPECT_FALSE(scheduler.damaged);
- EXPECT_FALSE(scheduler.entire_display_damaged);
+ EXPECT_FALSE(scheduler.has_new_root_surface);
display.SetSurfaceId(surface_id, 1.f);
EXPECT_FALSE(scheduler.damaged);
- EXPECT_TRUE(scheduler.entire_display_damaged);
+ EXPECT_FALSE(scheduler.display_resized_);
+ EXPECT_TRUE(scheduler.has_new_root_surface);
scheduler.ResetDamageForTest();
display.Resize(gfx::Size(100, 100));
EXPECT_FALSE(scheduler.damaged);
- EXPECT_TRUE(scheduler.entire_display_damaged);
+ EXPECT_TRUE(scheduler.display_resized_);
+ EXPECT_FALSE(scheduler.has_new_root_surface);
factory_.Create(surface_id);
@@ -156,21 +175,19 @@ TEST_F(DisplayTest, DisplayDamaged) {
pass_list.push_back(pass.Pass());
scheduler.ResetDamageForTest();
- SubmitFrame(&pass_list, surface_id);
+ SubmitCompositorFrame(&pass_list, surface_id);
EXPECT_TRUE(scheduler.damaged);
- EXPECT_FALSE(scheduler.entire_display_damaged);
+ EXPECT_FALSE(scheduler.display_resized_);
+ EXPECT_FALSE(scheduler.has_new_root_surface);
EXPECT_FALSE(scheduler.swapped);
EXPECT_EQ(0u, output_surface_ptr_->num_sent_frames());
display.DrawAndSwap();
EXPECT_TRUE(scheduler.swapped);
EXPECT_EQ(1u, output_surface_ptr_->num_sent_frames());
- SoftwareFrameData* software_data =
- output_surface_ptr_->last_sent_frame().software_frame_data.get();
- ASSERT_NE(nullptr, software_data);
- EXPECT_EQ(gfx::Size(100, 100).ToString(), software_data->size.ToString());
- EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
- software_data->damage_rect.ToString());
+ EXPECT_EQ(gfx::Size(100, 100),
+ software_output_device_->viewport_pixel_size());
+ EXPECT_EQ(gfx::Rect(0, 0, 100, 100), software_output_device_->damage_rect());
{
// Only damaged portion should be swapped.
@@ -181,20 +198,18 @@ TEST_F(DisplayTest, DisplayDamaged) {
pass_list.push_back(pass.Pass());
scheduler.ResetDamageForTest();
- SubmitFrame(&pass_list, surface_id);
+ SubmitCompositorFrame(&pass_list, surface_id);
EXPECT_TRUE(scheduler.damaged);
- EXPECT_FALSE(scheduler.entire_display_damaged);
+ EXPECT_FALSE(scheduler.display_resized_);
+ EXPECT_FALSE(scheduler.has_new_root_surface);
scheduler.swapped = false;
display.DrawAndSwap();
EXPECT_TRUE(scheduler.swapped);
EXPECT_EQ(2u, output_surface_ptr_->num_sent_frames());
- software_data =
- output_surface_ptr_->last_sent_frame().software_frame_data.get();
- ASSERT_NE(nullptr, software_data);
- EXPECT_EQ(gfx::Size(100, 100).ToString(), software_data->size.ToString());
- EXPECT_EQ(gfx::Rect(10, 10, 1, 1).ToString(),
- software_data->damage_rect.ToString());
+ EXPECT_EQ(gfx::Size(100, 100),
+ software_output_device_->viewport_pixel_size());
+ EXPECT_EQ(gfx::Rect(10, 10, 1, 1), software_output_device_->damage_rect());
}
{
@@ -206,9 +221,10 @@ TEST_F(DisplayTest, DisplayDamaged) {
pass_list.push_back(pass.Pass());
scheduler.ResetDamageForTest();
- SubmitFrame(&pass_list, surface_id);
+ SubmitCompositorFrame(&pass_list, surface_id);
EXPECT_TRUE(scheduler.damaged);
- EXPECT_FALSE(scheduler.entire_display_damaged);
+ EXPECT_FALSE(scheduler.display_resized_);
+ EXPECT_FALSE(scheduler.has_new_root_surface);
scheduler.swapped = false;
display.DrawAndSwap();
@@ -225,9 +241,10 @@ TEST_F(DisplayTest, DisplayDamaged) {
pass_list.push_back(pass.Pass());
scheduler.ResetDamageForTest();
- SubmitFrame(&pass_list, surface_id);
+ SubmitCompositorFrame(&pass_list, surface_id);
EXPECT_TRUE(scheduler.damaged);
- EXPECT_FALSE(scheduler.entire_display_damaged);
+ EXPECT_FALSE(scheduler.display_resized_);
+ EXPECT_FALSE(scheduler.has_new_root_surface);
scheduler.swapped = false;
display.DrawAndSwap();
@@ -236,6 +253,28 @@ TEST_F(DisplayTest, DisplayDamaged) {
}
{
+ // Previous frame wasn't swapped, so next swap should have full damage.
+ pass = RenderPass::Create();
+ pass->output_rect = gfx::Rect(0, 0, 100, 100);
+ pass->damage_rect = gfx::Rect(10, 10, 0, 0);
+ pass->id = RenderPassId(1, 1);
+
+ pass_list.push_back(pass.Pass());
+ scheduler.ResetDamageForTest();
+ SubmitCompositorFrame(&pass_list, surface_id);
+ EXPECT_TRUE(scheduler.damaged);
+ EXPECT_FALSE(scheduler.display_resized_);
+ EXPECT_FALSE(scheduler.has_new_root_surface);
+
+ scheduler.swapped = false;
+ display.DrawAndSwap();
+ EXPECT_TRUE(scheduler.swapped);
+ EXPECT_EQ(3u, output_surface_ptr_->num_sent_frames());
+ EXPECT_EQ(gfx::Rect(0, 0, 100, 100),
+ software_output_device_->damage_rect());
+ }
+
+ {
// Pass has copy output request so should be swapped.
pass = RenderPass::Create();
pass->output_rect = gfx::Rect(0, 0, 100, 100);
@@ -247,14 +286,15 @@ TEST_F(DisplayTest, DisplayDamaged) {
pass_list.push_back(pass.Pass());
scheduler.ResetDamageForTest();
- SubmitFrame(&pass_list, surface_id);
+ SubmitCompositorFrame(&pass_list, surface_id);
EXPECT_TRUE(scheduler.damaged);
- EXPECT_FALSE(scheduler.entire_display_damaged);
+ EXPECT_FALSE(scheduler.display_resized_);
+ EXPECT_FALSE(scheduler.has_new_root_surface);
scheduler.swapped = false;
display.DrawAndSwap();
EXPECT_TRUE(scheduler.swapped);
- EXPECT_EQ(3u, output_surface_ptr_->num_sent_frames());
+ EXPECT_EQ(4u, output_surface_ptr_->num_sent_frames());
EXPECT_TRUE(copy_called);
}
@@ -274,15 +314,16 @@ TEST_F(DisplayTest, DisplayDamaged) {
frame->delegated_frame_data = frame_data.Pass();
frame->metadata.latency_info.push_back(ui::LatencyInfo());
- factory_.SubmitFrame(surface_id, frame.Pass(),
- SurfaceFactory::DrawCallback());
+ factory_.SubmitCompositorFrame(surface_id, frame.Pass(),
+ SurfaceFactory::DrawCallback());
EXPECT_TRUE(scheduler.damaged);
- EXPECT_FALSE(scheduler.entire_display_damaged);
+ EXPECT_FALSE(scheduler.display_resized_);
+ EXPECT_FALSE(scheduler.has_new_root_surface);
scheduler.swapped = false;
display.DrawAndSwap();
EXPECT_TRUE(scheduler.swapped);
- EXPECT_EQ(4u, output_surface_ptr_->num_sent_frames());
+ EXPECT_EQ(5u, output_surface_ptr_->num_sent_frames());
}
// Resize should cause a swap if no frame was swapped at the previous size.
@@ -290,7 +331,7 @@ TEST_F(DisplayTest, DisplayDamaged) {
scheduler.swapped = false;
display.Resize(gfx::Size(200, 200));
EXPECT_FALSE(scheduler.swapped);
- EXPECT_EQ(4u, output_surface_ptr_->num_sent_frames());
+ EXPECT_EQ(5u, output_surface_ptr_->num_sent_frames());
pass = RenderPass::Create();
pass->output_rect = gfx::Rect(0, 0, 200, 200);
@@ -305,15 +346,16 @@ TEST_F(DisplayTest, DisplayDamaged) {
scoped_ptr<CompositorFrame> frame(new CompositorFrame);
frame->delegated_frame_data = frame_data.Pass();
- factory_.SubmitFrame(surface_id, frame.Pass(),
- SurfaceFactory::DrawCallback());
+ factory_.SubmitCompositorFrame(surface_id, frame.Pass(),
+ SurfaceFactory::DrawCallback());
EXPECT_TRUE(scheduler.damaged);
- EXPECT_FALSE(scheduler.entire_display_damaged);
+ EXPECT_FALSE(scheduler.display_resized_);
+ EXPECT_FALSE(scheduler.has_new_root_surface);
scheduler.swapped = false;
display.Resize(gfx::Size(100, 100));
EXPECT_TRUE(scheduler.swapped);
- EXPECT_EQ(5u, output_surface_ptr_->num_sent_frames());
+ EXPECT_EQ(6u, output_surface_ptr_->num_sent_frames());
}
factory_.Destroy(surface_id);
@@ -355,7 +397,7 @@ TEST_F(DisplayTest, Finish) {
pass->id = RenderPassId(1, 1);
pass_list.push_back(pass.Pass());
- SubmitFrame(&pass_list, surface_id);
+ SubmitCompositorFrame(&pass_list, surface_id);
}
display.DrawAndSwap();
@@ -381,7 +423,7 @@ TEST_F(DisplayTest, Finish) {
pass->id = RenderPassId(1, 1);
pass_list.push_back(pass.Pass());
- SubmitFrame(&pass_list, surface_id);
+ SubmitCompositorFrame(&pass_list, surface_id);
}
display.DrawAndSwap();
diff --git a/chromium/cc/surfaces/onscreen_display_client.cc b/chromium/cc/surfaces/onscreen_display_client.cc
index 2bd58fe4ca1..29a2a7a8ab2 100644
--- a/chromium/cc/surfaces/onscreen_display_client.cc
+++ b/chromium/cc/surfaces/onscreen_display_client.cc
@@ -29,7 +29,7 @@ OnscreenDisplayClient::OnscreenDisplayClient(
settings)),
task_runner_(task_runner),
output_surface_lost_(false),
- disable_gpu_vsync_(settings.disable_gpu_vsync) {
+ disable_display_vsync_(settings.disable_display_vsync) {
}
OnscreenDisplayClient::~OnscreenDisplayClient() {
@@ -42,7 +42,7 @@ bool OnscreenDisplayClient::Initialize() {
max_frames_pending = OutputSurface::DEFAULT_MAX_FRAMES_PENDING;
BeginFrameSource* frame_source;
- if (disable_gpu_vsync_) {
+ if (disable_display_vsync_) {
unthrottled_frame_source_ =
BackToBackBeginFrameSource::Create(task_runner_.get());
frame_source = unthrottled_frame_source_.get();
diff --git a/chromium/cc/surfaces/onscreen_display_client.h b/chromium/cc/surfaces/onscreen_display_client.h
index c2f69f1bf2c..4c4245d4161 100644
--- a/chromium/cc/surfaces/onscreen_display_client.h
+++ b/chromium/cc/surfaces/onscreen_display_client.h
@@ -60,7 +60,7 @@ class CC_SURFACES_EXPORT OnscreenDisplayClient
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
SurfaceDisplayOutputSurface* surface_display_output_surface_;
bool output_surface_lost_;
- bool disable_gpu_vsync_;
+ bool disable_display_vsync_;
private:
DISALLOW_COPY_AND_ASSIGN(OnscreenDisplayClient);
diff --git a/chromium/cc/surfaces/surface.h b/chromium/cc/surfaces/surface.h
index d9099f3122b..8ef332ecb79 100644
--- a/chromium/cc/surfaces/surface.h
+++ b/chromium/cc/surfaces/surface.h
@@ -23,7 +23,7 @@
#include "ui/gfx/geometry/size.h"
namespace ui {
-struct LatencyInfo;
+class LatencyInfo;
}
namespace cc {
diff --git a/chromium/cc/surfaces/surface_aggregator.cc b/chromium/cc/surfaces/surface_aggregator.cc
index ddfac7670b4..69618ba8b4c 100644
--- a/chromium/cc/surfaces/surface_aggregator.cc
+++ b/chromium/cc/surfaces/surface_aggregator.cc
@@ -41,8 +41,12 @@ void MoveMatchingRequests(
} // namespace
SurfaceAggregator::SurfaceAggregator(SurfaceManager* manager,
- ResourceProvider* provider)
- : manager_(manager), provider_(provider), next_render_pass_id_(1) {
+ ResourceProvider* provider,
+ bool aggregate_only_damaged)
+ : manager_(manager),
+ provider_(provider),
+ next_render_pass_id_(1),
+ aggregate_only_damaged_(aggregate_only_damaged) {
DCHECK(manager_);
}
@@ -154,11 +158,8 @@ void SurfaceAggregator::HandleSurfaceQuad(
if (referenced_surfaces_.count(surface_id))
return;
Surface* surface = manager_->GetSurfaceForId(surface_id);
- if (!surface) {
- contained_surfaces_[surface_id] = 0;
+ if (!surface)
return;
- }
- contained_surfaces_[surface_id] = surface->frame_index();
const CompositorFrame* frame = surface->GetEligibleFrame();
if (!frame)
return;
@@ -251,11 +252,10 @@ void SurfaceAggregator::HandleSurfaceQuad(
} else {
RenderPassId remapped_pass_id = RemapPassId(last_pass.id, surface_id);
- CopySharedQuadState(surface_quad->shared_quad_state, target_transform,
- clip_rect, dest_pass);
-
SharedQuadState* shared_quad_state =
- dest_pass->shared_quad_state_list.back();
+ CopySharedQuadState(surface_quad->shared_quad_state, target_transform,
+ clip_rect, dest_pass);
+
RenderPassDrawQuad* quad =
dest_pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
quad->SetNew(shared_quad_state,
@@ -270,11 +270,10 @@ void SurfaceAggregator::HandleSurfaceQuad(
FilterOperations());
}
-
referenced_surfaces_.erase(it);
}
-void SurfaceAggregator::CopySharedQuadState(
+SharedQuadState* SurfaceAggregator::CopySharedQuadState(
const SharedQuadState* source_sqs,
const gfx::Transform& target_transform,
const ClipData& clip_rect,
@@ -296,6 +295,21 @@ void SurfaceAggregator::CopySharedQuadState(
target_transform);
copy_shared_quad_state->is_clipped = new_clip_rect.is_clipped;
copy_shared_quad_state->clip_rect = new_clip_rect.rect;
+ return copy_shared_quad_state;
+}
+
+static gfx::Rect CalculateQuadSpaceDamageRect(
+ const gfx::Transform& quad_to_target_transform,
+ const gfx::Transform& target_to_root_transform,
+ const gfx::Rect& root_damage_rect) {
+ gfx::Transform quad_to_root_transform(target_to_root_transform,
+ quad_to_target_transform);
+ gfx::Transform inverse_transform(gfx::Transform::kSkipInitialization);
+ bool inverse_valid = quad_to_root_transform.GetInverse(&inverse_transform);
+ DCHECK(inverse_valid);
+
+ return MathUtil::ProjectEnclosingClippedRect(inverse_transform,
+ root_damage_rect);
}
void SurfaceAggregator::CopyQuadsToPass(
@@ -306,26 +320,65 @@ void SurfaceAggregator::CopyQuadsToPass(
const ClipData& clip_rect,
RenderPass* dest_pass,
SurfaceId surface_id) {
- const SharedQuadState* last_copied_source_shared_quad_state = NULL;
-
+ const SharedQuadState* last_copied_source_shared_quad_state = nullptr;
+ const SharedQuadState* dest_shared_quad_state = nullptr;
+ // If the current frame has copy requests then aggregate the entire
+ // thing, as otherwise parts of the copy requests may be ignored.
+ const bool ignore_undamaged = aggregate_only_damaged_ && !has_copy_requests_;
+ // Damage rect in the quad space of the current shared quad state.
+ // TODO(jbauman): This rect may contain unnecessary area if
+ // transform isn't axis-aligned.
+ gfx::Rect damage_rect_in_quad_space;
+
+#if DCHECK_IS_ON()
+ // If quads have come in with SharedQuadState out of order, or when quads have
+ // invalid SharedQuadState pointer, it should DCHECK.
SharedQuadStateList::ConstIterator sqs_iter =
source_shared_quad_state_list.begin();
for (const auto& quad : source_quad_list) {
- while (quad->shared_quad_state != *sqs_iter) {
+ while (sqs_iter != source_shared_quad_state_list.end() &&
+ quad->shared_quad_state != *sqs_iter) {
++sqs_iter;
- DCHECK(sqs_iter != source_shared_quad_state_list.end());
}
- DCHECK_EQ(quad->shared_quad_state, *sqs_iter);
+ DCHECK(sqs_iter != source_shared_quad_state_list.end());
+ }
+#endif
+ for (const auto& quad : source_quad_list) {
if (quad->material == DrawQuad::SURFACE_CONTENT) {
const SurfaceDrawQuad* surface_quad = SurfaceDrawQuad::MaterialCast(quad);
+ // HandleSurfaceQuad may add other shared quad state, so reset the
+ // current data.
+ last_copied_source_shared_quad_state = nullptr;
+
+ if (ignore_undamaged) {
+ gfx::Transform quad_to_target_transform(
+ target_transform,
+ quad->shared_quad_state->quad_to_target_transform);
+ damage_rect_in_quad_space = CalculateQuadSpaceDamageRect(
+ quad_to_target_transform, dest_pass->transform_to_root_target,
+ root_damage_rect_);
+ if (!damage_rect_in_quad_space.Intersects(quad->visible_rect))
+ continue;
+ }
HandleSurfaceQuad(surface_quad, target_transform, clip_rect, dest_pass);
} else {
if (quad->shared_quad_state != last_copied_source_shared_quad_state) {
- CopySharedQuadState(quad->shared_quad_state, target_transform,
- clip_rect, dest_pass);
+ dest_shared_quad_state = CopySharedQuadState(
+ quad->shared_quad_state, target_transform, clip_rect, dest_pass);
last_copied_source_shared_quad_state = quad->shared_quad_state;
+ if (aggregate_only_damaged_ && !has_copy_requests_) {
+ damage_rect_in_quad_space = CalculateQuadSpaceDamageRect(
+ dest_shared_quad_state->quad_to_target_transform,
+ dest_pass->transform_to_root_target, root_damage_rect_);
+ }
}
+
+ if (ignore_undamaged) {
+ if (!damage_rect_in_quad_space.Intersects(quad->visible_rect))
+ continue;
+ }
+
DrawQuad* dest_quad;
if (quad->material == DrawQuad::RENDER_PASS) {
const RenderPassDrawQuad* pass_quad =
@@ -335,11 +388,10 @@ void SurfaceAggregator::CopyQuadsToPass(
RemapPassId(original_pass_id, surface_id);
dest_quad = dest_pass->CopyFromAndAppendRenderPassDrawQuad(
- pass_quad, dest_pass->shared_quad_state_list.back(),
- remapped_pass_id);
+ pass_quad, dest_shared_quad_state, remapped_pass_id);
} else {
- dest_quad = dest_pass->CopyFromAndAppendDrawQuad(
- quad, dest_pass->shared_quad_state_list.back());
+ dest_quad =
+ dest_pass->CopyFromAndAppendDrawQuad(quad, dest_shared_quad_state);
}
if (!child_to_parent_map.empty()) {
for (ResourceId& resource_id : dest_quad->resources) {
@@ -415,15 +467,18 @@ void SurfaceAggregator::RemoveUnreferencedChildren() {
}
}
-// Validate the resources of the current surface and its descendants, and
-// calculate their combined damage rect.
-gfx::Rect SurfaceAggregator::ValidateAndCalculateDamageRect(
- SurfaceId surface_id) {
+// Walk the Surface tree from surface_id. Validate the resources of the current
+// surface and its descendants, check if there are any copy requests, and
+// return the combined damage rect.
+gfx::Rect SurfaceAggregator::PrewalkTree(SurfaceId surface_id) {
if (referenced_surfaces_.count(surface_id))
return gfx::Rect();
Surface* surface = manager_->GetSurfaceForId(surface_id);
- if (!surface)
+ if (!surface) {
+ contained_surfaces_[surface_id] = 0;
return gfx::Rect();
+ }
+ contained_surfaces_[surface_id] = surface->frame_index();
const CompositorFrame* surface_frame = surface->GetEligibleFrame();
if (!surface_frame)
return gfx::Rect();
@@ -467,8 +522,8 @@ gfx::Rect SurfaceAggregator::ValidateAndCalculateDamageRect(
const SurfaceDrawQuad* surface_quad =
SurfaceDrawQuad::MaterialCast(quad);
gfx::Transform target_to_surface_transform(
- surface_quad->shared_quad_state->quad_to_target_transform,
- render_pass->transform_to_root_target);
+ render_pass->transform_to_root_target,
+ surface_quad->shared_quad_state->quad_to_target_transform);
child_surfaces.push_back(std::make_pair(surface_quad->surface_id,
target_to_surface_transform));
}
@@ -492,11 +547,14 @@ gfx::Rect SurfaceAggregator::ValidateAndCalculateDamageRect(
if (provider_)
provider_->DeclareUsedResourcesFromChild(child_id, referenced_resources);
+ for (const auto& render_pass : frame_data->render_pass_list)
+ has_copy_requests_ |= !render_pass->copy_requests.empty();
+
gfx::Rect damage_rect;
if (!frame_data->render_pass_list.empty()) {
+ RenderPass* last_pass = frame_data->render_pass_list.back();
damage_rect =
- DamageRectForSurface(surface, *frame_data->render_pass_list.back(),
- frame_data->render_pass_list.back()->output_rect);
+ DamageRectForSurface(surface, *last_pass, last_pass->output_rect);
}
// Avoid infinite recursion by adding current surface to
@@ -504,8 +562,7 @@ gfx::Rect SurfaceAggregator::ValidateAndCalculateDamageRect(
SurfaceSet::iterator it =
referenced_surfaces_.insert(surface->surface_id()).first;
for (const auto& surface_info : child_surfaces) {
- gfx::Rect surface_damage =
- ValidateAndCalculateDamageRect(surface_info.first);
+ gfx::Rect surface_damage = PrewalkTree(surface_info.first);
damage_rect.Union(
MathUtil::MapEnclosingClippedRect(surface_info.second, surface_damage));
}
@@ -531,7 +588,8 @@ scoped_ptr<CompositorFrame> SurfaceAggregator::Aggregate(SurfaceId surface_id) {
dest_pass_list_ = &frame->delegated_frame_data->render_pass_list;
valid_surfaces_.clear();
- gfx::Rect damage_rect = ValidateAndCalculateDamageRect(surface_id);
+ has_copy_requests_ = false;
+ root_damage_rect_ = PrewalkTree(surface_id);
SurfaceSet::iterator it = referenced_surfaces_.insert(surface_id).first;
CopyPasses(root_surface_frame->delegated_frame_data.get(), surface);
@@ -541,7 +599,7 @@ scoped_ptr<CompositorFrame> SurfaceAggregator::Aggregate(SurfaceId surface_id) {
if (dest_pass_list_->empty())
return nullptr;
- dest_pass_list_->back()->damage_rect = damage_rect;
+ dest_pass_list_->back()->damage_rect = root_damage_rect_;
dest_pass_list_ = NULL;
RemoveUnreferencedChildren();
diff --git a/chromium/cc/surfaces/surface_aggregator.h b/chromium/cc/surfaces/surface_aggregator.h
index 17ea4c43125..1ff4a45804b 100644
--- a/chromium/cc/surfaces/surface_aggregator.h
+++ b/chromium/cc/surfaces/surface_aggregator.h
@@ -29,7 +29,9 @@ class CC_SURFACES_EXPORT SurfaceAggregator {
public:
typedef base::hash_map<SurfaceId, int> SurfaceIndexMap;
- SurfaceAggregator(SurfaceManager* manager, ResourceProvider* provider);
+ SurfaceAggregator(SurfaceManager* manager,
+ ResourceProvider* provider,
+ bool aggregate_only_damaged);
~SurfaceAggregator();
scoped_ptr<CompositorFrame> Aggregate(SurfaceId surface_id);
@@ -60,10 +62,10 @@ class CC_SURFACES_EXPORT SurfaceAggregator {
const gfx::Transform& target_transform,
const ClipData& clip_rect,
RenderPass* dest_pass);
- void CopySharedQuadState(const SharedQuadState* source_sqs,
- const gfx::Transform& target_transform,
- const ClipData& clip_rect,
- RenderPass* dest_render_pass);
+ SharedQuadState* CopySharedQuadState(const SharedQuadState* source_sqs,
+ const gfx::Transform& target_transform,
+ const ClipData& clip_rect,
+ RenderPass* dest_render_pass);
void CopyQuadsToPass(
const QuadList& source_quad_list,
const SharedQuadStateList& source_shared_quad_state_list,
@@ -72,7 +74,7 @@ class CC_SURFACES_EXPORT SurfaceAggregator {
const ClipData& clip_rect,
RenderPass* dest_pass,
SurfaceId surface_id);
- gfx::Rect ValidateAndCalculateDamageRect(SurfaceId surface_id);
+ gfx::Rect PrewalkTree(SurfaceId surface_id);
void CopyPasses(const DelegatedFrameData* frame_data, Surface* surface);
// Remove Surfaces that were referenced before but aren't currently
@@ -92,6 +94,7 @@ class CC_SURFACES_EXPORT SurfaceAggregator {
RenderPassIdAllocatorMap;
RenderPassIdAllocatorMap render_pass_allocator_map_;
int next_render_pass_id_;
+ const bool aggregate_only_damaged_;
typedef base::hash_map<SurfaceId, int> SurfaceToResourceChildIdMap;
SurfaceToResourceChildIdMap surface_id_to_resource_child_id_;
@@ -116,6 +119,13 @@ class CC_SURFACES_EXPORT SurfaceAggregator {
// This is the pass list for the aggregated frame.
RenderPassList* dest_pass_list_;
+ // The root damage rect of the currently-aggregating frame.
+ gfx::Rect root_damage_rect_;
+
+ // True if the frame that's currently being aggregated has copy requests.
+ // This is valid during Aggregate after PrewalkTree is called.
+ bool has_copy_requests_;
+
// Resource list for the aggregated frame.
TransferableResourceArray* dest_resource_list_;
diff --git a/chromium/cc/surfaces/surface_aggregator_perftest.cc b/chromium/cc/surfaces/surface_aggregator_perftest.cc
index b5fddf51dc6..71589edd7ec 100644
--- a/chromium/cc/surfaces/surface_aggregator_perftest.cc
+++ b/chromium/cc/surfaces/surface_aggregator_perftest.cc
@@ -36,14 +36,16 @@ class SurfaceAggregatorPerfTest : public testing::Test {
resource_provider_ = FakeResourceProvider::Create(
output_surface_.get(), shared_bitmap_manager_.get());
- aggregator_.reset(
- new SurfaceAggregator(&manager_, resource_provider_.get()));
}
void RunTest(int num_surfaces,
int num_textures,
float opacity,
+ bool optimize_damage,
+ bool full_damage,
const std::string& name) {
+ aggregator_.reset(new SurfaceAggregator(&manager_, resource_provider_.get(),
+ optimize_damage));
for (int i = 1; i <= num_surfaces; i++) {
factory_.Create(SurfaceId(i));
scoped_ptr<RenderPass> pass(RenderPass::Create());
@@ -60,7 +62,9 @@ class SurfaceAggregatorPerfTest : public testing::Test {
pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
const gfx::Rect rect(0, 0, 1, 1);
const gfx::Rect opaque_rect;
- const gfx::Rect visible_rect(0, 0, 1, 1);
+ // Half of rects should be visible with partial damage.
+ gfx::Rect visible_rect =
+ j % 2 == 0 ? gfx::Rect(0, 0, 1, 1) : gfx::Rect(1, 1, 1, 1);
bool needs_blending = false;
bool premultiplied_alpha = false;
const gfx::PointF uv_top_left;
@@ -86,20 +90,42 @@ class SurfaceAggregatorPerfTest : public testing::Test {
frame_data->render_pass_list.push_back(pass.Pass());
scoped_ptr<CompositorFrame> frame(new CompositorFrame);
frame->delegated_frame_data = frame_data.Pass();
- factory_.SubmitFrame(SurfaceId(i), frame.Pass(),
- SurfaceFactory::DrawCallback());
+ factory_.SubmitCompositorFrame(SurfaceId(i), frame.Pass(),
+ SurfaceFactory::DrawCallback());
}
+ factory_.Create(SurfaceId(num_surfaces + 1));
timer_.Reset();
do {
+ scoped_ptr<RenderPass> pass(RenderPass::Create());
+ scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
+
+ SharedQuadState* sqs = pass->CreateAndAppendSharedQuadState();
+ SurfaceDrawQuad* surface_quad =
+ pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
+ surface_quad->SetNew(sqs, gfx::Rect(0, 0, 100, 100),
+ gfx::Rect(0, 0, 100, 100), SurfaceId(num_surfaces));
+
+ if (full_damage)
+ pass->damage_rect = gfx::Rect(0, 0, 100, 100);
+ else
+ pass->damage_rect = gfx::Rect(0, 0, 1, 1);
+
+ frame_data->render_pass_list.push_back(pass.Pass());
+ scoped_ptr<CompositorFrame> frame(new CompositorFrame);
+ frame->delegated_frame_data = frame_data.Pass();
+ factory_.SubmitCompositorFrame(SurfaceId(num_surfaces + 1), frame.Pass(),
+ SurfaceFactory::DrawCallback());
+
scoped_ptr<CompositorFrame> aggregated =
- aggregator_->Aggregate(SurfaceId(num_surfaces));
+ aggregator_->Aggregate(SurfaceId(num_surfaces + 1));
timer_.NextLap();
} while (!timer_.HasTimeLimitExpired());
perf_test::PrintResult("aggregator_speed", "", name, timer_.LapsPerSecond(),
"runs/s", true);
+ factory_.Destroy(SurfaceId(num_surfaces + 1));
for (int i = 1; i <= num_surfaces; i++)
factory_.Destroy(SurfaceId(i));
}
@@ -117,15 +143,31 @@ class SurfaceAggregatorPerfTest : public testing::Test {
};
TEST_F(SurfaceAggregatorPerfTest, ManySurfacesOpaque) {
- RunTest(20, 100, 1.f, "many_surfaces_opaque");
+ RunTest(20, 100, 1.f, false, true, "many_surfaces_opaque");
}
TEST_F(SurfaceAggregatorPerfTest, ManySurfacesTransparent) {
- RunTest(20, 100, .5f, "many_surfaces_transparent");
+ RunTest(20, 100, .5f, false, true, "many_surfaces_transparent");
}
TEST_F(SurfaceAggregatorPerfTest, FewSurfaces) {
- RunTest(3, 1000, 1.f, "few_surfaces");
+ RunTest(3, 1000, 1.f, false, true, "few_surfaces");
+}
+
+TEST_F(SurfaceAggregatorPerfTest, ManySurfacesOpaqueDamageCalc) {
+ RunTest(20, 100, 1.f, true, true, "many_surfaces_opaque_damage_calc");
+}
+
+TEST_F(SurfaceAggregatorPerfTest, ManySurfacesTransparentDamageCalc) {
+ RunTest(20, 100, .5f, true, true, "many_surfaces_transparent_damage_calc");
+}
+
+TEST_F(SurfaceAggregatorPerfTest, FewSurfacesDamageCalc) {
+ RunTest(3, 1000, 1.f, true, true, "few_surfaces_damage_calc");
+}
+
+TEST_F(SurfaceAggregatorPerfTest, FewSurfacesAggregateDamaged) {
+ RunTest(3, 1000, 1.f, true, false, "few_surfaces_aggregate_damaged");
}
} // namespace
diff --git a/chromium/cc/surfaces/surface_aggregator_test_helpers.cc b/chromium/cc/surfaces/surface_aggregator_test_helpers.cc
index f7da1a25c84..45b57d0ffe7 100644
--- a/chromium/cc/surfaces/surface_aggregator_test_helpers.cc
+++ b/chromium/cc/surfaces/surface_aggregator_test_helpers.cc
@@ -14,7 +14,6 @@
#include "cc/quads/solid_color_draw_quad.h"
#include "cc/quads/surface_draw_quad.h"
#include "cc/surfaces/surface.h"
-#include "cc/test/render_pass_test_common.h"
#include "cc/test/render_pass_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkXfermode.h"
@@ -22,10 +21,10 @@
namespace cc {
namespace test {
-void AddTestSurfaceQuad(TestRenderPass* pass,
- const gfx::Size& surface_size,
- float opacity,
- SurfaceId surface_id) {
+void AddSurfaceQuad(RenderPass* pass,
+ const gfx::Size& surface_size,
+ float opacity,
+ SurfaceId surface_id) {
gfx::Transform layer_to_target_transform;
gfx::Size layer_bounds = surface_size;
gfx::Rect visible_layer_rect = gfx::Rect(surface_size);
@@ -46,7 +45,7 @@ void AddTestSurfaceQuad(TestRenderPass* pass,
gfx::Rect(surface_size),
surface_id);
}
-void AddTestRenderPassQuad(TestRenderPass* pass, RenderPassId render_pass_id) {
+void AddRenderPassQuad(RenderPass* pass, RenderPassId render_pass_id) {
gfx::Rect output_rect = gfx::Rect(0, 0, 5, 5);
SharedQuadState* shared_state = pass->CreateAndAppendSharedQuadState();
shared_state->SetAll(gfx::Transform(),
@@ -71,16 +70,16 @@ void AddTestRenderPassQuad(TestRenderPass* pass, RenderPassId render_pass_id) {
FilterOperations());
}
-void AddQuadInPass(TestRenderPass* pass, Quad desc) {
+void AddQuadInPass(RenderPass* pass, Quad desc) {
switch (desc.material) {
case DrawQuad::SOLID_COLOR:
AddQuad(pass, gfx::Rect(0, 0, 5, 5), desc.color);
break;
case DrawQuad::SURFACE_CONTENT:
- AddTestSurfaceQuad(pass, gfx::Size(5, 5), desc.opacity, desc.surface_id);
+ AddSurfaceQuad(pass, gfx::Size(5, 5), desc.opacity, desc.surface_id);
break;
case DrawQuad::RENDER_PASS:
- AddTestRenderPassQuad(pass, desc.render_pass_id);
+ AddRenderPassQuad(pass, desc.render_pass_id);
break;
default:
NOTREACHED();
@@ -94,7 +93,7 @@ void AddPasses(RenderPassList* pass_list,
gfx::Transform root_transform;
for (size_t i = 0; i < pass_count; ++i) {
Pass pass = passes[i];
- TestRenderPass* test_pass =
+ RenderPass* test_pass =
AddRenderPass(pass_list, pass.id, output_rect, root_transform);
for (size_t j = 0; j < pass.quad_count; ++j) {
AddQuadInPass(test_pass, pass.quads[j]);
diff --git a/chromium/cc/surfaces/surface_aggregator_unittest.cc b/chromium/cc/surfaces/surface_aggregator_unittest.cc
index e4ade82116e..b2476d9df57 100644
--- a/chromium/cc/surfaces/surface_aggregator_unittest.cc
+++ b/chromium/cc/surfaces/surface_aggregator_unittest.cc
@@ -20,7 +20,6 @@
#include "cc/test/fake_output_surface.h"
#include "cc/test/fake_output_surface_client.h"
#include "cc/test/fake_resource_provider.h"
-#include "cc/test/render_pass_test_common.h"
#include "cc/test/render_pass_test_utils.h"
#include "cc/test/test_shared_bitmap_manager.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -48,8 +47,11 @@ class EmptySurfaceFactoryClient : public SurfaceFactoryClient {
class SurfaceAggregatorTest : public testing::Test {
public:
- SurfaceAggregatorTest()
- : factory_(&manager_, &empty_client_), aggregator_(&manager_, NULL) {}
+ explicit SurfaceAggregatorTest(bool use_damage_rect)
+ : factory_(&manager_, &empty_client_),
+ aggregator_(&manager_, NULL, use_damage_rect) {}
+
+ SurfaceAggregatorTest() : SurfaceAggregatorTest(false) {}
protected:
SurfaceManager manager_;
@@ -68,7 +70,12 @@ TEST_F(SurfaceAggregatorTest, ValidSurfaceNoFrame) {
class SurfaceAggregatorValidSurfaceTest : public SurfaceAggregatorTest {
public:
- SurfaceAggregatorValidSurfaceTest() : allocator_(1u), child_allocator_(2u) {}
+ explicit SurfaceAggregatorValidSurfaceTest(bool use_damage_rect)
+ : SurfaceAggregatorTest(use_damage_rect),
+ allocator_(1u),
+ child_allocator_(2u) {}
+ SurfaceAggregatorValidSurfaceTest()
+ : SurfaceAggregatorValidSurfaceTest(false) {}
void SetUp() override {
SurfaceAggregatorTest::SetUp();
@@ -112,20 +119,23 @@ class SurfaceAggregatorValidSurfaceTest : public SurfaceAggregatorTest {
}
}
- void SubmitFrame(test::Pass* passes,
- size_t pass_count,
- SurfaceId surface_id) {
- RenderPassList pass_list;
- AddPasses(&pass_list, gfx::Rect(SurfaceSize()), passes, pass_count);
-
+ void SubmitPassListAsFrame(SurfaceId surface_id, RenderPassList* pass_list) {
scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
- pass_list.swap(frame_data->render_pass_list);
+ pass_list->swap(frame_data->render_pass_list);
scoped_ptr<CompositorFrame> frame(new CompositorFrame);
frame->delegated_frame_data = frame_data.Pass();
- factory_.SubmitFrame(surface_id, frame.Pass(),
- SurfaceFactory::DrawCallback());
+ factory_.SubmitCompositorFrame(surface_id, frame.Pass(),
+ SurfaceFactory::DrawCallback());
+ }
+
+ void SubmitCompositorFrame(test::Pass* passes,
+ size_t pass_count,
+ SurfaceId surface_id) {
+ RenderPassList pass_list;
+ AddPasses(&pass_list, gfx::Rect(SurfaceSize()), passes, pass_count);
+ SubmitPassListAsFrame(surface_id, &pass_list);
}
void QueuePassAsFrame(scoped_ptr<RenderPass> pass, SurfaceId surface_id) {
@@ -135,8 +145,8 @@ class SurfaceAggregatorValidSurfaceTest : public SurfaceAggregatorTest {
scoped_ptr<CompositorFrame> child_frame(new CompositorFrame);
child_frame->delegated_frame_data = delegated_frame_data.Pass();
- factory_.SubmitFrame(surface_id, child_frame.Pass(),
- SurfaceFactory::DrawCallback());
+ factory_.SubmitCompositorFrame(surface_id, child_frame.Pass(),
+ SurfaceFactory::DrawCallback());
}
protected:
@@ -152,7 +162,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleFrame) {
test::Quad::SolidColorQuad(SK_ColorBLUE)};
test::Pass passes[] = {test::Pass(quads, arraysize(quads))};
- SubmitFrame(passes, arraysize(passes), root_surface_id_);
+ SubmitCompositorFrame(passes, arraysize(passes), root_surface_id_);
SurfaceId ids[] = {root_surface_id_};
AggregateAndVerify(passes, arraysize(passes), ids, arraysize(ids));
@@ -167,12 +177,13 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, OpacityCopied) {
test::Pass embedded_passes[] = {
test::Pass(embedded_quads, arraysize(embedded_quads))};
- SubmitFrame(embedded_passes, arraysize(embedded_passes), embedded_surface_id);
+ SubmitCompositorFrame(embedded_passes, arraysize(embedded_passes),
+ embedded_surface_id);
test::Quad quads[] = {test::Quad::SurfaceQuad(embedded_surface_id, .5f)};
test::Pass passes[] = {test::Pass(quads, arraysize(quads))};
- SubmitFrame(passes, arraysize(passes), root_surface_id_);
+ SubmitCompositorFrame(passes, arraysize(passes), root_surface_id_);
scoped_ptr<CompositorFrame> aggregated_frame =
aggregator_.Aggregate(root_surface_id_);
@@ -207,7 +218,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSimpleFrame) {
test::Pass(quads[0], arraysize(quads[0]), RenderPassId(1, 1)),
test::Pass(quads[1], arraysize(quads[1]), RenderPassId(1, 2))};
- SubmitFrame(passes, arraysize(passes), root_surface_id_);
+ SubmitCompositorFrame(passes, arraysize(passes), root_surface_id_);
SurfaceId ids[] = {root_surface_id_};
AggregateAndVerify(passes, arraysize(passes), ids, arraysize(ids));
@@ -225,14 +236,15 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleSurfaceReference) {
test::Pass embedded_passes[] = {
test::Pass(embedded_quads, arraysize(embedded_quads))};
- SubmitFrame(embedded_passes, arraysize(embedded_passes), embedded_surface_id);
+ SubmitCompositorFrame(embedded_passes, arraysize(embedded_passes),
+ embedded_surface_id);
test::Quad root_quads[] = {test::Quad::SolidColorQuad(SK_ColorWHITE),
test::Quad::SurfaceQuad(embedded_surface_id, 1.f),
test::Quad::SolidColorQuad(SK_ColorBLACK)};
test::Pass root_passes[] = {test::Pass(root_quads, arraysize(root_quads))};
- SubmitFrame(root_passes, arraysize(root_passes), root_surface_id_);
+ SubmitCompositorFrame(root_passes, arraysize(root_passes), root_surface_id_);
test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorWHITE),
test::Quad::SolidColorQuad(SK_ColorGREEN),
@@ -254,7 +266,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, CopyRequest) {
test::Pass embedded_passes[] = {
test::Pass(embedded_quads, arraysize(embedded_quads))};
- SubmitFrame(embedded_passes, arraysize(embedded_passes), embedded_surface_id);
+ SubmitCompositorFrame(embedded_passes, arraysize(embedded_passes),
+ embedded_surface_id);
scoped_ptr<CopyOutputRequest> copy_request(
CopyOutputRequest::CreateEmptyRequest());
CopyOutputRequest* copy_request_ptr = copy_request.get();
@@ -265,7 +278,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, CopyRequest) {
test::Quad::SolidColorQuad(SK_ColorBLACK)};
test::Pass root_passes[] = {test::Pass(root_quads, arraysize(root_quads))};
- SubmitFrame(root_passes, arraysize(root_passes), root_surface_id_);
+ SubmitCompositorFrame(root_passes, arraysize(root_passes), root_surface_id_);
scoped_ptr<CompositorFrame> aggregated_frame =
aggregator_.Aggregate(root_surface_id_);
@@ -311,7 +324,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, RootCopyRequest) {
test::Pass embedded_passes[] = {
test::Pass(embedded_quads, arraysize(embedded_quads))};
- SubmitFrame(embedded_passes, arraysize(embedded_passes), embedded_surface_id);
+ SubmitCompositorFrame(embedded_passes, arraysize(embedded_passes),
+ embedded_surface_id);
scoped_ptr<CopyOutputRequest> copy_request(
CopyOutputRequest::CreateEmptyRequest());
CopyOutputRequest* copy_request_ptr = copy_request.get();
@@ -341,8 +355,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, RootCopyRequest) {
scoped_ptr<CompositorFrame> frame(new CompositorFrame);
frame->delegated_frame_data = frame_data.Pass();
- factory_.SubmitFrame(root_surface_id_, frame.Pass(),
- SurfaceFactory::DrawCallback());
+ factory_.SubmitCompositorFrame(root_surface_id_, frame.Pass(),
+ SurfaceFactory::DrawCallback());
}
scoped_ptr<CompositorFrame> aggregated_frame =
@@ -408,7 +422,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSurfaceReference) {
test::Pass(embedded_quads[1], arraysize(embedded_quads[1]), pass_ids[1]),
test::Pass(embedded_quads[2], arraysize(embedded_quads[2]), pass_ids[2])};
- SubmitFrame(embedded_passes, arraysize(embedded_passes), embedded_surface_id);
+ SubmitCompositorFrame(embedded_passes, arraysize(embedded_passes),
+ embedded_surface_id);
test::Quad root_quads[][2] = {
{test::Quad::SolidColorQuad(5), test::Quad::SolidColorQuad(6)},
@@ -420,7 +435,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSurfaceReference) {
test::Pass(root_quads[1], arraysize(root_quads[1]), pass_ids[1]),
test::Pass(root_quads[2], arraysize(root_quads[2]), pass_ids[2])};
- SubmitFrame(root_passes, arraysize(root_passes), root_surface_id_);
+ SubmitCompositorFrame(root_passes, arraysize(root_passes), root_surface_id_);
scoped_ptr<CompositorFrame> aggregated_frame =
aggregator_.Aggregate(root_surface_id_);
@@ -537,7 +552,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, InvalidSurfaceReference) {
test::Quad::SolidColorQuad(SK_ColorBLUE)};
test::Pass passes[] = {test::Pass(quads, arraysize(quads))};
- SubmitFrame(passes, arraysize(passes), root_surface_id_);
+ SubmitCompositorFrame(passes, arraysize(passes), root_surface_id_);
test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN),
test::Quad::SolidColorQuad(SK_ColorBLUE)};
@@ -558,7 +573,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, ValidSurfaceReferenceWithNoFrame) {
test::Quad::SolidColorQuad(SK_ColorBLUE)};
test::Pass passes[] = {test::Pass(quads, arraysize(quads))};
- SubmitFrame(passes, arraysize(passes), root_surface_id_);
+ SubmitCompositorFrame(passes, arraysize(passes), root_surface_id_);
test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN),
test::Quad::SolidColorQuad(SK_ColorBLUE)};
@@ -577,7 +592,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleCyclicalReference) {
test::Quad::SolidColorQuad(SK_ColorYELLOW)};
test::Pass passes[] = {test::Pass(quads, arraysize(quads))};
- SubmitFrame(passes, arraysize(passes), root_surface_id_);
+ SubmitCompositorFrame(passes, arraysize(passes), root_surface_id_);
test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorYELLOW)};
test::Pass expected_passes[] = {
@@ -598,14 +613,16 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, TwoSurfaceCyclicalReference) {
test::Pass parent_passes[] = {
test::Pass(parent_quads, arraysize(parent_quads))};
- SubmitFrame(parent_passes, arraysize(parent_passes), root_surface_id_);
+ SubmitCompositorFrame(parent_passes, arraysize(parent_passes),
+ root_surface_id_);
test::Quad child_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN),
test::Quad::SurfaceQuad(root_surface_id_, 1.f),
test::Quad::SolidColorQuad(SK_ColorMAGENTA)};
test::Pass child_passes[] = {test::Pass(child_quads, arraysize(child_quads))};
- SubmitFrame(child_passes, arraysize(child_passes), child_surface_id);
+ SubmitCompositorFrame(child_passes, arraysize(child_passes),
+ child_surface_id);
// The child surface's reference to the root_surface_ will be dropped, so
// we'll end up with:
@@ -638,7 +655,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, RenderPassIdMapping) {
test::Pass(child_quad[0], arraysize(child_quad[0]), child_pass_id[0]),
test::Pass(child_quad[1], arraysize(child_quad[1]), child_pass_id[1])};
- SubmitFrame(surface_passes, arraysize(surface_passes), child_surface_id);
+ SubmitCompositorFrame(surface_passes, arraysize(surface_passes),
+ child_surface_id);
// Pass IDs from the parent surface may collide with ones from the child.
RenderPassId parent_pass_id[] = {RenderPassId(2, 1), RenderPassId(1, 2)};
@@ -649,7 +667,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, RenderPassIdMapping) {
test::Pass(parent_quad[0], arraysize(parent_quad[0]), parent_pass_id[0]),
test::Pass(parent_quad[1], arraysize(parent_quad[1]), parent_pass_id[1])};
- SubmitFrame(parent_passes, arraysize(parent_passes), root_surface_id_);
+ SubmitCompositorFrame(parent_passes, arraysize(parent_passes),
+ root_surface_id_);
scoped_ptr<CompositorFrame> aggregated_frame =
aggregator_.Aggregate(root_surface_id_);
@@ -896,8 +915,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateMultiplePassWithTransform) {
scoped_ptr<CompositorFrame> child_frame(new CompositorFrame);
child_frame->delegated_frame_data = child_frame_data.Pass();
- factory_.SubmitFrame(child_surface_id, child_frame.Pass(),
- SurfaceFactory::DrawCallback());
+ factory_.SubmitCompositorFrame(child_surface_id, child_frame.Pass(),
+ SurfaceFactory::DrawCallback());
}
// Middle child surface.
@@ -927,8 +946,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateMultiplePassWithTransform) {
scoped_ptr<CompositorFrame> middle_frame(new CompositorFrame);
middle_frame->delegated_frame_data = middle_frame_data.Pass();
- factory_.SubmitFrame(middle_surface_id, middle_frame.Pass(),
- SurfaceFactory::DrawCallback());
+ factory_.SubmitCompositorFrame(middle_surface_id, middle_frame.Pass(),
+ SurfaceFactory::DrawCallback());
}
// Root surface.
@@ -963,8 +982,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateMultiplePassWithTransform) {
scoped_ptr<CompositorFrame> root_frame(new CompositorFrame);
root_frame->delegated_frame_data = root_frame_data.Pass();
- factory_.SubmitFrame(root_surface_id_, root_frame.Pass(),
- SurfaceFactory::DrawCallback());
+ factory_.SubmitCompositorFrame(root_surface_id_, root_frame.Pass(),
+ SurfaceFactory::DrawCallback());
scoped_ptr<CompositorFrame> aggregated_frame =
aggregator_.Aggregate(root_surface_id_);
@@ -1072,8 +1091,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) {
SurfaceId child_surface_id = allocator_.GenerateId();
factory_.Create(child_surface_id);
- factory_.SubmitFrame(child_surface_id, child_frame.Pass(),
- SurfaceFactory::DrawCallback());
+ factory_.SubmitCompositorFrame(child_surface_id, child_frame.Pass(),
+ SurfaceFactory::DrawCallback());
test::Quad parent_surface_quads[] = {
test::Quad::SurfaceQuad(child_surface_id, 1.f)};
@@ -1098,8 +1117,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) {
SurfaceId parent_surface_id = allocator_.GenerateId();
factory_.Create(parent_surface_id);
- factory_.SubmitFrame(parent_surface_id, parent_surface_frame.Pass(),
- SurfaceFactory::DrawCallback());
+ factory_.SubmitCompositorFrame(parent_surface_id, parent_surface_frame.Pass(),
+ SurfaceFactory::DrawCallback());
test::Quad root_surface_quads[] = {
test::Quad::SurfaceQuad(parent_surface_id, 1.f)};
@@ -1130,8 +1149,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) {
scoped_ptr<CompositorFrame> root_frame(new CompositorFrame);
root_frame->delegated_frame_data = root_frame_data.Pass();
- factory_.SubmitFrame(root_surface_id_, root_frame.Pass(),
- SurfaceFactory::DrawCallback());
+ factory_.SubmitCompositorFrame(root_surface_id_, root_frame.Pass(),
+ SurfaceFactory::DrawCallback());
scoped_ptr<CompositorFrame> aggregated_frame =
aggregator_.Aggregate(root_surface_id_);
@@ -1167,8 +1186,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) {
scoped_ptr<CompositorFrame> child_frame(new CompositorFrame);
child_frame->delegated_frame_data = child_frame_data.Pass();
- factory_.SubmitFrame(child_surface_id, child_frame.Pass(),
- SurfaceFactory::DrawCallback());
+ factory_.SubmitCompositorFrame(child_surface_id, child_frame.Pass(),
+ SurfaceFactory::DrawCallback());
scoped_ptr<CompositorFrame> aggregated_frame =
aggregator_.Aggregate(root_surface_id_);
@@ -1207,8 +1226,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) {
scoped_ptr<CompositorFrame> root_frame(new CompositorFrame);
root_frame->delegated_frame_data = root_frame_data.Pass();
- factory_.SubmitFrame(root_surface_id_, root_frame.Pass(),
- SurfaceFactory::DrawCallback());
+ factory_.SubmitCompositorFrame(root_surface_id_, root_frame.Pass(),
+ SurfaceFactory::DrawCallback());
}
{
@@ -1229,8 +1248,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) {
scoped_ptr<CompositorFrame> root_frame(new CompositorFrame);
root_frame->delegated_frame_data = root_frame_data.Pass();
- factory_.SubmitFrame(root_surface_id_, root_frame.Pass(),
- SurfaceFactory::DrawCallback());
+ factory_.SubmitCompositorFrame(root_surface_id_, root_frame.Pass(),
+ SurfaceFactory::DrawCallback());
scoped_ptr<CompositorFrame> aggregated_frame =
aggregator_.Aggregate(root_surface_id_);
@@ -1293,6 +1312,196 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) {
factory_.Destroy(child_surface_id);
}
+class SurfaceAggregatorPartialSwapTest
+ : public SurfaceAggregatorValidSurfaceTest {
+ public:
+ SurfaceAggregatorPartialSwapTest()
+ : SurfaceAggregatorValidSurfaceTest(true) {}
+};
+
+// Tests that quads outside the damage rect are ignored.
+TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) {
+ SurfaceId child_surface_id = allocator_.GenerateId();
+ factory_.Create(child_surface_id);
+ // The child surface has two quads, one with a visible rect of 13,13 4x4 and
+ // the other other with a visible rect of 10,10 2x2 (relative to root target
+ // space).
+ {
+ RenderPassId child_pass_id = RenderPassId(1, 1);
+ test::Quad child_quads1[] = {test::Quad::RenderPassQuad(child_pass_id)};
+ test::Quad child_quads2[] = {test::Quad::RenderPassQuad(child_pass_id)};
+ test::Pass child_passes[] = {
+ test::Pass(child_quads1, arraysize(child_quads1), child_pass_id),
+ test::Pass(child_quads2, arraysize(child_quads2), child_pass_id)};
+
+ RenderPassList child_pass_list;
+ AddPasses(&child_pass_list, gfx::Rect(SurfaceSize()), child_passes,
+ arraysize(child_passes));
+
+ child_pass_list.at(0u)->quad_list.ElementAt(0)->visible_rect =
+ gfx::Rect(1, 1, 2, 2);
+ SharedQuadState* child_sqs =
+ child_pass_list.at(0u)->shared_quad_state_list.ElementAt(0u);
+ child_sqs->quad_to_target_transform.Translate(1, 1);
+ child_sqs->quad_to_target_transform.Scale(2, 2);
+
+ child_pass_list.at(1u)->quad_list.ElementAt(0)->visible_rect =
+ gfx::Rect(0, 0, 2, 2);
+
+ SubmitPassListAsFrame(child_surface_id, &child_pass_list);
+ }
+
+ {
+ test::Quad root_quads[] = {test::Quad::SurfaceQuad(child_surface_id, 1.f)};
+
+ test::Pass root_passes[] = {test::Pass(root_quads, arraysize(root_quads))};
+
+ RenderPassList root_pass_list;
+ AddPasses(&root_pass_list, gfx::Rect(SurfaceSize()), root_passes,
+ arraysize(root_passes));
+
+ RenderPass* root_pass = root_pass_list.at(0u);
+ root_pass->shared_quad_state_list.front()
+ ->quad_to_target_transform.Translate(10, 10);
+ root_pass->damage_rect = gfx::Rect(0, 0, 1, 1);
+
+ SubmitPassListAsFrame(root_surface_id_, &root_pass_list);
+ }
+
+ scoped_ptr<CompositorFrame> aggregated_frame =
+ aggregator_.Aggregate(root_surface_id_);
+
+ ASSERT_TRUE(aggregated_frame);
+ ASSERT_TRUE(aggregated_frame->delegated_frame_data);
+
+ DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get();
+
+ const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
+
+ ASSERT_EQ(2u, aggregated_pass_list.size());
+
+ // Damage rect for first aggregation should contain entire root surface.
+ EXPECT_EQ(gfx::Rect(0, 0, 15, 15), aggregated_pass_list[1]->damage_rect);
+ EXPECT_EQ(1u, aggregated_pass_list[0]->quad_list.size());
+ EXPECT_EQ(1u, aggregated_pass_list[1]->quad_list.size());
+
+ // Create a root surface with a smaller damage rect.
+ {
+ test::Quad root_quads[] = {test::Quad::SurfaceQuad(child_surface_id, 1.f)};
+
+ test::Pass root_passes[] = {test::Pass(root_quads, arraysize(root_quads))};
+
+ RenderPassList root_pass_list;
+ AddPasses(&root_pass_list, gfx::Rect(SurfaceSize()), root_passes,
+ arraysize(root_passes));
+
+ RenderPass* root_pass = root_pass_list.at(0u);
+ root_pass->shared_quad_state_list.front()
+ ->quad_to_target_transform.Translate(10, 10);
+ root_pass->damage_rect = gfx::Rect(10, 10, 2, 2);
+ SubmitPassListAsFrame(root_surface_id_, &root_pass_list);
+ }
+
+ {
+ scoped_ptr<CompositorFrame> aggregated_frame =
+ aggregator_.Aggregate(root_surface_id_);
+
+ ASSERT_TRUE(aggregated_frame);
+ ASSERT_TRUE(aggregated_frame->delegated_frame_data);
+
+ DelegatedFrameData* frame_data =
+ aggregated_frame->delegated_frame_data.get();
+
+ const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
+
+ ASSERT_EQ(2u, aggregated_pass_list.size());
+
+ // Only first quad from surface is inside damage rect and should be
+ // included.
+ EXPECT_EQ(gfx::Rect(10, 10, 2, 2), aggregated_pass_list[1]->damage_rect);
+ EXPECT_EQ(0u, aggregated_pass_list[0]->quad_list.size());
+ EXPECT_EQ(1u, aggregated_pass_list[1]->quad_list.size());
+ EXPECT_EQ(gfx::Rect(0, 0, 2, 2),
+ aggregated_pass_list[1]->quad_list.back()->visible_rect);
+ }
+
+ // New child frame has same content and no damage, but has a
+ // CopyOutputRequest.
+ {
+ RenderPassId child_pass_id = RenderPassId(1, 1);
+ test::Quad child_quads1[] = {test::Quad::RenderPassQuad(child_pass_id)};
+ test::Quad child_quads2[] = {test::Quad::RenderPassQuad(child_pass_id)};
+ test::Pass child_passes[] = {
+ test::Pass(child_quads1, arraysize(child_quads1), child_pass_id),
+ test::Pass(child_quads2, arraysize(child_quads2), child_pass_id)};
+
+ RenderPassList child_pass_list;
+ AddPasses(&child_pass_list, gfx::Rect(SurfaceSize()), child_passes,
+ arraysize(child_passes));
+
+ child_pass_list.at(0u)->quad_list.ElementAt(0)->visible_rect =
+ gfx::Rect(1, 1, 2, 2);
+ SharedQuadState* child_sqs =
+ child_pass_list.at(0u)->shared_quad_state_list.ElementAt(0u);
+ child_sqs->quad_to_target_transform.Translate(1, 1);
+ child_sqs->quad_to_target_transform.Scale(2, 2);
+
+ child_pass_list.at(1u)->quad_list.ElementAt(0)->visible_rect =
+ gfx::Rect(0, 0, 2, 2);
+
+ RenderPass* child_root_pass = child_pass_list.at(1u);
+
+ child_root_pass->copy_requests.push_back(
+ CopyOutputRequest::CreateEmptyRequest());
+ child_root_pass->damage_rect = gfx::Rect();
+ SubmitPassListAsFrame(child_surface_id, &child_pass_list);
+ }
+
+ {
+ scoped_ptr<CompositorFrame> aggregated_frame =
+ aggregator_.Aggregate(root_surface_id_);
+
+ ASSERT_TRUE(aggregated_frame);
+ ASSERT_TRUE(aggregated_frame->delegated_frame_data);
+
+ DelegatedFrameData* frame_data =
+ aggregated_frame->delegated_frame_data.get();
+
+ const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
+
+ // Output frame should have no damage, but all quads included.
+ ASSERT_EQ(3u, aggregated_pass_list.size());
+
+ EXPECT_TRUE(aggregated_pass_list[1]->damage_rect.IsEmpty());
+ ASSERT_EQ(1u, aggregated_pass_list[0]->quad_list.size());
+ ASSERT_EQ(1u, aggregated_pass_list[1]->quad_list.size());
+ EXPECT_EQ(gfx::Rect(1, 1, 2, 2),
+ aggregated_pass_list[0]->quad_list.ElementAt(0)->visible_rect);
+ EXPECT_EQ(gfx::Rect(0, 0, 2, 2),
+ aggregated_pass_list[1]->quad_list.ElementAt(0)->visible_rect);
+ }
+
+ {
+ scoped_ptr<CompositorFrame> aggregated_frame =
+ aggregator_.Aggregate(root_surface_id_);
+
+ ASSERT_TRUE(aggregated_frame);
+ ASSERT_TRUE(aggregated_frame->delegated_frame_data);
+
+ DelegatedFrameData* frame_data =
+ aggregated_frame->delegated_frame_data.get();
+
+ const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
+ // There were no changes since last aggregation, so output should be empty
+ // and have no damage.
+ ASSERT_EQ(1u, aggregated_pass_list.size());
+ EXPECT_TRUE(aggregated_pass_list[0]->damage_rect.IsEmpty());
+ ASSERT_EQ(0u, aggregated_pass_list[0]->quad_list.size());
+ }
+
+ factory_.Destroy(child_surface_id);
+}
+
class SurfaceAggregatorWithResourcesTest : public testing::Test {
public:
void SetUp() override {
@@ -1305,7 +1514,7 @@ class SurfaceAggregatorWithResourcesTest : public testing::Test {
output_surface_.get(), shared_bitmap_manager_.get());
aggregator_.reset(
- new SurfaceAggregator(&manager_, resource_provider_.get()));
+ new SurfaceAggregator(&manager_, resource_provider_.get(), false));
}
protected:
@@ -1336,12 +1545,12 @@ class ResourceTrackingSurfaceFactoryClient : public SurfaceFactoryClient {
DISALLOW_COPY_AND_ASSIGN(ResourceTrackingSurfaceFactoryClient);
};
-void SubmitFrameWithResources(ResourceId* resource_ids,
- size_t num_resource_ids,
- bool valid,
- SurfaceId child_id,
- SurfaceFactory* factory,
- SurfaceId surface_id) {
+void SubmitCompositorFrameWithResources(ResourceId* resource_ids,
+ size_t num_resource_ids,
+ bool valid,
+ SurfaceId child_id,
+ SurfaceFactory* factory,
+ SurfaceId surface_id) {
scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
scoped_ptr<RenderPass> pass = RenderPass::Create();
pass->id = RenderPassId(1, 1);
@@ -1380,8 +1589,8 @@ void SubmitFrameWithResources(ResourceId* resource_ids,
frame_data->render_pass_list.push_back(pass.Pass());
scoped_ptr<CompositorFrame> frame(new CompositorFrame);
frame->delegated_frame_data = frame_data.Pass();
- factory->SubmitFrame(surface_id, frame.Pass(),
- SurfaceFactory::DrawCallback());
+ factory->SubmitCompositorFrame(surface_id, frame.Pass(),
+ SurfaceFactory::DrawCallback());
}
TEST_F(SurfaceAggregatorWithResourcesTest, TakeResourcesOneSurface) {
@@ -1391,15 +1600,16 @@ TEST_F(SurfaceAggregatorWithResourcesTest, TakeResourcesOneSurface) {
factory.Create(surface_id);
ResourceId ids[] = {11, 12, 13};
- SubmitFrameWithResources(ids, arraysize(ids), true, SurfaceId(), &factory,
- surface_id);
+ SubmitCompositorFrameWithResources(ids, arraysize(ids), true, SurfaceId(),
+ &factory, surface_id);
scoped_ptr<CompositorFrame> frame = aggregator_->Aggregate(surface_id);
// Nothing should be available to be returned yet.
EXPECT_TRUE(client.returned_resources().empty());
- SubmitFrameWithResources(NULL, 0u, true, SurfaceId(), &factory, surface_id);
+ SubmitCompositorFrameWithResources(NULL, 0u, true, SurfaceId(), &factory,
+ surface_id);
frame = aggregator_->Aggregate(surface_id);
@@ -1431,7 +1641,8 @@ TEST_F(SurfaceAggregatorWithResourcesTest, TakeInvalidResources) {
frame_data->render_pass_list.push_back(pass.Pass());
scoped_ptr<CompositorFrame> frame(new CompositorFrame);
frame->delegated_frame_data = frame_data.Pass();
- factory.SubmitFrame(surface_id, frame.Pass(), SurfaceFactory::DrawCallback());
+ factory.SubmitCompositorFrame(surface_id, frame.Pass(),
+ SurfaceFactory::DrawCallback());
scoped_ptr<CompositorFrame> returned_frame =
aggregator_->Aggregate(surface_id);
@@ -1439,7 +1650,8 @@ TEST_F(SurfaceAggregatorWithResourcesTest, TakeInvalidResources) {
// Nothing should be available to be returned yet.
EXPECT_TRUE(client.returned_resources().empty());
- SubmitFrameWithResources(NULL, 0, true, SurfaceId(), &factory, surface_id);
+ SubmitCompositorFrameWithResources(NULL, 0, true, SurfaceId(), &factory,
+ surface_id);
ASSERT_EQ(1u, client.returned_resources().size());
EXPECT_EQ(11u, client.returned_resources()[0].id);
@@ -1455,15 +1667,16 @@ TEST_F(SurfaceAggregatorWithResourcesTest, TwoSurfaces) {
factory.Create(surface_id2);
ResourceId ids[] = {11, 12, 13};
- SubmitFrameWithResources(ids, arraysize(ids), true, SurfaceId(), &factory,
- surface_id);
+ SubmitCompositorFrameWithResources(ids, arraysize(ids), true, SurfaceId(),
+ &factory, surface_id);
ResourceId ids2[] = {14, 15, 16};
- SubmitFrameWithResources(ids2, arraysize(ids2), true, SurfaceId(), &factory,
- surface_id2);
+ SubmitCompositorFrameWithResources(ids2, arraysize(ids2), true, SurfaceId(),
+ &factory, surface_id2);
scoped_ptr<CompositorFrame> frame = aggregator_->Aggregate(surface_id);
- SubmitFrameWithResources(NULL, 0, true, SurfaceId(), &factory, surface_id);
+ SubmitCompositorFrameWithResources(NULL, 0, true, SurfaceId(), &factory,
+ surface_id);
// Nothing should be available to be returned yet.
EXPECT_TRUE(client.returned_resources().empty());
@@ -1496,16 +1709,18 @@ TEST_F(SurfaceAggregatorWithResourcesTest, InvalidChildSurface) {
factory.Create(child_surface_id);
ResourceId ids[] = {14, 15, 16};
- SubmitFrameWithResources(ids, arraysize(ids), true, SurfaceId(), &factory,
- child_surface_id);
+ SubmitCompositorFrameWithResources(ids, arraysize(ids), true, SurfaceId(),
+ &factory, child_surface_id);
ResourceId ids2[] = {17, 18, 19};
- SubmitFrameWithResources(ids2, arraysize(ids2), false, child_surface_id,
- &factory, middle_surface_id);
+ SubmitCompositorFrameWithResources(ids2, arraysize(ids2), false,
+ child_surface_id, &factory,
+ middle_surface_id);
ResourceId ids3[] = {20, 21, 22};
- SubmitFrameWithResources(ids3, arraysize(ids3), true, middle_surface_id,
- &factory, root_surface_id);
+ SubmitCompositorFrameWithResources(ids3, arraysize(ids3), true,
+ middle_surface_id, &factory,
+ root_surface_id);
scoped_ptr<CompositorFrame> frame;
frame = aggregator_->Aggregate(root_surface_id);
@@ -1515,8 +1730,9 @@ TEST_F(SurfaceAggregatorWithResourcesTest, InvalidChildSurface) {
EXPECT_EQ(1u, pass_list->back()->shared_quad_state_list.size());
EXPECT_EQ(3u, pass_list->back()->quad_list.size());
- SubmitFrameWithResources(ids2, arraysize(ids), true, child_surface_id,
- &factory, middle_surface_id);
+ SubmitCompositorFrameWithResources(ids2, arraysize(ids), true,
+ child_surface_id, &factory,
+ middle_surface_id);
frame = aggregator_->Aggregate(root_surface_id);
diff --git a/chromium/cc/surfaces/surface_display_output_surface.cc b/chromium/cc/surfaces/surface_display_output_surface.cc
index e21d15d8afb..ed26b491bf0 100644
--- a/chromium/cc/surfaces/surface_display_output_surface.cc
+++ b/chromium/cc/surfaces/surface_display_output_surface.cc
@@ -17,8 +17,9 @@ namespace cc {
SurfaceDisplayOutputSurface::SurfaceDisplayOutputSurface(
SurfaceManager* surface_manager,
SurfaceIdAllocator* allocator,
- const scoped_refptr<ContextProvider>& context_provider)
- : OutputSurface(context_provider),
+ const scoped_refptr<ContextProvider>& context_provider,
+ const scoped_refptr<ContextProvider>& worker_context_provider)
+ : OutputSurface(context_provider, worker_context_provider),
display_client_(NULL),
factory_(surface_manager, this),
allocator_(allocator) {
@@ -63,7 +64,7 @@ void SurfaceDisplayOutputSurface::SwapBuffers(CompositorFrame* frame) {
scoped_ptr<CompositorFrame> frame_copy(new CompositorFrame());
frame->AssignTo(frame_copy.get());
- factory_.SubmitFrame(
+ factory_.SubmitCompositorFrame(
surface_id_, frame_copy.Pass(),
base::Bind(&SurfaceDisplayOutputSurface::SwapBuffersComplete,
base::Unretained(this)));
@@ -80,7 +81,8 @@ bool SurfaceDisplayOutputSurface::BindToClient(OutputSurfaceClient* client) {
void SurfaceDisplayOutputSurface::ForceReclaimResources() {
if (!surface_id_.is_null())
- factory_.SubmitFrame(surface_id_, nullptr, SurfaceFactory::DrawCallback());
+ factory_.SubmitCompositorFrame(surface_id_, nullptr,
+ SurfaceFactory::DrawCallback());
}
void SurfaceDisplayOutputSurface::ReturnResources(
diff --git a/chromium/cc/surfaces/surface_display_output_surface.h b/chromium/cc/surfaces/surface_display_output_surface.h
index c11bb86075d..2cdaadc7830 100644
--- a/chromium/cc/surfaces/surface_display_output_surface.h
+++ b/chromium/cc/surfaces/surface_display_output_surface.h
@@ -27,7 +27,8 @@ class CC_SURFACES_EXPORT SurfaceDisplayOutputSurface
SurfaceDisplayOutputSurface(
SurfaceManager* surface_manager,
SurfaceIdAllocator* allocator,
- const scoped_refptr<ContextProvider>& context_provider);
+ const scoped_refptr<ContextProvider>& context_provider,
+ const scoped_refptr<ContextProvider>& worker_context_provider);
~SurfaceDisplayOutputSurface() override;
void set_display_client(OnscreenDisplayClient* display_client) {
diff --git a/chromium/cc/surfaces/surface_display_output_surface_unittest.cc b/chromium/cc/surfaces/surface_display_output_surface_unittest.cc
index 922dd9e8d5f..daabafec7f0 100644
--- a/chromium/cc/surfaces/surface_display_output_surface_unittest.cc
+++ b/chromium/cc/surfaces/surface_display_output_surface_unittest.cc
@@ -60,7 +60,8 @@ class SurfaceDisplayOutputSurfaceTest : public testing::Test {
context_provider_(TestContextProvider::Create()),
surface_display_output_surface_(&surface_manager_,
&allocator_,
- context_provider_) {
+ context_provider_,
+ nullptr) {
output_surface_ = display_client_.output_surface();
display_client_.set_surface_output_surface(
&surface_display_output_surface_);
diff --git a/chromium/cc/surfaces/surface_factory.cc b/chromium/cc/surfaces/surface_factory.cc
index 9bb50ace4c2..3e83c8cfd73 100644
--- a/chromium/cc/surfaces/surface_factory.cc
+++ b/chromium/cc/surfaces/surface_factory.cc
@@ -4,6 +4,7 @@
#include "cc/surfaces/surface_factory.h"
+#include "base/trace_event/trace_event.h"
#include "cc/output/compositor_frame.h"
#include "cc/output/copy_output_request.h"
#include "cc/surfaces/surface.h"
@@ -47,15 +48,18 @@ void SurfaceFactory::Destroy(SurfaceId surface_id) {
manager_->Destroy(surface_map_.take_and_erase(it));
}
-void SurfaceFactory::SubmitFrame(SurfaceId surface_id,
- scoped_ptr<CompositorFrame> frame,
- const DrawCallback& callback) {
+void SurfaceFactory::SubmitCompositorFrame(SurfaceId surface_id,
+ scoped_ptr<CompositorFrame> frame,
+ const DrawCallback& callback) {
+ TRACE_EVENT0("cc", "SurfaceFactory::SubmitCompositorFrame");
OwningSurfaceMap::iterator it = surface_map_.find(surface_id);
DCHECK(it != surface_map_.end());
DCHECK(it->second->factory().get() == this);
it->second->QueueFrame(frame.Pass(), callback);
- if (!manager_->SurfaceModified(surface_id))
+ if (!manager_->SurfaceModified(surface_id)) {
+ TRACE_EVENT_INSTANT0("cc", "Damage not visible.", TRACE_EVENT_SCOPE_THREAD);
it->second->RunDrawCallbacks(SurfaceDrawStatus::DRAW_SKIPPED);
+ }
}
void SurfaceFactory::RequestCopyOfSurface(
diff --git a/chromium/cc/surfaces/surface_factory.h b/chromium/cc/surfaces/surface_factory.h
index 0e812de5e23..5af8d2e0eb7 100644
--- a/chromium/cc/surfaces/surface_factory.h
+++ b/chromium/cc/surfaces/surface_factory.h
@@ -11,6 +11,7 @@
#include "base/containers/scoped_ptr_hash_map.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
+#include "cc/output/compositor_frame.h"
#include "cc/surfaces/surface_id.h"
#include "cc/surfaces/surface_resource_holder.h"
#include "cc/surfaces/surface_sequence.h"
@@ -21,7 +22,6 @@ class Size;
}
namespace cc {
-class CompositorFrame;
class CopyOutputRequest;
class Surface;
class SurfaceFactoryClient;
@@ -49,9 +49,9 @@ class CC_SURFACES_EXPORT SurfaceFactory
// although the frame may reference surfaces created by other factories.
// The callback is called the first time this frame is used to draw, or if
// the frame is discarded.
- void SubmitFrame(SurfaceId surface_id,
- scoped_ptr<CompositorFrame> frame,
- const DrawCallback& callback);
+ void SubmitCompositorFrame(SurfaceId surface_id,
+ scoped_ptr<CompositorFrame> frame,
+ const DrawCallback& callback);
void RequestCopyOfSurface(SurfaceId surface_id,
scoped_ptr<CopyOutputRequest> copy_request);
diff --git a/chromium/cc/surfaces/surface_factory_unittest.cc b/chromium/cc/surfaces/surface_factory_unittest.cc
index c2951aead48..c7ce96403e2 100644
--- a/chromium/cc/surfaces/surface_factory_unittest.cc
+++ b/chromium/cc/surfaces/surface_factory_unittest.cc
@@ -49,8 +49,8 @@ class SurfaceFactoryTest : public testing::Test {
factory_.Destroy(surface_id_);
}
- void SubmitFrameWithResources(ResourceId* resource_ids,
- size_t num_resource_ids) {
+ void SubmitCompositorFrameWithResources(ResourceId* resource_ids,
+ size_t num_resource_ids) {
scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
for (size_t i = 0u; i < num_resource_ids; ++i) {
TransferableResource resource;
@@ -60,8 +60,8 @@ class SurfaceFactoryTest : public testing::Test {
}
scoped_ptr<CompositorFrame> frame(new CompositorFrame);
frame->delegated_frame_data = frame_data.Pass();
- factory_.SubmitFrame(surface_id_, frame.Pass(),
- SurfaceFactory::DrawCallback());
+ factory_.SubmitCompositorFrame(surface_id_, frame.Pass(),
+ SurfaceFactory::DrawCallback());
}
void UnrefResources(ResourceId* ids_to_unref,
@@ -108,7 +108,8 @@ class SurfaceFactoryTest : public testing::Test {
// with no resource provider action in between.
TEST_F(SurfaceFactoryTest, ResourceLifetimeSimple) {
ResourceId first_frame_ids[] = {1, 2, 3};
- SubmitFrameWithResources(first_frame_ids, arraysize(first_frame_ids));
+ SubmitCompositorFrameWithResources(first_frame_ids,
+ arraysize(first_frame_ids));
// All of the resources submitted in the first frame are still in use at this
// time by virtue of being in the pending frame, so none can be returned to
@@ -118,7 +119,7 @@ TEST_F(SurfaceFactoryTest, ResourceLifetimeSimple) {
// The second frame references no resources and thus should make all resources
// available to be returned.
- SubmitFrameWithResources(NULL, 0);
+ SubmitCompositorFrameWithResources(NULL, 0);
ResourceId expected_returned_ids[] = {1, 2, 3};
int expected_returned_counts[] = {1, 1, 1};
@@ -131,7 +132,8 @@ TEST_F(SurfaceFactoryTest, ResourceLifetimeSimple) {
// with the resource provider holding everything alive.
TEST_F(SurfaceFactoryTest, ResourceLifetimeSimpleWithProviderHoldingAlive) {
ResourceId first_frame_ids[] = {1, 2, 3};
- SubmitFrameWithResources(first_frame_ids, arraysize(first_frame_ids));
+ SubmitCompositorFrameWithResources(first_frame_ids,
+ arraysize(first_frame_ids));
// All of the resources submitted in the first frame are still in use at this
// time by virtue of being in the pending frame, so none can be returned to
@@ -144,7 +146,7 @@ TEST_F(SurfaceFactoryTest, ResourceLifetimeSimpleWithProviderHoldingAlive) {
// The second frame references no resources and thus should make all resources
// available to be returned as soon as the resource provider releases them.
- SubmitFrameWithResources(NULL, 0);
+ SubmitCompositorFrameWithResources(NULL, 0);
EXPECT_EQ(0u, client_.returned_resources().size());
client_.clear_returned_resources();
@@ -163,16 +165,18 @@ TEST_F(SurfaceFactoryTest, ResourceLifetimeSimpleWithProviderHoldingAlive) {
// before returning it to the client.
TEST_F(SurfaceFactoryTest, ResourceReusedBeforeReturn) {
ResourceId first_frame_ids[] = {7};
- SubmitFrameWithResources(first_frame_ids, arraysize(first_frame_ids));
+ SubmitCompositorFrameWithResources(first_frame_ids,
+ arraysize(first_frame_ids));
// This removes all references to resource id 7.
- SubmitFrameWithResources(NULL, 0);
+ SubmitCompositorFrameWithResources(NULL, 0);
// This references id 7 again.
- SubmitFrameWithResources(first_frame_ids, arraysize(first_frame_ids));
+ SubmitCompositorFrameWithResources(first_frame_ids,
+ arraysize(first_frame_ids));
// This removes it again.
- SubmitFrameWithResources(NULL, 0);
+ SubmitCompositorFrameWithResources(NULL, 0);
// Now it should be returned.
// We don't care how many entries are in the returned array for 7, so long as
@@ -190,14 +194,16 @@ TEST_F(SurfaceFactoryTest, ResourceReusedBeforeReturn) {
// multiple providers.
TEST_F(SurfaceFactoryTest, ResourceRefMultipleTimes) {
ResourceId first_frame_ids[] = {3, 4};
- SubmitFrameWithResources(first_frame_ids, arraysize(first_frame_ids));
+ SubmitCompositorFrameWithResources(first_frame_ids,
+ arraysize(first_frame_ids));
// Ref resources from the first frame twice.
RefCurrentFrameResources();
RefCurrentFrameResources();
ResourceId second_frame_ids[] = {4, 5};
- SubmitFrameWithResources(second_frame_ids, arraysize(second_frame_ids));
+ SubmitCompositorFrameWithResources(second_frame_ids,
+ arraysize(second_frame_ids));
// Ref resources from the second frame 3 times.
RefCurrentFrameResources();
@@ -206,7 +212,7 @@ TEST_F(SurfaceFactoryTest, ResourceRefMultipleTimes) {
// Submit a frame with no resources to remove all current frame refs from
// submitted resources.
- SubmitFrameWithResources(NULL, 0);
+ SubmitCompositorFrameWithResources(NULL, 0);
EXPECT_EQ(0u, client_.returned_resources().size());
client_.clear_returned_resources();
@@ -267,7 +273,8 @@ TEST_F(SurfaceFactoryTest, ResourceRefMultipleTimes) {
TEST_F(SurfaceFactoryTest, ResourceLifetime) {
ResourceId first_frame_ids[] = {1, 2, 3};
- SubmitFrameWithResources(first_frame_ids, arraysize(first_frame_ids));
+ SubmitCompositorFrameWithResources(first_frame_ids,
+ arraysize(first_frame_ids));
// All of the resources submitted in the first frame are still in use at this
// time by virtue of being in the pending frame, so none can be returned to
@@ -279,7 +286,8 @@ TEST_F(SurfaceFactoryTest, ResourceLifetime) {
// ones. We expect to receive back resource 1 with a count of 1 since it was
// only referenced by the first frame.
ResourceId second_frame_ids[] = {2, 3, 4};
- SubmitFrameWithResources(second_frame_ids, arraysize(second_frame_ids));
+ SubmitCompositorFrameWithResources(second_frame_ids,
+ arraysize(second_frame_ids));
{
SCOPED_TRACE("second frame");
@@ -295,7 +303,8 @@ TEST_F(SurfaceFactoryTest, ResourceLifetime) {
// and 3 will have counts of 2, since they were used in both frames, and
// resource ID 4 will have a count of 1.
ResourceId third_frame_ids[] = {10, 11, 12, 13};
- SubmitFrameWithResources(third_frame_ids, arraysize(third_frame_ids));
+ SubmitCompositorFrameWithResources(third_frame_ids,
+ arraysize(third_frame_ids));
{
SCOPED_TRACE("third frame");
@@ -310,7 +319,8 @@ TEST_F(SurfaceFactoryTest, ResourceLifetime) {
RefCurrentFrameResources();
ResourceId fourth_frame_ids[] = {12, 13};
- SubmitFrameWithResources(fourth_frame_ids, arraysize(fourth_frame_ids));
+ SubmitCompositorFrameWithResources(fourth_frame_ids,
+ arraysize(fourth_frame_ids));
EXPECT_EQ(0u, client_.returned_resources().size());
@@ -348,7 +358,7 @@ TEST_F(SurfaceFactoryTest, ResourceLifetime) {
EXPECT_EQ(0u, client_.returned_resources().size());
// If we submit an empty frame, however, they should become available.
- SubmitFrameWithResources(NULL, 0u);
+ SubmitCompositorFrameWithResources(NULL, 0u);
{
SCOPED_TRACE("fourth frame, second unref");
@@ -369,8 +379,8 @@ TEST_F(SurfaceFactoryTest, BlankNoIndexIncrement) {
scoped_ptr<CompositorFrame> frame(new CompositorFrame);
frame->delegated_frame_data.reset(new DelegatedFrameData);
- factory_.SubmitFrame(surface_id, frame.Pass(),
- SurfaceFactory::DrawCallback());
+ factory_.SubmitCompositorFrame(surface_id, frame.Pass(),
+ SurfaceFactory::DrawCallback());
EXPECT_EQ(2, surface->frame_index());
factory_.Destroy(surface_id);
}
@@ -397,8 +407,8 @@ TEST_F(SurfaceFactoryTest, DestroyAll) {
uint32 execute_count = 0;
SurfaceDrawStatus drawn = SurfaceDrawStatus::DRAW_SKIPPED;
- factory_.SubmitFrame(id, frame.Pass(),
- base::Bind(&DrawCallback, &execute_count, &drawn));
+ factory_.SubmitCompositorFrame(
+ id, frame.Pass(), base::Bind(&DrawCallback, &execute_count, &drawn));
surface_id_ = SurfaceId();
factory_.DestroyAll();
@@ -423,8 +433,8 @@ TEST_F(SurfaceFactoryTest, DestroySequence) {
frame->metadata.satisfies_sequences.push_back(4);
frame->delegated_frame_data = frame_data.Pass();
DCHECK(manager_.GetSurfaceForId(id2));
- factory_.SubmitFrame(surface_id_, frame.Pass(),
- SurfaceFactory::DrawCallback());
+ factory_.SubmitCompositorFrame(surface_id_, frame.Pass(),
+ SurfaceFactory::DrawCallback());
DCHECK(!manager_.GetSurfaceForId(id2));
// Check that waiting after the sequence is satisfied works.
@@ -475,7 +485,8 @@ TEST_F(SurfaceFactoryTest, DestroyCycle) {
frame_data->render_pass_list.push_back(render_pass.Pass());
scoped_ptr<CompositorFrame> frame(new CompositorFrame);
frame->delegated_frame_data = frame_data.Pass();
- factory_.SubmitFrame(id2, frame.Pass(), SurfaceFactory::DrawCallback());
+ factory_.SubmitCompositorFrame(id2, frame.Pass(),
+ SurfaceFactory::DrawCallback());
}
factory_.Destroy(id2);
@@ -487,8 +498,8 @@ TEST_F(SurfaceFactoryTest, DestroyCycle) {
frame_data->render_pass_list.push_back(render_pass.Pass());
scoped_ptr<CompositorFrame> frame(new CompositorFrame);
frame->delegated_frame_data = frame_data.Pass();
- factory_.SubmitFrame(surface_id_, frame.Pass(),
- SurfaceFactory::DrawCallback());
+ factory_.SubmitCompositorFrame(surface_id_, frame.Pass(),
+ SurfaceFactory::DrawCallback());
}
factory_.Destroy(surface_id_);
EXPECT_TRUE(manager_.GetSurfaceForId(id2));
diff --git a/chromium/cc/surfaces/surface_hittest.cc b/chromium/cc/surfaces/surface_hittest.cc
new file mode 100644
index 00000000000..3a3864ecdb8
--- /dev/null
+++ b/chromium/cc/surfaces/surface_hittest.cc
@@ -0,0 +1,175 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/surfaces/surface_hittest.h"
+
+#include "cc/output/compositor_frame.h"
+#include "cc/output/delegated_frame_data.h"
+#include "cc/quads/draw_quad.h"
+#include "cc/quads/render_pass_draw_quad.h"
+#include "cc/quads/surface_draw_quad.h"
+#include "cc/surfaces/surface.h"
+#include "cc/surfaces/surface_manager.h"
+#include "ui/gfx/geometry/point.h"
+#include "ui/gfx/transform.h"
+
+namespace cc {
+namespace {
+}
+
+SurfaceHittest::SurfaceHittest(SurfaceManager* manager) : manager_(manager) {}
+
+SurfaceHittest::~SurfaceHittest() {}
+
+SurfaceId SurfaceHittest::GetTargetSurfaceAtPoint(SurfaceId surface_id,
+ const gfx::Point& point,
+ gfx::Transform* transform) {
+ SurfaceId hittest_surface_id = surface_id;
+ // Reset the output transform to identity.
+ if (transform)
+ *transform = gfx::Transform();
+
+ std::set<const RenderPass*> referenced_passes;
+ GetTargetSurfaceAtPointInternal(surface_id, RenderPassId(), point,
+ &referenced_passes, &hittest_surface_id,
+ transform);
+
+ return hittest_surface_id;
+}
+
+bool SurfaceHittest::GetTargetSurfaceAtPointInternal(
+ SurfaceId surface_id,
+ const RenderPassId& render_pass_id,
+ const gfx::Point& point_in_root_target,
+ std::set<const RenderPass*>* referenced_passes,
+ SurfaceId* out_surface_id,
+ gfx::Transform* out_transform) {
+ const RenderPass* render_pass =
+ GetRenderPassForSurfaceById(surface_id, render_pass_id);
+ if (!render_pass)
+ return false;
+
+ // To avoid an infinite recursion, we need to skip the RenderPass if it's
+ // already been referenced.
+ if (referenced_passes->find(render_pass) != referenced_passes->end())
+ return false;
+
+ referenced_passes->insert(render_pass);
+
+ // The |transform_to_root_target| matrix cannot be inverted if it has a
+ // z-scale of 0 or due to floating point errors.
+ gfx::Transform transform_from_root_target;
+ if (!render_pass->transform_to_root_target.GetInverse(
+ &transform_from_root_target)) {
+ return false;
+ }
+
+ gfx::Point point_in_render_pass_space(point_in_root_target);
+ transform_from_root_target.TransformPoint(&point_in_render_pass_space);
+
+ for (const DrawQuad* quad : render_pass->quad_list) {
+ gfx::Transform target_to_quad_transform;
+ gfx::Point point_in_quad_space;
+ if (!PointInQuad(quad, point_in_render_pass_space,
+ &target_to_quad_transform, &point_in_quad_space)) {
+ continue;
+ }
+
+ if (quad->material == DrawQuad::SURFACE_CONTENT) {
+ // We've hit a SurfaceDrawQuad, we need to recurse into this
+ // Surface.
+ const SurfaceDrawQuad* surface_quad = SurfaceDrawQuad::MaterialCast(quad);
+
+ gfx::Transform transform_to_child_space;
+ if (GetTargetSurfaceAtPointInternal(
+ surface_quad->surface_id, RenderPassId(), point_in_quad_space,
+ referenced_passes, out_surface_id, &transform_to_child_space)) {
+ *out_transform = transform_to_child_space * target_to_quad_transform *
+ transform_from_root_target;
+ return true;
+ }
+
+ continue;
+ }
+
+ if (quad->material == DrawQuad::RENDER_PASS) {
+ // We've hit a RenderPassDrawQuad, we need to recurse into this
+ // RenderPass.
+ const RenderPassDrawQuad* render_quad =
+ RenderPassDrawQuad::MaterialCast(quad);
+
+ gfx::Transform transform_to_child_space;
+ if (GetTargetSurfaceAtPointInternal(
+ surface_id, render_quad->render_pass_id, point_in_root_target,
+ referenced_passes, out_surface_id, &transform_to_child_space)) {
+ *out_transform = transform_to_child_space;
+ return true;
+ }
+
+ continue;
+ }
+
+ // We've hit a different type of quad in the current Surface. There's no
+ // need to iterate anymore, this is the quad that receives the event.
+ *out_surface_id = surface_id;
+ return true;
+ }
+
+ // No quads were found beneath the provided |point|.
+ return false;
+}
+
+const RenderPass* SurfaceHittest::GetRenderPassForSurfaceById(
+ SurfaceId surface_id,
+ const RenderPassId& render_pass_id) {
+ Surface* surface = manager_->GetSurfaceForId(surface_id);
+ if (!surface)
+ return nullptr;
+
+ const CompositorFrame* surface_frame = surface->GetEligibleFrame();
+ if (!surface_frame)
+ return nullptr;
+
+ const DelegatedFrameData* frame_data =
+ surface_frame->delegated_frame_data.get();
+ if (frame_data->render_pass_list.empty())
+ return nullptr;
+
+ if (!render_pass_id.IsValid())
+ return frame_data->render_pass_list.back();
+
+ for (const auto* render_pass : frame_data->render_pass_list) {
+ if (render_pass->id == render_pass_id)
+ return render_pass;
+ }
+
+ return nullptr;
+}
+
+bool SurfaceHittest::PointInQuad(const DrawQuad* quad,
+ const gfx::Point& point_in_render_pass_space,
+ gfx::Transform* target_to_quad_transform,
+ gfx::Point* point_in_quad_space) {
+ // First we test against the clip_rect. The clip_rect is in target space, so
+ // we can test the point directly.
+ if (quad->shared_quad_state->is_clipped &&
+ !quad->shared_quad_state->clip_rect.Contains(
+ point_in_render_pass_space)) {
+ return false;
+ }
+
+ // We now transform the point to content space and test if it hits the
+ // rect.
+ if (!quad->shared_quad_state->quad_to_target_transform.GetInverse(
+ target_to_quad_transform)) {
+ return false;
+ }
+
+ *point_in_quad_space = point_in_render_pass_space;
+ target_to_quad_transform->TransformPoint(point_in_quad_space);
+
+ return quad->rect.Contains(*point_in_quad_space);
+}
+
+} // namespace cc
diff --git a/chromium/cc/surfaces/surface_hittest.h b/chromium/cc/surfaces/surface_hittest.h
new file mode 100644
index 00000000000..b5e1a672494
--- /dev/null
+++ b/chromium/cc/surfaces/surface_hittest.h
@@ -0,0 +1,60 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_SURFACES_SURFACE_HITTEST_H_
+#define CC_SURFACES_SURFACE_HITTEST_H_
+
+#include <set>
+
+#include "cc/surfaces/surface_id.h"
+#include "cc/surfaces/surfaces_export.h"
+
+namespace gfx {
+class Point;
+class Transform;
+}
+
+namespace cc {
+class DrawQuad;
+class QuadList;
+class RenderPass;
+class RenderPassId;
+class SurfaceManager;
+
+// Performs a hittest in surface quads.
+class CC_SURFACES_EXPORT SurfaceHittest {
+ public:
+ explicit SurfaceHittest(SurfaceManager* manager);
+ ~SurfaceHittest();
+
+ // Hittests against Surface with SurfaceId |surface_id|, return the contained
+ // surface that the point is hitting and the |transformed_point| in the
+ // surface space.
+ SurfaceId GetTargetSurfaceAtPoint(SurfaceId surface_id,
+ const gfx::Point& point,
+ gfx::Transform* transform);
+
+ private:
+ bool GetTargetSurfaceAtPointInternal(
+ SurfaceId surface_id,
+ const RenderPassId& render_pass_id,
+ const gfx::Point& point_in_root_target,
+ std::set<const RenderPass*>* referenced_passes,
+ SurfaceId* out_surface_id,
+ gfx::Transform* out_transform);
+
+ const RenderPass* GetRenderPassForSurfaceById(
+ SurfaceId surface_id,
+ const RenderPassId& render_pass_id);
+
+ bool PointInQuad(const DrawQuad* quad,
+ const gfx::Point& point_in_render_pass_space,
+ gfx::Transform* target_to_quad_transform,
+ gfx::Point* point_in_quad_space);
+
+ SurfaceManager* const manager_;
+};
+} // namespace cc
+
+#endif // CC_SURFACES_SURFACE_HITTEST_H_
diff --git a/chromium/cc/surfaces/surface_hittest_unittest.cc b/chromium/cc/surfaces/surface_hittest_unittest.cc
new file mode 100644
index 00000000000..a7f373fff10
--- /dev/null
+++ b/chromium/cc/surfaces/surface_hittest_unittest.cc
@@ -0,0 +1,487 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/output/compositor_frame.h"
+#include "cc/output/delegated_frame_data.h"
+#include "cc/quads/render_pass.h"
+#include "cc/quads/render_pass_draw_quad.h"
+#include "cc/quads/render_pass_id.h"
+#include "cc/quads/solid_color_draw_quad.h"
+#include "cc/quads/surface_draw_quad.h"
+#include "cc/surfaces/surface.h"
+#include "cc/surfaces/surface_factory.h"
+#include "cc/surfaces/surface_factory_client.h"
+#include "cc/surfaces/surface_hittest.h"
+#include "cc/surfaces/surface_id_allocator.h"
+#include "cc/surfaces/surface_manager.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace cc {
+
+namespace {
+
+class EmptySurfaceFactoryClient : public SurfaceFactoryClient {
+ public:
+ void ReturnResources(const ReturnedResourceArray& resources) override {}
+};
+
+void CreateSharedQuadState(RenderPass* pass,
+ const gfx::Transform& transform,
+ const gfx::Rect& root_rect) {
+ SharedQuadState* child_shared_state =
+ pass->CreateAndAppendSharedQuadState();
+ child_shared_state->SetAll(transform,
+ root_rect.size(),
+ root_rect, root_rect, false, 1.0f,
+ SkXfermode::kSrcOver_Mode, 0);
+}
+
+void CreateSolidColorDrawQuad(RenderPass* pass,
+ const gfx::Transform& transform,
+ const gfx::Rect& root_rect,
+ const gfx::Rect& quad_rect) {
+ CreateSharedQuadState(pass, transform, root_rect);
+ SolidColorDrawQuad* color_quad =
+ pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
+ color_quad->SetNew(pass->shared_quad_state_list.back(),
+ quad_rect, quad_rect,
+ SK_ColorYELLOW, false);
+}
+
+void CreateRenderPassDrawQuad(RenderPass* pass,
+ const gfx::Transform& transform,
+ const gfx::Rect& root_rect,
+ const gfx::Rect& quad_rect,
+ const RenderPassId& render_pass_id) {
+ CreateSharedQuadState(pass, transform, root_rect);
+ RenderPassDrawQuad* render_pass_quad =
+ pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
+ render_pass_quad->SetNew(pass->shared_quad_state_list.back(),
+ quad_rect, quad_rect,
+ render_pass_id,
+ ResourceId(),
+ gfx::Vector2dF(),
+ gfx::Size(),
+ FilterOperations(),
+ gfx::Vector2dF(),
+ FilterOperations());
+}
+
+void CreateSurfaceDrawQuad(RenderPass* pass,
+ const gfx::Transform& transform,
+ const gfx::Rect& root_rect,
+ const gfx::Rect& quad_rect,
+ SurfaceId surface_id) {
+ CreateSharedQuadState(pass, transform, root_rect);
+ SurfaceDrawQuad* surface_quad =
+ pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
+ surface_quad->SetNew(pass->shared_quad_state_list.back(),
+ quad_rect, quad_rect,
+ surface_id);
+}
+
+void CreateRenderPass(const RenderPassId& render_pass_id,
+ const gfx::Rect& rect,
+ const gfx::Transform& transform_to_root_target,
+ RenderPassList* render_pass_list) {
+ scoped_ptr<RenderPass> render_pass = RenderPass::Create();
+ render_pass->SetNew(render_pass_id, rect, rect, transform_to_root_target);
+ render_pass_list->push_back(render_pass.Pass());
+}
+
+scoped_ptr<CompositorFrame> CreateCompositorFrameWithRenderPassList(
+ RenderPassList* render_pass_list) {
+ scoped_ptr<DelegatedFrameData> root_delegated_frame_data(
+ new DelegatedFrameData);
+ root_delegated_frame_data->render_pass_list.swap(*render_pass_list);
+ scoped_ptr<CompositorFrame> root_frame(new CompositorFrame);
+ root_frame->delegated_frame_data = root_delegated_frame_data.Pass();
+ return root_frame.Pass();
+}
+
+scoped_ptr<CompositorFrame> CreateCompositorFrame(
+ const gfx::Rect& root_rect,
+ RenderPass** render_pass) {
+ RenderPassList render_pass_list;
+ RenderPassId root_id(1, 1);
+ CreateRenderPass(root_id, root_rect, gfx::Transform(), &render_pass_list);
+
+ scoped_ptr<CompositorFrame> root_frame =
+ CreateCompositorFrameWithRenderPassList(&render_pass_list);
+
+ *render_pass = root_frame->delegated_frame_data->render_pass_list.back();
+ return root_frame.Pass();
+}
+
+} // namespace
+
+// This test verifies that hit testing on a surface that does not exist does
+// not crash.
+TEST(SurfaceHittestTest, Hittest_BadCompositorFrameDoesNotCrash) {
+ SurfaceManager manager;
+ EmptySurfaceFactoryClient client;
+ SurfaceFactory factory(&manager, &client);
+
+ // Creates a root surface.
+ gfx::Rect root_rect(300, 300);
+ RenderPass* root_pass = nullptr;
+ scoped_ptr<CompositorFrame> root_frame =
+ CreateCompositorFrame(root_rect, &root_pass);
+
+ // Add a reference to a non-existant child surface on the root surface.
+ SurfaceIdAllocator child_allocator(3);
+ SurfaceId child_surface_id;
+ child_surface_id.id = 0xdeadbeef;
+ gfx::Rect child_rect(200, 200);
+ CreateSurfaceDrawQuad(root_pass,
+ gfx::Transform(),
+ root_rect,
+ child_rect,
+ child_surface_id);
+
+ // Submit the root frame.
+ SurfaceIdAllocator root_allocator(2);
+ SurfaceId root_surface_id = root_allocator.GenerateId();
+ factory.Create(root_surface_id);
+ factory.SubmitCompositorFrame(root_surface_id, root_frame.Pass(),
+ SurfaceFactory::DrawCallback());
+
+ {
+ SurfaceHittest hittest(&manager);
+ // It is expected this test will complete without crashes.
+ gfx::Transform transform;
+ EXPECT_EQ(root_surface_id,
+ hittest.GetTargetSurfaceAtPoint(
+ root_surface_id, gfx::Point(100, 100), &transform));
+ }
+
+ factory.Destroy(root_surface_id);
+}
+
+TEST(SurfaceHittestTest, Hittest_SingleSurface) {
+ SurfaceManager manager;
+ EmptySurfaceFactoryClient client;
+ SurfaceFactory factory(&manager, &client);
+
+ // Creates a root surface.
+ gfx::Rect root_rect(300, 300);
+ RenderPass* root_pass = nullptr;
+ scoped_ptr<CompositorFrame> root_frame =
+ CreateCompositorFrame(root_rect, &root_pass);
+
+ // Submit the root frame.
+ SurfaceIdAllocator root_allocator(2);
+ SurfaceId root_surface_id = root_allocator.GenerateId();
+ factory.Create(root_surface_id);
+ factory.SubmitCompositorFrame(root_surface_id, root_frame.Pass(),
+ SurfaceFactory::DrawCallback());
+
+ {
+ SurfaceHittest hittest(&manager);
+ gfx::Point point(100, 100);
+ gfx::Transform transform;
+ EXPECT_EQ(root_surface_id, hittest.GetTargetSurfaceAtPoint(
+ root_surface_id, point, &transform));
+ transform.TransformPoint(&point);
+ EXPECT_EQ(gfx::Point(100, 100), point);
+ }
+
+ factory.Destroy(root_surface_id);
+}
+
+TEST(SurfaceHittestTest, Hittest_ChildSurface) {
+ SurfaceManager manager;
+ EmptySurfaceFactoryClient client;
+ SurfaceFactory factory(&manager, &client);
+
+ // Creates a root surface.
+ gfx::Rect root_rect(300, 300);
+ RenderPass* root_pass = nullptr;
+ scoped_ptr<CompositorFrame> root_frame =
+ CreateCompositorFrame(root_rect, &root_pass);
+
+ // Add a reference to the child surface on the root surface.
+ SurfaceIdAllocator child_allocator(3);
+ SurfaceId child_surface_id = child_allocator.GenerateId();
+ gfx::Rect child_rect(200, 200);
+ CreateSurfaceDrawQuad(root_pass,
+ gfx::Transform(1.0f, 0.0f, 0.0f, 50.0f,
+ 0.0f, 1.0f, 0.0f, 50.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f),
+ root_rect,
+ child_rect,
+ child_surface_id);
+
+ // Submit the root frame.
+ SurfaceIdAllocator root_allocator(2);
+ SurfaceId root_surface_id = root_allocator.GenerateId();
+ factory.Create(root_surface_id);
+ factory.SubmitCompositorFrame(root_surface_id, root_frame.Pass(),
+ SurfaceFactory::DrawCallback());
+
+ // Creates a child surface.
+ RenderPass* child_pass = nullptr;
+ scoped_ptr<CompositorFrame> child_frame =
+ CreateCompositorFrame(child_rect, &child_pass);
+
+ // Add a solid quad in the child surface.
+ gfx::Rect child_solid_quad_rect(100, 100);
+ CreateSolidColorDrawQuad(
+ child_pass,
+ gfx::Transform(1.0f, 0.0f, 0.0f, 50.0f, 0.0f, 1.0f, 0.0f, 50.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f),
+ root_rect, child_solid_quad_rect);
+
+ // Submit the frame.
+ factory.Create(child_surface_id);
+ factory.SubmitCompositorFrame(child_surface_id, child_frame.Pass(),
+ SurfaceFactory::DrawCallback());
+
+ struct Test {
+ SurfaceId input_surface_id;
+ gfx::Point input_point;
+ SurfaceId expected_output_surface_id;
+ gfx::Point expected_output_point;
+ } tests[] = {{root_surface_id, gfx::Point(10, 10), root_surface_id,
+ gfx::Point(10, 10)},
+ {root_surface_id, gfx::Point(99, 99), root_surface_id,
+ gfx::Point(99, 99)},
+ {root_surface_id, gfx::Point(100, 100), child_surface_id,
+ gfx::Point(50, 50)},
+ {root_surface_id, gfx::Point(199, 199), child_surface_id,
+ gfx::Point(149, 149)},
+ {root_surface_id, gfx::Point(200, 200), root_surface_id,
+ gfx::Point(200, 200)},
+ {root_surface_id, gfx::Point(290, 290), root_surface_id,
+ gfx::Point(290, 290)}};
+
+ SurfaceHittest hittest(&manager);
+ for (const auto& test : tests) {
+ gfx::Point point(test.input_point);
+ gfx::Transform transform;
+ EXPECT_EQ(test.expected_output_surface_id,
+ hittest.GetTargetSurfaceAtPoint(test.input_surface_id, point,
+ &transform));
+ transform.TransformPoint(&point);
+ EXPECT_EQ(test.expected_output_point, point);
+ }
+
+ factory.Destroy(root_surface_id);
+ factory.Destroy(child_surface_id);
+}
+
+// This test verifies that hit testing will progress to the next quad if it
+// encounters an invalid RenderPassDrawQuad for whatever reason.
+TEST(SurfaceHittestTest, Hittest_InvalidRenderPassDrawQuad) {
+ SurfaceManager manager;
+ EmptySurfaceFactoryClient client;
+ SurfaceFactory factory(&manager, &client);
+
+ // Creates a root surface.
+ gfx::Rect root_rect(300, 300);
+ RenderPass* root_pass = nullptr;
+ scoped_ptr<CompositorFrame> root_frame =
+ CreateCompositorFrame(root_rect, &root_pass);
+
+ // Create a RenderPassDrawQuad to a non-existant RenderPass.
+ CreateRenderPassDrawQuad(root_pass,
+ gfx::Transform(),
+ root_rect,
+ root_rect,
+ RenderPassId(1337, 1337));
+
+ // Add a reference to the child surface on the root surface.
+ SurfaceIdAllocator child_allocator(3);
+ SurfaceId child_surface_id = child_allocator.GenerateId();
+ gfx::Rect child_rect(200, 200);
+ CreateSurfaceDrawQuad(root_pass,
+ gfx::Transform(1.0f, 0.0f, 0.0f, 50.0f,
+ 0.0f, 1.0f, 0.0f, 50.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f),
+ root_rect,
+ child_rect,
+ child_surface_id);
+
+ // Submit the root frame.
+ SurfaceIdAllocator root_allocator(2);
+ SurfaceId root_surface_id = root_allocator.GenerateId();
+ factory.Create(root_surface_id);
+ factory.SubmitCompositorFrame(root_surface_id, root_frame.Pass(),
+ SurfaceFactory::DrawCallback());
+
+ // Creates a child surface.
+ RenderPass* child_pass = nullptr;
+ scoped_ptr<CompositorFrame> child_frame =
+ CreateCompositorFrame(child_rect, &child_pass);
+
+ // Add a solid quad in the child surface.
+ gfx::Rect child_solid_quad_rect(100, 100);
+ CreateSolidColorDrawQuad(child_pass,
+ gfx::Transform(1.0f, 0.0f, 0.0f, 50.0f,
+ 0.0f, 1.0f, 0.0f, 50.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f),
+ root_rect,
+ child_solid_quad_rect);
+
+ // Submit the frame.
+ factory.Create(child_surface_id);
+ factory.SubmitCompositorFrame(child_surface_id, child_frame.Pass(),
+ SurfaceFactory::DrawCallback());
+
+ struct Test {
+ SurfaceId input_surface_id;
+ gfx::Point input_point;
+ SurfaceId expected_output_surface_id;
+ gfx::Point expected_output_point;
+ } tests[] = {{root_surface_id, gfx::Point(10, 10), root_surface_id,
+ gfx::Point(10, 10)},
+ {root_surface_id, gfx::Point(99, 99), root_surface_id,
+ gfx::Point(99, 99)},
+ {root_surface_id, gfx::Point(100, 100), child_surface_id,
+ gfx::Point(50, 50)},
+ {root_surface_id, gfx::Point(199, 199), child_surface_id,
+ gfx::Point(149, 149)},
+ {root_surface_id, gfx::Point(200, 200), root_surface_id,
+ gfx::Point(200, 200)},
+ {root_surface_id, gfx::Point(290, 290), root_surface_id,
+ gfx::Point(290, 290)}};
+
+ SurfaceHittest hittest(&manager);
+ for (const auto& test : tests) {
+ gfx::Point point(test.input_point);
+ gfx::Transform transform;
+ EXPECT_EQ(test.expected_output_surface_id,
+ hittest.GetTargetSurfaceAtPoint(test.input_surface_id, point,
+ &transform));
+ transform.TransformPoint(&point);
+ EXPECT_EQ(test.expected_output_point, point);
+ }
+
+ factory.Destroy(root_surface_id);
+ factory.Destroy(child_surface_id);
+}
+
+TEST(SurfaceHittestTest, Hittest_RenderPassDrawQuad) {
+ SurfaceManager manager;
+ EmptySurfaceFactoryClient client;
+ SurfaceFactory factory(&manager, &client);
+
+ // Create a CompostiorFrame with two RenderPasses.
+ gfx::Rect root_rect(300, 300);
+ RenderPassList render_pass_list;
+
+ // Create a child RenderPass.
+ RenderPassId child_render_pass_id(1, 3);
+ gfx::Transform transform_to_root_target(1.0f, 0.0f, 0.0f, 50.0f,
+ 0.0f, 1.0f, 0.0f, 50.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f);
+ CreateRenderPass(child_render_pass_id,
+ gfx::Rect(100, 100),
+ transform_to_root_target,
+ &render_pass_list);
+
+ // Create the root RenderPass.
+ RenderPassId root_render_pass_id(1, 2);
+ CreateRenderPass(root_render_pass_id, root_rect, gfx::Transform(),
+ &render_pass_list);
+
+ RenderPass* root_pass = nullptr;
+ scoped_ptr<CompositorFrame> root_frame =
+ CreateCompositorFrameWithRenderPassList(&render_pass_list);
+ root_pass = root_frame->delegated_frame_data->render_pass_list.back();
+
+ // Create a RenderPassDrawQuad.
+ gfx::Rect render_pass_quad_rect(100, 100);
+ CreateRenderPassDrawQuad(root_pass,
+ transform_to_root_target,
+ root_rect,
+ render_pass_quad_rect,
+ child_render_pass_id);
+
+ // Add a solid quad in the child render pass.
+ RenderPass* child_render_pass =
+ root_frame->delegated_frame_data->render_pass_list.front();
+ gfx::Rect child_solid_quad_rect(100, 100);
+ CreateSolidColorDrawQuad(child_render_pass,
+ gfx::Transform(),
+ gfx::Rect(100, 100),
+ child_solid_quad_rect);
+
+ // Submit the root frame.
+ SurfaceIdAllocator root_allocator(1);
+ SurfaceId root_surface_id = root_allocator.GenerateId();
+ factory.Create(root_surface_id);
+ factory.SubmitCompositorFrame(root_surface_id, root_frame.Pass(),
+ SurfaceFactory::DrawCallback());
+
+ struct Test {
+ SurfaceId input_surface_id;
+ gfx::Point input_point;
+ SurfaceId expected_output_surface_id;
+ gfx::Point expected_output_point;
+ } tests[] = {
+ // These tests just miss the RenderPassDrawQuad.
+ {
+ root_surface_id,
+ gfx::Point(49, 49),
+ root_surface_id,
+ gfx::Point(49, 49)
+ },
+ {
+ root_surface_id,
+ gfx::Point(150, 150),
+ root_surface_id,
+ gfx::Point(150, 150)
+ },
+ // These tests just hit the boundaries of the
+ // RenderPassDrawQuad.
+ {
+ root_surface_id,
+ gfx::Point(50, 50),
+ root_surface_id,
+ gfx::Point(50, 50)
+ },
+ {
+ root_surface_id,
+ gfx::Point(149, 149),
+ root_surface_id,
+ gfx::Point(149, 149)
+ },
+ // These tests fall somewhere in the center of the
+ // RenderPassDrawQuad.
+ {
+ root_surface_id,
+ gfx::Point(99, 99),
+ root_surface_id,
+ gfx::Point(99, 99)
+ },
+ {
+ root_surface_id,
+ gfx::Point(100, 100),
+ root_surface_id,
+ gfx::Point(100, 100)
+ }
+ };
+
+ SurfaceHittest hittest(&manager);
+ for (const auto& test : tests) {
+ gfx::Point point(test.input_point);
+ gfx::Transform transform;
+ EXPECT_EQ(test.expected_output_surface_id,
+ hittest.GetTargetSurfaceAtPoint(test.input_surface_id, point,
+ &transform));
+ transform.TransformPoint(&point);
+ EXPECT_EQ(test.expected_output_point, point);
+ }
+
+ factory.Destroy(root_surface_id);
+}
+
+} // namespace cc
diff --git a/chromium/cc/surfaces/surfaces_pixeltest.cc b/chromium/cc/surfaces/surfaces_pixeltest.cc
index bf8ad57fb91..a584f7c806d 100644
--- a/chromium/cc/surfaces/surfaces_pixeltest.cc
+++ b/chromium/cc/surfaces/surfaces_pixeltest.cc
@@ -80,10 +80,10 @@ TEST_F(SurfacesPixelTest, DrawSimpleFrame) {
SurfaceId root_surface_id = allocator_.GenerateId();
factory_.Create(root_surface_id);
- factory_.SubmitFrame(root_surface_id, root_frame.Pass(),
- SurfaceFactory::DrawCallback());
+ factory_.SubmitCompositorFrame(root_surface_id, root_frame.Pass(),
+ SurfaceFactory::DrawCallback());
- SurfaceAggregator aggregator(&manager_, resource_provider_.get());
+ SurfaceAggregator aggregator(&manager_, resource_provider_.get(), true);
scoped_ptr<CompositorFrame> aggregated_frame =
aggregator.Aggregate(root_surface_id);
factory_.Destroy(root_surface_id);
@@ -135,8 +135,8 @@ TEST_F(SurfacesPixelTest, DrawSimpleAggregatedFrame) {
scoped_ptr<CompositorFrame> root_frame(new CompositorFrame);
root_frame->delegated_frame_data = delegated_frame_data.Pass();
- factory_.SubmitFrame(root_surface_id, root_frame.Pass(),
- SurfaceFactory::DrawCallback());
+ factory_.SubmitCompositorFrame(root_surface_id, root_frame.Pass(),
+ SurfaceFactory::DrawCallback());
}
{
@@ -163,11 +163,11 @@ TEST_F(SurfacesPixelTest, DrawSimpleAggregatedFrame) {
scoped_ptr<CompositorFrame> child_frame(new CompositorFrame);
child_frame->delegated_frame_data = delegated_frame_data.Pass();
- factory_.SubmitFrame(child_surface_id, child_frame.Pass(),
- SurfaceFactory::DrawCallback());
+ factory_.SubmitCompositorFrame(child_surface_id, child_frame.Pass(),
+ SurfaceFactory::DrawCallback());
}
- SurfaceAggregator aggregator(&manager_, resource_provider_.get());
+ SurfaceAggregator aggregator(&manager_, resource_provider_.get(), true);
scoped_ptr<CompositorFrame> aggregated_frame =
aggregator.Aggregate(root_surface_id);
@@ -234,8 +234,8 @@ TEST_F(SurfacesPixelTest, DrawAggregatedFrameWithSurfaceTransforms) {
scoped_ptr<CompositorFrame> root_frame(new CompositorFrame);
root_frame->delegated_frame_data = delegated_frame_data.Pass();
- factory_.SubmitFrame(root_surface_id, root_frame.Pass(),
- SurfaceFactory::DrawCallback());
+ factory_.SubmitCompositorFrame(root_surface_id, root_frame.Pass(),
+ SurfaceFactory::DrawCallback());
}
{
@@ -270,8 +270,8 @@ TEST_F(SurfacesPixelTest, DrawAggregatedFrameWithSurfaceTransforms) {
scoped_ptr<CompositorFrame> child_frame(new CompositorFrame);
child_frame->delegated_frame_data = delegated_frame_data.Pass();
- factory_.SubmitFrame(left_child_id, child_frame.Pass(),
- SurfaceFactory::DrawCallback());
+ factory_.SubmitCompositorFrame(left_child_id, child_frame.Pass(),
+ SurfaceFactory::DrawCallback());
}
{
@@ -306,11 +306,11 @@ TEST_F(SurfacesPixelTest, DrawAggregatedFrameWithSurfaceTransforms) {
scoped_ptr<CompositorFrame> child_frame(new CompositorFrame);
child_frame->delegated_frame_data = delegated_frame_data.Pass();
- factory_.SubmitFrame(right_child_id, child_frame.Pass(),
- SurfaceFactory::DrawCallback());
+ factory_.SubmitCompositorFrame(right_child_id, child_frame.Pass(),
+ SurfaceFactory::DrawCallback());
}
- SurfaceAggregator aggregator(&manager_, resource_provider_.get());
+ SurfaceAggregator aggregator(&manager_, resource_provider_.get(), true);
scoped_ptr<CompositorFrame> aggregated_frame =
aggregator.Aggregate(root_surface_id);
diff --git a/chromium/cc/tiles/image_decode_controller.cc b/chromium/cc/tiles/image_decode_controller.cc
new file mode 100644
index 00000000000..19e16c47ec6
--- /dev/null
+++ b/chromium/cc/tiles/image_decode_controller.cc
@@ -0,0 +1,120 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/tiles/image_decode_controller.h"
+
+#include "cc/debug/devtools_instrumentation.h"
+
+namespace cc {
+namespace {
+
+class ImageDecodeTaskImpl : public ImageDecodeTask {
+ public:
+ ImageDecodeTaskImpl(ImageDecodeController* controller,
+ const SkImage* image,
+ int layer_id,
+ uint64_t source_prepare_tiles_id)
+ : controller_(controller),
+ image_(skia::SharePtr(image)),
+ layer_id_(layer_id),
+ source_prepare_tiles_id_(source_prepare_tiles_id) {}
+
+ // Overridden from Task:
+ void RunOnWorkerThread() override {
+ TRACE_EVENT1("cc", "ImageDecodeTaskImpl::RunOnWorkerThread",
+ "source_prepare_tiles_id", source_prepare_tiles_id_);
+ devtools_instrumentation::ScopedImageDecodeTask image_decode_task(
+ image_.get());
+ controller_->DecodeImage(image_.get());
+
+ // Release the reference after decoding image to ensure that it is not kept
+ // alive unless needed.
+ image_.clear();
+ }
+
+ // Overridden from TileTask:
+ void ScheduleOnOriginThread(TileTaskClient* client) override {}
+ void CompleteOnOriginThread(TileTaskClient* client) override {
+ controller_->OnImageDecodeTaskCompleted(layer_id_, image_.get(),
+ !HasFinishedRunning());
+ }
+
+ protected:
+ ~ImageDecodeTaskImpl() override {}
+
+ private:
+ ImageDecodeController* controller_;
+ skia::RefPtr<const SkImage> image_;
+ int layer_id_;
+ uint64_t source_prepare_tiles_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(ImageDecodeTaskImpl);
+};
+
+} // namespace
+
+ImageDecodeController::ImageDecodeController() {}
+
+ImageDecodeController::~ImageDecodeController() {}
+
+scoped_refptr<ImageDecodeTask> ImageDecodeController::GetTaskForImage(
+ const PositionImage& image,
+ int layer_id,
+ uint64_t prepare_tiles_id) {
+ uint32_t generation_id = image.image->uniqueID();
+ scoped_refptr<ImageDecodeTask>& decode_task =
+ image_decode_tasks_[layer_id][generation_id];
+ if (!decode_task)
+ decode_task = CreateTaskForImage(image.image, layer_id, prepare_tiles_id);
+ return decode_task;
+}
+
+scoped_refptr<ImageDecodeTask> ImageDecodeController::CreateTaskForImage(
+ const SkImage* image,
+ int layer_id,
+ uint64_t prepare_tiles_id) {
+ return make_scoped_refptr(
+ new ImageDecodeTaskImpl(this, image, layer_id, prepare_tiles_id));
+}
+
+void ImageDecodeController::DecodeImage(const SkImage* image) {
+ image->preroll();
+}
+
+void ImageDecodeController::AddLayerUsedCount(int layer_id) {
+ ++used_layer_counts_[layer_id];
+}
+
+void ImageDecodeController::SubtractLayerUsedCount(int layer_id) {
+ if (--used_layer_counts_[layer_id])
+ return;
+
+ // Clean up decode tasks once a layer is no longer used.
+ used_layer_counts_.erase(layer_id);
+ image_decode_tasks_.erase(layer_id);
+}
+
+void ImageDecodeController::OnImageDecodeTaskCompleted(int layer_id,
+ const SkImage* image,
+ bool was_canceled) {
+ // If the task has successfully finished, then keep the task until the layer
+ // is no longer in use. This ensures that we only decode a image once.
+ // TODO(vmpstr): Remove this when decode lifetime is controlled by cc.
+ if (!was_canceled)
+ return;
+
+ // Otherwise, we have to clean up the task so that a new one can be created if
+ // we need to decode the image again.
+ LayerImageTaskMap::iterator layer_it = image_decode_tasks_.find(layer_id);
+ if (layer_it == image_decode_tasks_.end())
+ return;
+
+ ImageTaskMap& image_tasks = layer_it->second;
+ ImageTaskMap::iterator task_it = image_tasks.find(image->uniqueID());
+ if (task_it == image_tasks.end())
+ return;
+ image_tasks.erase(task_it);
+}
+
+} // namespace cc
diff --git a/chromium/cc/tiles/image_decode_controller.h b/chromium/cc/tiles/image_decode_controller.h
new file mode 100644
index 00000000000..e2016482b19
--- /dev/null
+++ b/chromium/cc/tiles/image_decode_controller.h
@@ -0,0 +1,53 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_TILES_IMAGE_DECODE_CONTROLLER_H_
+#define CC_TILES_IMAGE_DECODE_CONTROLLER_H_
+
+#include "base/containers/hash_tables.h"
+#include "base/memory/ref_counted.h"
+#include "cc/base/cc_export.h"
+#include "cc/playback/discardable_image_map.h"
+#include "cc/raster/tile_task_runner.h"
+#include "skia/ext/refptr.h"
+
+namespace cc {
+
+class ImageDecodeController {
+ public:
+ ImageDecodeController();
+ ~ImageDecodeController();
+
+ scoped_refptr<ImageDecodeTask> GetTaskForImage(const PositionImage& image,
+ int layer_id,
+ uint64_t prepare_tiles_id);
+
+ // Note that this function has to remain thread safe.
+ void DecodeImage(const SkImage* image);
+
+ // TODO(vmpstr): This should go away once the controller is decoding images
+ // based on priority and memory.
+ void AddLayerUsedCount(int layer_id);
+ void SubtractLayerUsedCount(int layer_id);
+
+ void OnImageDecodeTaskCompleted(int layer_id,
+ const SkImage* image,
+ bool was_canceled);
+
+ private:
+ scoped_refptr<ImageDecodeTask> CreateTaskForImage(const SkImage* image,
+ int layer_id,
+ uint64_t prepare_tiles_id);
+
+ using ImageTaskMap = base::hash_map<uint32_t, scoped_refptr<ImageDecodeTask>>;
+ using LayerImageTaskMap = base::hash_map<int, ImageTaskMap>;
+ LayerImageTaskMap image_decode_tasks_;
+
+ using LayerCountMap = base::hash_map<int, int>;
+ LayerCountMap used_layer_counts_;
+};
+
+} // namespace cc
+
+#endif // CC_TILES_IMAGE_DECODE_CONTROLLER_H_
diff --git a/chromium/cc/tiles/picture_layer_tiling.cc b/chromium/cc/tiles/picture_layer_tiling.cc
index ef31f58256b..be8a7940f70 100644
--- a/chromium/cc/tiles/picture_layer_tiling.cc
+++ b/chromium/cc/tiles/picture_layer_tiling.cc
@@ -38,11 +38,11 @@ scoped_ptr<PictureLayerTiling> PictureLayerTiling::Create(
float contents_scale,
scoped_refptr<RasterSource> raster_source,
PictureLayerTilingClient* client,
- size_t max_tiles_for_interest_area,
+ size_t tiling_interest_area_padding,
float skewport_target_time_in_seconds,
int skewport_extrapolation_limit_in_content_pixels) {
return make_scoped_ptr(new PictureLayerTiling(
- tree, contents_scale, raster_source, client, max_tiles_for_interest_area,
+ tree, contents_scale, raster_source, client, tiling_interest_area_padding,
skewport_target_time_in_seconds,
skewport_extrapolation_limit_in_content_pixels));
}
@@ -52,10 +52,10 @@ PictureLayerTiling::PictureLayerTiling(
float contents_scale,
scoped_refptr<RasterSource> raster_source,
PictureLayerTilingClient* client,
- size_t max_tiles_for_interest_area,
+ size_t tiling_interest_area_padding,
float skewport_target_time_in_seconds,
int skewport_extrapolation_limit_in_content_pixels)
- : max_tiles_for_interest_area_(max_tiles_for_interest_area),
+ : tiling_interest_area_padding_(tiling_interest_area_padding),
skewport_target_time_in_seconds_(skewport_target_time_in_seconds),
skewport_extrapolation_limit_in_content_pixels_(
skewport_extrapolation_limit_in_content_pixels),
@@ -64,6 +64,7 @@ PictureLayerTiling::PictureLayerTiling(
tree_(tree),
raster_source_(raster_source),
resolution_(NON_IDEAL_RESOLUTION),
+ may_contain_low_resolution_tiles_(false),
tiling_data_(gfx::Size(), gfx::Size(), kBorderTexels),
can_require_tiles_for_activation_(false),
current_content_to_screen_scale_(0.f),
@@ -73,12 +74,12 @@ PictureLayerTiling::PictureLayerTiling(
has_eventually_rect_tiles_(false),
all_tiles_done_(true) {
DCHECK(!raster_source->IsSolidColor());
- gfx::Size content_bounds = gfx::ToCeiledSize(
- gfx::ScaleSize(raster_source_->GetSize(), contents_scale));
+ gfx::Size content_bounds =
+ gfx::ScaleToCeiledSize(raster_source_->GetSize(), contents_scale);
gfx::Size tile_size = client_->CalculateTileSize(content_bounds);
- DCHECK(!gfx::ToFlooredSize(gfx::ScaleSize(raster_source_->GetSize(),
- contents_scale)).IsEmpty())
+ DCHECK(!gfx::ScaleToFlooredSize(raster_source_->GetSize(), contents_scale)
+ .IsEmpty())
<< "Tiling created with scale too small as contents become empty."
<< " Layer bounds: " << raster_source_->GetSize().ToString()
<< " Contents scale: " << contents_scale;
@@ -101,26 +102,29 @@ float PictureLayerTiling::CalculateSoonBorderDistance(
max_dimension * kSoonBorderDistanceViewportPercentage);
}
-Tile* PictureLayerTiling::CreateTile(int i, int j) {
+Tile* PictureLayerTiling::CreateTile(const Tile::CreateInfo& info) {
+ const int i = info.tiling_i_index;
+ const int j = info.tiling_j_index;
TileMapKey key(i, j);
DCHECK(tiles_.find(key) == tiles_.end());
- gfx::Rect paint_rect = tiling_data_.TileBoundsWithBorder(i, j);
- gfx::Rect tile_rect = paint_rect;
- tile_rect.set_size(tiling_data_.max_texture_size());
-
- if (!raster_source_->CoversRect(tile_rect, contents_scale_))
+ if (!raster_source_->CoversRect(info.enclosing_layer_rect))
return nullptr;
all_tiles_done_ = false;
- ScopedTilePtr tile = client_->CreateTile(contents_scale_, tile_rect);
+ ScopedTilePtr tile = client_->CreateTile(info);
Tile* raw_ptr = tile.get();
- tile->set_tiling_index(i, j);
tiles_.add(key, tile.Pass());
return raw_ptr;
}
void PictureLayerTiling::CreateMissingTilesInLiveTilesRect() {
+ const PictureLayerTiling* active_twin =
+ tree_ == PENDING_TREE ? client_->GetPendingOrActiveTwinTiling(this)
+ : nullptr;
+ const Region* invalidation =
+ active_twin ? client_->GetPendingInvalidation() : nullptr;
+
bool include_borders = false;
for (TilingData::Iterator iter(&tiling_data_, live_tiles_rect_,
include_borders);
@@ -130,8 +134,29 @@ void PictureLayerTiling::CreateMissingTilesInLiveTilesRect() {
if (find != tiles_.end())
continue;
- if (ShouldCreateTileAt(key.index_x, key.index_y))
- CreateTile(key.index_x, key.index_y);
+ Tile::CreateInfo info = CreateInfoForTile(key.index_x, key.index_y);
+ if (ShouldCreateTileAt(info)) {
+ Tile* tile = CreateTile(info);
+
+ // If this is the pending tree, then the active twin tiling may contain
+ // the previous content ID of these tiles. In that case, we need only
+ // partially raster the tile content.
+ if (tile && invalidation && TilingMatchesTileIndices(active_twin)) {
+ if (const Tile* old_tile =
+ active_twin->TileAt(key.index_x, key.index_y)) {
+ gfx::Rect tile_rect = tile->content_rect();
+ gfx::Rect invalidated;
+ for (Region::Iterator iter(*invalidation); iter.has_rect();
+ iter.next()) {
+ gfx::Rect invalid_content_rect =
+ gfx::ScaleToEnclosingRect(iter.rect(), contents_scale_);
+ invalid_content_rect.Intersect(tile_rect);
+ invalidated.Union(invalid_content_rect);
+ }
+ tile->SetInvalidated(invalidated, old_tile->id());
+ }
+ }
+ }
}
VerifyLiveTilesRect(false);
}
@@ -186,7 +211,7 @@ void PictureLayerTiling::SetRasterSourceAndResize(
raster_source_.swap(raster_source);
gfx::Size new_layer_bounds = raster_source_->GetSize();
gfx::Size content_bounds =
- gfx::ToCeiledSize(gfx::ScaleSize(new_layer_bounds, contents_scale_));
+ gfx::ScaleToCeiledSize(new_layer_bounds, contents_scale_);
gfx::Size tile_size = client_->CalculateTileSize(content_bounds);
if (tile_size != tiling_data_.max_texture_size()) {
@@ -242,15 +267,17 @@ void PictureLayerTiling::SetRasterSourceAndResize(
if (after_right > before_right) {
DCHECK_EQ(after_right, before_right + 1);
for (int j = before_top; j <= after_bottom; ++j) {
- if (ShouldCreateTileAt(after_right, j))
- CreateTile(after_right, j);
+ Tile::CreateInfo info = CreateInfoForTile(after_right, j);
+ if (ShouldCreateTileAt(info))
+ CreateTile(info);
}
}
if (after_bottom > before_bottom) {
DCHECK_EQ(after_bottom, before_bottom + 1);
for (int i = before_left; i <= before_right; ++i) {
- if (ShouldCreateTileAt(i, after_bottom))
- CreateTile(i, after_bottom);
+ Tile::CreateInfo info = CreateInfoForTile(i, after_bottom);
+ if (ShouldCreateTileAt(info))
+ CreateTile(info);
}
}
}
@@ -310,13 +337,26 @@ void PictureLayerTiling::RemoveTilesInRegion(const Region& layer_invalidation,
// tiles from knowing the invalidation rect and content id. crbug.com/490847
ScopedTilePtr old_tile = TakeTileAt(key.index_x, key.index_y);
if (recreate_tiles && old_tile) {
- if (Tile* tile = CreateTile(key.index_x, key.index_y))
+ Tile::CreateInfo info = CreateInfoForTile(key.index_x, key.index_y);
+ if (Tile* tile = CreateTile(info))
tile->SetInvalidated(invalid_content_rect, old_tile->id());
}
}
}
-bool PictureLayerTiling::ShouldCreateTileAt(int i, int j) const {
+Tile::CreateInfo PictureLayerTiling::CreateInfoForTile(int i, int j) const {
+ gfx::Rect tile_rect = tiling_data_.TileBoundsWithBorder(i, j);
+ tile_rect.set_size(tiling_data_.max_texture_size());
+ gfx::Rect enclosing_layer_rect =
+ gfx::ScaleToEnclosingRect(tile_rect, 1.f / contents_scale_);
+ return Tile::CreateInfo(i, j, enclosing_layer_rect, tile_rect,
+ contents_scale_);
+}
+
+bool PictureLayerTiling::ShouldCreateTileAt(
+ const Tile::CreateInfo& info) const {
+ const int i = info.tiling_i_index;
+ const int j = info.tiling_j_index;
// Active tree should always create a tile. The reason for this is that active
// tree represents content that we draw on screen, which means that whenever
// we check whether a tile should exist somewhere, the answer is yes. This
@@ -337,21 +377,16 @@ bool PictureLayerTiling::ShouldCreateTileAt(int i, int j) const {
if (!TilingMatchesTileIndices(active_twin))
return true;
- gfx::Rect paint_rect = tiling_data_.TileBoundsWithBorder(i, j);
- gfx::Rect tile_rect = paint_rect;
- tile_rect.set_size(tiling_data_.max_texture_size());
-
// If the active tree can't create a tile, because of its raster source, then
// the pending tree should create one.
- if (!active_twin->raster_source()->CoversRect(tile_rect, contents_scale()))
+ if (!active_twin->raster_source()->CoversRect(info.enclosing_layer_rect))
return true;
const Region* layer_invalidation = client_->GetPendingInvalidation();
- gfx::Rect layer_rect =
- gfx::ScaleToEnclosingRect(tile_rect, 1.f / contents_scale());
// If this tile is invalidated, then the pending tree should create one.
- if (layer_invalidation && layer_invalidation->Intersects(layer_rect))
+ if (layer_invalidation &&
+ layer_invalidation->Intersects(info.enclosing_layer_rect))
return true;
// If the active tree doesn't have a tile here, but it's in the pending tree's
@@ -359,7 +394,8 @@ bool PictureLayerTiling::ShouldCreateTileAt(int i, int j) const {
// if the pending visible rect is outside of the active tree's live tiles
// rect. In those situations, we need to block activation until we're ready to
// display content, which will have to come from the pending tree.
- if (!active_twin->TileAt(i, j) && current_visible_rect_.Intersects(tile_rect))
+ if (!active_twin->TileAt(i, j) &&
+ current_visible_rect_.Intersects(info.content_rect))
return true;
// In all other cases, the pending tree doesn't need to create a tile.
@@ -456,11 +492,10 @@ PictureLayerTiling::CoverageIterator::operator++() {
gfx::Rect content_rect = tiling_->tiling_data_.TileBounds(tile_i_, tile_j_);
current_geometry_rect_ =
- gfx::ScaleToEnclosingRect(content_rect,
- 1 / dest_to_content_scale_,
- 1 / dest_to_content_scale_);
+ gfx::ScaleToEnclosingRect(content_rect, 1 / dest_to_content_scale_);
current_geometry_rect_.Intersect(dest_rect_);
+ DCHECK(!current_geometry_rect_.IsEmpty());
if (first_time)
return *this;
@@ -503,7 +538,7 @@ gfx::RectF PictureLayerTiling::CoverageIterator::texture_rect() const {
gfx::RectF texture_rect(current_geometry_rect_);
texture_rect.Scale(dest_to_content_scale_,
dest_to_content_scale_);
- texture_rect.Intersect(gfx::Rect(tiling_->tiling_size()));
+ texture_rect.Intersect(gfx::RectF(gfx::SizeF(tiling_->tiling_size())));
if (texture_rect.IsEmpty())
return texture_rect;
texture_rect.Offset(-tex_origin.OffsetFromOrigin());
@@ -626,22 +661,24 @@ bool PictureLayerTiling::ComputeTilePriorityRects(
// Calculate the eventually/live tiles rect.
gfx::Size tile_size = tiling_data_.max_texture_size();
- int64 eventually_rect_area =
- max_tiles_for_interest_area_ * tile_size.width() * tile_size.height();
-
- gfx::Rect eventually_rect =
- ExpandRectEquallyToAreaBoundedBy(visible_rect_in_content_space,
- eventually_rect_area,
- gfx::Rect(tiling_size()),
- &expansion_cache_);
- DCHECK(eventually_rect.IsEmpty() ||
- gfx::Rect(tiling_size()).Contains(eventually_rect))
+ float content_to_screen_scale = ideal_contents_scale / contents_scale_;
+ int pad_in_content_space =
+ static_cast<int>(tiling_interest_area_padding_ / content_to_screen_scale);
+ gfx::Rect eventually_rect = visible_rect_in_content_space;
+ // If the visible rect is empty, keep the eventually rect as empty.
+ if (!eventually_rect.IsEmpty()) {
+ eventually_rect.Inset(-pad_in_content_space, -pad_in_content_space);
+ eventually_rect =
+ tiling_data_.ExpandRectIgnoringBordersToTileBounds(eventually_rect);
+ }
+
+ DCHECK_IMPLIES(!eventually_rect.IsEmpty(),
+ gfx::Rect(tiling_size()).Contains(eventually_rect))
<< "tiling_size: " << tiling_size().ToString()
<< " eventually_rect: " << eventually_rect.ToString();
// Calculate the soon border rect.
- float content_to_screen_scale = ideal_contents_scale / contents_scale_;
gfx::Rect soon_border_rect = visible_rect_in_content_space;
float border = CalculateSoonBorderDistance(visible_rect_in_content_space,
content_to_screen_scale);
@@ -696,13 +733,21 @@ void PictureLayerTiling::SetLiveTilesRect(
RemoveTileAt(iter.index_x(), iter.index_y());
}
+ // We don't rasterize non ideal resolution tiles, so there is no need to
+ // create any new tiles.
+ if (resolution_ == NON_IDEAL_RESOLUTION) {
+ live_tiles_rect_.Intersect(new_live_tiles_rect);
+ VerifyLiveTilesRect(false);
+ return;
+ }
+
// Iterate to allocate new tiles for all regions with newly exposed area.
for (TilingData::DifferenceIterator iter(&tiling_data_, new_live_tiles_rect,
live_tiles_rect_);
iter; ++iter) {
- TileMapKey key(iter.index());
- if (ShouldCreateTileAt(key.index_x, key.index_y))
- CreateTile(key.index_x, key.index_y);
+ Tile::CreateInfo info = CreateInfoForTile(iter.index_x(), iter.index_y());
+ if (ShouldCreateTileAt(info))
+ CreateTile(info);
}
live_tiles_rect_ = new_live_tiles_rect;
@@ -853,11 +898,11 @@ PrioritizedTile PictureLayerTiling::MakePrioritizedTile(
Tile* tile,
PriorityRectType priority_rect_type) const {
DCHECK(tile);
- DCHECK(
- raster_source()->CoversRect(tile->content_rect(), tile->contents_scale()))
+ DCHECK(raster_source()->CoversRect(tile->enclosing_layer_rect()))
<< "Recording rect: "
<< gfx::ScaleToEnclosingRect(tile->content_rect(),
- 1.f / tile->contents_scale()).ToString();
+ 1.f / tile->contents_scale())
+ .ToString();
return PrioritizedTile(tile, raster_source(),
ComputePriorityForTile(tile, priority_rect_type),
@@ -966,155 +1011,4 @@ size_t PictureLayerTiling::GPUMemoryUsageInBytes() const {
return amount;
}
-PictureLayerTiling::RectExpansionCache::RectExpansionCache()
- : previous_target(0) {
-}
-
-namespace {
-
-// This struct represents an event at which the expending rect intersects
-// one of its boundaries. 4 intersection events will occur during expansion.
-struct EdgeEvent {
- enum { BOTTOM, TOP, LEFT, RIGHT } edge;
- int* num_edges;
- int distance;
-};
-
-// Compute the delta to expand from edges to cover target_area.
-int ComputeExpansionDelta(int num_x_edges, int num_y_edges,
- int width, int height,
- int64 target_area) {
- // Compute coefficients for the quadratic equation:
- // a*x^2 + b*x + c = 0
- int a = num_y_edges * num_x_edges;
- int b = num_y_edges * width + num_x_edges * height;
- int64 c = static_cast<int64>(width) * height - target_area;
-
- // Compute the delta for our edges using the quadratic equation.
- int delta =
- (a == 0) ? -c / b : (-b + static_cast<int>(std::sqrt(
- static_cast<int64>(b) * b - 4.0 * a * c))) /
- (2 * a);
- return std::max(0, delta);
-}
-
-} // namespace
-
-gfx::Rect PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
- const gfx::Rect& starting_rect,
- int64 target_area,
- const gfx::Rect& bounding_rect,
- RectExpansionCache* cache) {
- if (starting_rect.IsEmpty())
- return starting_rect;
-
- if (cache &&
- cache->previous_start == starting_rect &&
- cache->previous_bounds == bounding_rect &&
- cache->previous_target == target_area)
- return cache->previous_result;
-
- if (cache) {
- cache->previous_start = starting_rect;
- cache->previous_bounds = bounding_rect;
- cache->previous_target = target_area;
- }
-
- DCHECK(!bounding_rect.IsEmpty());
- DCHECK_GT(target_area, 0);
-
- // Expand the starting rect to cover target_area, if it is smaller than it.
- int delta = ComputeExpansionDelta(
- 2, 2, starting_rect.width(), starting_rect.height(), target_area);
- gfx::Rect expanded_starting_rect = starting_rect;
- if (delta > 0)
- expanded_starting_rect.Inset(-delta, -delta);
-
- gfx::Rect rect = IntersectRects(expanded_starting_rect, bounding_rect);
- if (rect.IsEmpty()) {
- // The starting_rect and bounding_rect are far away.
- if (cache)
- cache->previous_result = rect;
- return rect;
- }
- if (delta >= 0 && rect == expanded_starting_rect) {
- // The starting rect already covers the entire bounding_rect and isn't too
- // large for the target_area.
- if (cache)
- cache->previous_result = rect;
- return rect;
- }
-
- // Continue to expand/shrink rect to let it cover target_area.
-
- // These values will be updated by the loop and uses as the output.
- int origin_x = rect.x();
- int origin_y = rect.y();
- int width = rect.width();
- int height = rect.height();
-
- // In the beginning we will consider 2 edges in each dimension.
- int num_y_edges = 2;
- int num_x_edges = 2;
-
- // Create an event list.
- EdgeEvent events[] = {
- { EdgeEvent::BOTTOM, &num_y_edges, rect.y() - bounding_rect.y() },
- { EdgeEvent::TOP, &num_y_edges, bounding_rect.bottom() - rect.bottom() },
- { EdgeEvent::LEFT, &num_x_edges, rect.x() - bounding_rect.x() },
- { EdgeEvent::RIGHT, &num_x_edges, bounding_rect.right() - rect.right() }
- };
-
- // Sort the events by distance (closest first).
- if (events[0].distance > events[1].distance) std::swap(events[0], events[1]);
- if (events[2].distance > events[3].distance) std::swap(events[2], events[3]);
- if (events[0].distance > events[2].distance) std::swap(events[0], events[2]);
- if (events[1].distance > events[3].distance) std::swap(events[1], events[3]);
- if (events[1].distance > events[2].distance) std::swap(events[1], events[2]);
-
- for (int event_index = 0; event_index < 4; event_index++) {
- const EdgeEvent& event = events[event_index];
-
- int delta = ComputeExpansionDelta(
- num_x_edges, num_y_edges, width, height, target_area);
-
- // Clamp delta to our event distance.
- if (delta > event.distance)
- delta = event.distance;
-
- // Adjust the edge count for this kind of edge.
- --*event.num_edges;
-
- // Apply the delta to the edges and edge events.
- for (int i = event_index; i < 4; i++) {
- switch (events[i].edge) {
- case EdgeEvent::BOTTOM:
- origin_y -= delta;
- height += delta;
- break;
- case EdgeEvent::TOP:
- height += delta;
- break;
- case EdgeEvent::LEFT:
- origin_x -= delta;
- width += delta;
- break;
- case EdgeEvent::RIGHT:
- width += delta;
- break;
- }
- events[i].distance -= delta;
- }
-
- // If our delta is less then our event distance, we're done.
- if (delta < event.distance)
- break;
- }
-
- gfx::Rect result(origin_x, origin_y, width, height);
- if (cache)
- cache->previous_result = result;
- return result;
-}
-
} // namespace cc
diff --git a/chromium/cc/tiles/picture_layer_tiling.h b/chromium/cc/tiles/picture_layer_tiling.h
index 721f9e1e340..08380b1d78c 100644
--- a/chromium/cc/tiles/picture_layer_tiling.h
+++ b/chromium/cc/tiles/picture_layer_tiling.h
@@ -36,8 +36,7 @@ class CC_EXPORT PictureLayerTilingClient {
public:
// Create a tile at the given content_rect (in the contents scale of the
// tiling) This might return null if the client cannot create such a tile.
- virtual ScopedTilePtr CreateTile(float contents_scale,
- const gfx::Rect& content_rect) = 0;
+ virtual ScopedTilePtr CreateTile(const Tile::CreateInfo& info) = 0;
virtual gfx::Size CalculateTileSize(
const gfx::Size& content_bounds) const = 0;
// This invalidation region defines the area (if any, it can by null) that
@@ -98,7 +97,7 @@ class CC_EXPORT PictureLayerTiling {
float contents_scale,
scoped_refptr<RasterSource> raster_source,
PictureLayerTilingClient* client,
- size_t max_tiles_for_interest_area,
+ size_t tiling_interest_area_padding,
float skewport_target_time_in_seconds,
int skewport_extrapolation_limit_in_content_pixels);
@@ -111,8 +110,17 @@ class CC_EXPORT PictureLayerTiling {
bool IsTileRequiredForActivation(const Tile* tile) const;
bool IsTileRequiredForDraw(const Tile* tile) const;
- void set_resolution(TileResolution resolution) { resolution_ = resolution; }
+ void set_resolution(TileResolution resolution) {
+ resolution_ = resolution;
+ may_contain_low_resolution_tiles_ |= resolution == LOW_RESOLUTION;
+ }
TileResolution resolution() const { return resolution_; }
+ bool may_contain_low_resolution_tiles() const {
+ return may_contain_low_resolution_tiles_;
+ }
+ void reset_may_contain_low_resolution_tiles() {
+ may_contain_low_resolution_tiles_ = false;
+ }
void set_can_require_tiles_for_activation(bool can_require_tiles) {
can_require_tiles_for_activation_ = can_require_tiles;
}
@@ -240,22 +248,6 @@ class CC_EXPORT PictureLayerTiling {
void AsValueInto(base::trace_event::TracedValue* array) const;
size_t GPUMemoryUsageInBytes() const;
- struct RectExpansionCache {
- RectExpansionCache();
-
- gfx::Rect previous_start;
- gfx::Rect previous_bounds;
- gfx::Rect previous_result;
- int64 previous_target;
- };
-
- static
- gfx::Rect ExpandRectEquallyToAreaBoundedBy(
- const gfx::Rect& starting_rect,
- int64 target_area,
- const gfx::Rect& bounding_rect,
- RectExpansionCache* cache);
-
protected:
friend class CoverageIterator;
friend class PrioritizedTile;
@@ -287,12 +279,12 @@ class CC_EXPORT PictureLayerTiling {
float contents_scale,
scoped_refptr<RasterSource> raster_source,
PictureLayerTilingClient* client,
- size_t max_tiles_for_interest_area,
+ size_t tiling_interest_area_padding,
float skewport_target_time_in_seconds,
int skewport_extrapolation_limit_in_content_pixels);
void SetLiveTilesRect(const gfx::Rect& live_tiles_rect);
void VerifyLiveTilesRect(bool is_on_recycle_tree) const;
- Tile* CreateTile(int i, int j);
+ Tile* CreateTile(const Tile::CreateInfo& info);
ScopedTilePtr TakeTileAt(int i, int j);
// Returns true if the Tile existed and was removed from the tiling.
bool RemoveTileAt(int i, int j);
@@ -333,7 +325,8 @@ class CC_EXPORT PictureLayerTiling {
visible_rect_history_[1] = visible_rect_history_[0];
}
bool IsTileOccludedOnCurrentTree(const Tile* tile) const;
- bool ShouldCreateTileAt(int i, int j) const;
+ Tile::CreateInfo CreateInfoForTile(int i, int j) const;
+ bool ShouldCreateTileAt(const Tile::CreateInfo& info) const;
bool IsTileOccluded(const Tile* tile) const;
void UpdateRequiredStatesOnTile(Tile* tile) const;
PrioritizedTile MakePrioritizedTile(
@@ -375,7 +368,7 @@ class CC_EXPORT PictureLayerTiling {
}
void RemoveTilesInRegion(const Region& layer_region, bool recreate_tiles);
- const size_t max_tiles_for_interest_area_;
+ const size_t tiling_interest_area_padding_;
const float skewport_target_time_in_seconds_;
const int skewport_extrapolation_limit_in_content_pixels_;
@@ -385,6 +378,7 @@ class CC_EXPORT PictureLayerTiling {
const WhichTree tree_;
scoped_refptr<RasterSource> raster_source_;
TileResolution resolution_;
+ bool may_contain_low_resolution_tiles_;
// Internal data.
TilingData tiling_data_;
@@ -414,8 +408,6 @@ class CC_EXPORT PictureLayerTiling {
private:
DISALLOW_ASSIGN(PictureLayerTiling);
-
- RectExpansionCache expansion_cache_;
};
} // namespace cc
diff --git a/chromium/cc/tiles/picture_layer_tiling_perftest.cc b/chromium/cc/tiles/picture_layer_tiling_perftest.cc
index f27c227edcc..f996edc1792 100644
--- a/chromium/cc/tiles/picture_layer_tiling_perftest.cc
+++ b/chromium/cc/tiles/picture_layer_tiling_perftest.cc
@@ -5,10 +5,10 @@
#include "cc/debug/lap_timer.h"
#include "cc/resources/resource_provider.h"
#include "cc/resources/scoped_resource.h"
+#include "cc/test/fake_display_list_raster_source.h"
#include "cc/test/fake_output_surface.h"
#include "cc/test/fake_output_surface_client.h"
#include "cc/test/fake_picture_layer_tiling_client.h"
-#include "cc/test/fake_picture_pile_impl.h"
#include "cc/test/fake_resource_provider.h"
#include "cc/test/test_context_provider.h"
#include "cc/test/test_shared_bitmap_manager.h"
@@ -44,12 +44,12 @@ class PictureLayerTilingPerfTest : public testing::Test {
void SetUp() override {
LayerTreeSettings defaults;
picture_layer_tiling_client_.SetTileSize(gfx::Size(256, 256));
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
+ scoped_refptr<FakeDisplayListRasterSource> raster_source =
+ FakeDisplayListRasterSource::CreateFilled(
gfx::Size(256 * 50, 256 * 50));
picture_layer_tiling_ = PictureLayerTiling::Create(
- PENDING_TREE, 1.f, pile, &picture_layer_tiling_client_,
- defaults.max_tiles_for_interest_area,
+ PENDING_TREE, 1.f, raster_source, &picture_layer_tiling_client_,
+ defaults.tiling_interest_area_padding,
defaults.skewport_target_time_in_seconds,
defaults.skewport_extrapolation_limit_in_content_pixels);
picture_layer_tiling_->CreateAllTilesForTesting();
diff --git a/chromium/cc/tiles/picture_layer_tiling_set.cc b/chromium/cc/tiles/picture_layer_tiling_set.cc
index c820e81ce1a..a9e16f58a73 100644
--- a/chromium/cc/tiles/picture_layer_tiling_set.cc
+++ b/chromium/cc/tiles/picture_layer_tiling_set.cc
@@ -33,11 +33,11 @@ inline float LargerRatio(float float1, float float2) {
scoped_ptr<PictureLayerTilingSet> PictureLayerTilingSet::Create(
WhichTree tree,
PictureLayerTilingClient* client,
- size_t max_tiles_for_interest_area,
+ size_t tiling_interest_area_padding,
float skewport_target_time_in_seconds,
int skewport_extrapolation_limit_in_content_pixels) {
return make_scoped_ptr(new PictureLayerTilingSet(
- tree, client, max_tiles_for_interest_area,
+ tree, client, tiling_interest_area_padding,
skewport_target_time_in_seconds,
skewport_extrapolation_limit_in_content_pixels));
}
@@ -45,16 +45,15 @@ scoped_ptr<PictureLayerTilingSet> PictureLayerTilingSet::Create(
PictureLayerTilingSet::PictureLayerTilingSet(
WhichTree tree,
PictureLayerTilingClient* client,
- size_t max_tiles_for_interest_area,
+ size_t tiling_interest_area_padding,
float skewport_target_time_in_seconds,
int skewport_extrapolation_limit_in_content_pixels)
- : max_tiles_for_interest_area_(max_tiles_for_interest_area),
+ : tiling_interest_area_padding_(tiling_interest_area_padding),
skewport_target_time_in_seconds_(skewport_target_time_in_seconds),
skewport_extrapolation_limit_in_content_pixels_(
skewport_extrapolation_limit_in_content_pixels),
tree_(tree),
- client_(client) {
-}
+ client_(client) {}
PictureLayerTilingSet::~PictureLayerTilingSet() {
}
@@ -78,7 +77,7 @@ void PictureLayerTilingSet::CopyTilingsAndPropertiesFromPendingTwin(
if (!this_tiling) {
scoped_ptr<PictureLayerTiling> new_tiling = PictureLayerTiling::Create(
tree_, contents_scale, raster_source, client_,
- max_tiles_for_interest_area_, skewport_target_time_in_seconds_,
+ tiling_interest_area_padding_, skewport_target_time_in_seconds_,
skewport_extrapolation_limit_in_content_pixels_);
tilings_.push_back(new_tiling.Pass());
this_tiling = tilings_.back();
@@ -120,8 +119,12 @@ void PictureLayerTilingSet::UpdateTilingsToCurrentRasterSourceForActivation(
tiling->CreateMissingTilesInLiveTilesRect();
// |this| is active set and |tiling| is not in the pending set, which means
- // it is now NON_IDEAL_RESOLUTION.
- tiling->set_resolution(NON_IDEAL_RESOLUTION);
+ // it is now NON_IDEAL_RESOLUTION. The exception is for LOW_RESOLUTION
+ // tilings, which are computed and created entirely on the active tree.
+ // Since the pending tree does not have them, we should just leave them as
+ // low resolution to not lose them.
+ if (tiling->resolution() != LOW_RESOLUTION)
+ tiling->set_resolution(NON_IDEAL_RESOLUTION);
}
VerifyTilings(pending_twin_set);
@@ -197,16 +200,7 @@ void PictureLayerTilingSet::CleanUpTilings(
float min_acceptable_high_res_scale,
float max_acceptable_high_res_scale,
const std::vector<PictureLayerTiling*>& needed_tilings,
- bool should_have_low_res,
PictureLayerTilingSet* twin_set) {
- float twin_low_res_scale = 0.f;
- if (twin_set) {
- PictureLayerTiling* tiling =
- twin_set->FindTilingWithResolution(LOW_RESOLUTION);
- if (tiling)
- twin_low_res_scale = tiling->contents_scale();
- }
-
std::vector<PictureLayerTiling*> to_remove;
for (auto* tiling : tilings_) {
// Keep all tilings within the min/max scales.
@@ -215,12 +209,9 @@ void PictureLayerTilingSet::CleanUpTilings(
continue;
}
- // Keep low resolution tilings, if the tiling set should have them.
- if (should_have_low_res &&
- (tiling->resolution() == LOW_RESOLUTION ||
- tiling->contents_scale() == twin_low_res_scale)) {
+ // Keep low resolution tilings.
+ if (tiling->resolution() == LOW_RESOLUTION)
continue;
- }
// Don't remove tilings that are required.
if (std::find(needed_tilings.begin(), needed_tilings.end(), tiling) !=
@@ -259,7 +250,7 @@ PictureLayerTiling* PictureLayerTilingSet::AddTiling(
tilings_.push_back(PictureLayerTiling::Create(
tree_, contents_scale, raster_source, client_,
- max_tiles_for_interest_area_, skewport_target_time_in_seconds_,
+ tiling_interest_area_padding_, skewport_target_time_in_seconds_,
skewport_extrapolation_limit_in_content_pixels_));
PictureLayerTiling* appended = tilings_.back();
diff --git a/chromium/cc/tiles/picture_layer_tiling_set.h b/chromium/cc/tiles/picture_layer_tiling_set.h
index dcaf77586ff..b3e22fe34af 100644
--- a/chromium/cc/tiles/picture_layer_tiling_set.h
+++ b/chromium/cc/tiles/picture_layer_tiling_set.h
@@ -40,7 +40,7 @@ class CC_EXPORT PictureLayerTilingSet {
static scoped_ptr<PictureLayerTilingSet> Create(
WhichTree tree,
PictureLayerTilingClient* client,
- size_t max_tiles_for_interest_area,
+ size_t tiling_interest_area_padding,
float skewport_target_time_in_seconds,
int skewport_extrapolation_limit_in_content);
@@ -51,7 +51,6 @@ class CC_EXPORT PictureLayerTilingSet {
void CleanUpTilings(float min_acceptable_high_res_scale,
float max_acceptable_high_res_scale,
const std::vector<PictureLayerTiling*>& needed_tilings,
- bool should_have_low_res,
PictureLayerTilingSet* twin_set);
void RemoveNonIdealTilings();
@@ -175,7 +174,7 @@ class CC_EXPORT PictureLayerTilingSet {
explicit PictureLayerTilingSet(
WhichTree tree,
PictureLayerTilingClient* client,
- size_t max_tiles_for_interest_area,
+ size_t tiling_interest_area_padding,
float skewport_target_time_in_seconds,
int skewport_extrapolation_limit_in_content_pixels);
@@ -190,7 +189,7 @@ class CC_EXPORT PictureLayerTilingSet {
ScopedPtrVector<PictureLayerTiling> tilings_;
- const size_t max_tiles_for_interest_area_;
+ const size_t tiling_interest_area_padding_;
const float skewport_target_time_in_seconds_;
const int skewport_extrapolation_limit_in_content_pixels_;
WhichTree tree_;
diff --git a/chromium/cc/tiles/picture_layer_tiling_set_unittest.cc b/chromium/cc/tiles/picture_layer_tiling_set_unittest.cc
index e7593cde80b..a8afd820547 100644
--- a/chromium/cc/tiles/picture_layer_tiling_set_unittest.cc
+++ b/chromium/cc/tiles/picture_layer_tiling_set_unittest.cc
@@ -8,10 +8,10 @@
#include <vector>
#include "cc/resources/resource_provider.h"
+#include "cc/test/fake_display_list_raster_source.h"
#include "cc/test/fake_output_surface.h"
#include "cc/test/fake_output_surface_client.h"
#include "cc/test/fake_picture_layer_tiling_client.h"
-#include "cc/test/fake_picture_pile_impl.h"
#include "cc/test/fake_resource_provider.h"
#include "cc/test/test_shared_bitmap_manager.h"
#include "cc/trees/layer_tree_settings.h"
@@ -25,7 +25,7 @@ scoped_ptr<PictureLayerTilingSet> CreateTilingSet(
PictureLayerTilingClient* client) {
LayerTreeSettings defaults;
return PictureLayerTilingSet::Create(
- ACTIVE_TREE, client, defaults.max_tiles_for_interest_area,
+ ACTIVE_TREE, client, defaults.tiling_interest_area_padding,
defaults.skewport_target_time_in_seconds,
defaults.skewport_extrapolation_limit_in_content_pixels);
}
@@ -36,16 +36,16 @@ TEST(PictureLayerTilingSetTest, NoResources) {
scoped_ptr<PictureLayerTilingSet> set = CreateTilingSet(&client);
client.SetTileSize(gfx::Size(256, 256));
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateEmptyPileWithDefaultTileSize(layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> raster_source =
+ FakeDisplayListRasterSource::CreateEmpty(layer_bounds);
- set->AddTiling(1.0, pile);
- set->AddTiling(1.5, pile);
- set->AddTiling(2.0, pile);
+ set->AddTiling(1.0, raster_source);
+ set->AddTiling(1.5, raster_source);
+ set->AddTiling(2.0, raster_source);
float contents_scale = 2.0;
gfx::Size content_bounds(
- gfx::ToCeiledSize(gfx::ScaleSize(layer_bounds, contents_scale)));
+ gfx::ScaleToCeiledSize(layer_bounds, contents_scale));
gfx::Rect content_rect(content_bounds);
Region remaining(content_rect);
@@ -74,17 +74,17 @@ TEST(PictureLayerTilingSetTest, TilingRange) {
PictureLayerTiling* high_res_tiling;
PictureLayerTiling* low_res_tiling;
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
scoped_ptr<PictureLayerTilingSet> set = CreateTilingSet(&client);
- set->AddTiling(2.0, pile);
- high_res_tiling = set->AddTiling(1.0, pile);
+ set->AddTiling(2.0, raster_source);
+ high_res_tiling = set->AddTiling(1.0, raster_source);
high_res_tiling->set_resolution(HIGH_RESOLUTION);
- set->AddTiling(0.5, pile);
- low_res_tiling = set->AddTiling(0.25, pile);
+ set->AddTiling(0.5, raster_source);
+ low_res_tiling = set->AddTiling(0.25, raster_source);
low_res_tiling->set_resolution(LOW_RESOLUTION);
- set->AddTiling(0.125, pile);
+ set->AddTiling(0.125, raster_source);
higher_than_high_res_range =
set->GetTilingRange(PictureLayerTilingSet::HIGHER_THAN_HIGH_RES);
@@ -111,11 +111,11 @@ TEST(PictureLayerTilingSetTest, TilingRange) {
scoped_ptr<PictureLayerTilingSet> set_without_low_res =
CreateTilingSet(&client);
- set_without_low_res->AddTiling(2.0, pile);
- high_res_tiling = set_without_low_res->AddTiling(1.0, pile);
+ set_without_low_res->AddTiling(2.0, raster_source);
+ high_res_tiling = set_without_low_res->AddTiling(1.0, raster_source);
high_res_tiling->set_resolution(HIGH_RESOLUTION);
- set_without_low_res->AddTiling(0.5, pile);
- set_without_low_res->AddTiling(0.25, pile);
+ set_without_low_res->AddTiling(0.5, raster_source);
+ set_without_low_res->AddTiling(0.25, raster_source);
higher_than_high_res_range = set_without_low_res->GetTilingRange(
PictureLayerTilingSet::HIGHER_THAN_HIGH_RES);
@@ -142,9 +142,11 @@ TEST(PictureLayerTilingSetTest, TilingRange) {
scoped_ptr<PictureLayerTilingSet> set_with_only_high_and_low_res =
CreateTilingSet(&client);
- high_res_tiling = set_with_only_high_and_low_res->AddTiling(1.0, pile);
+ high_res_tiling =
+ set_with_only_high_and_low_res->AddTiling(1.0, raster_source);
high_res_tiling->set_resolution(HIGH_RESOLUTION);
- low_res_tiling = set_with_only_high_and_low_res->AddTiling(0.5, pile);
+ low_res_tiling =
+ set_with_only_high_and_low_res->AddTiling(0.5, raster_source);
low_res_tiling->set_resolution(LOW_RESOLUTION);
higher_than_high_res_range = set_with_only_high_and_low_res->GetTilingRange(
@@ -174,7 +176,7 @@ TEST(PictureLayerTilingSetTest, TilingRange) {
scoped_ptr<PictureLayerTilingSet> set_with_only_high_res =
CreateTilingSet(&client);
- high_res_tiling = set_with_only_high_res->AddTiling(1.0, pile);
+ high_res_tiling = set_with_only_high_res->AddTiling(1.0, raster_source);
high_res_tiling->set_resolution(HIGH_RESOLUTION);
higher_than_high_res_range = set_with_only_high_res->GetTilingRange(
@@ -223,12 +225,13 @@ class PictureLayerTilingSetTestWithResources : public testing::Test {
client.SetTileSize(gfx::Size(256, 256));
gfx::Size layer_bounds(1000, 800);
scoped_ptr<PictureLayerTilingSet> set = CreateTilingSet(&client);
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
float scale = min_scale;
for (int i = 0; i < num_tilings; ++i, scale += scale_increment) {
- PictureLayerTiling* tiling = set->AddTiling(scale, pile);
+ PictureLayerTiling* tiling = set->AddTiling(scale, raster_source);
+ tiling->set_resolution(HIGH_RESOLUTION);
tiling->CreateAllTilesForTesting();
std::vector<Tile*> tiles = tiling->AllTilesForTesting();
client.tile_manager()->InitializeTilesWithResourcesForTesting(tiles);
@@ -236,7 +239,7 @@ class PictureLayerTilingSetTestWithResources : public testing::Test {
float max_contents_scale = scale;
gfx::Size content_bounds(
- gfx::ToCeiledSize(gfx::ScaleSize(layer_bounds, max_contents_scale)));
+ gfx::ScaleToCeiledSize(layer_bounds, max_contents_scale));
gfx::Rect content_rect(content_bounds);
Region remaining(content_rect);
@@ -302,15 +305,15 @@ TEST(PictureLayerTilingSetTest, TileSizeChange) {
ACTIVE_TREE, &active_client, 1000, 1.f, 1000);
gfx::Size layer_bounds(100, 100);
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
gfx::Size tile_size1(10, 10);
gfx::Size tile_size2(30, 30);
gfx::Size tile_size3(20, 20);
pending_client.SetTileSize(tile_size1);
- pending_set->AddTiling(1.f, pile);
+ pending_set->AddTiling(1.f, raster_source);
// New tilings get the correct tile size.
EXPECT_EQ(tile_size1, pending_set->tiling_at(0)->tile_size());
@@ -335,11 +338,11 @@ TEST(PictureLayerTilingSetTest, TileSizeChange) {
// activation, since we can't set the raster source twice on the pending tree
// without activating. For test, just remove and add a new tiling instead.
pending_set->RemoveAllTilings();
- pending_set->AddTiling(1.f, pile);
+ pending_set->AddTiling(1.f, raster_source);
pending_set->tiling_at(0)->set_resolution(HIGH_RESOLUTION);
pending_client.SetTileSize(tile_size2);
- pending_set->UpdateTilingsToCurrentRasterSourceForCommit(pile.get(), Region(),
- 1.f, 1.f);
+ pending_set->UpdateTilingsToCurrentRasterSourceForCommit(raster_source.get(),
+ Region(), 1.f, 1.f);
// The tiling should get the correct tile size.
EXPECT_EQ(tile_size2, pending_set->tiling_at(0)->tile_size());
@@ -357,7 +360,7 @@ TEST(PictureLayerTilingSetTest, TileSizeChange) {
// Clone from the pending to the active tree.
active_client.SetTileSize(tile_size2);
active_set->UpdateTilingsToCurrentRasterSourceForActivation(
- pile.get(), pending_set.get(), Region(), 1.f, 1.f);
+ raster_source.get(), pending_set.get(), Region(), 1.f, 1.f);
// The active tiling should get the right tile size.
EXPECT_EQ(tile_size2, active_set->tiling_at(0)->tile_size());
@@ -370,8 +373,8 @@ TEST(PictureLayerTilingSetTest, TileSizeChange) {
// A new source frame with a new tile size.
pending_client.SetTileSize(tile_size3);
- pending_set->UpdateTilingsToCurrentRasterSourceForCommit(pile.get(), Region(),
- 1.f, 1.f);
+ pending_set->UpdateTilingsToCurrentRasterSourceForCommit(raster_source.get(),
+ Region(), 1.f, 1.f);
// The tiling gets the new size correctly.
EXPECT_EQ(tile_size3, pending_set->tiling_at(0)->tile_size());
@@ -389,7 +392,7 @@ TEST(PictureLayerTilingSetTest, TileSizeChange) {
// Now we activate with a different tile size for the active tiling.
active_client.SetTileSize(tile_size3);
active_set->UpdateTilingsToCurrentRasterSourceForActivation(
- pile.get(), pending_set.get(), Region(), 1.f, 1.f);
+ raster_source.get(), pending_set.get(), Region(), 1.f, 1.f);
// The active tiling changes its tile size.
EXPECT_EQ(tile_size3, active_set->tiling_at(0)->tile_size());
@@ -409,13 +412,13 @@ TEST(PictureLayerTilingSetTest, MaxContentScale) {
ACTIVE_TREE, &active_client, 1000, 1.f, 1000);
gfx::Size layer_bounds(100, 105);
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateEmptyPileWithDefaultTileSize(layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> raster_source =
+ FakeDisplayListRasterSource::CreateEmpty(layer_bounds);
// Tilings can be added of any scale, the tiling client can controls this.
- pending_set->AddTiling(1.f, pile);
- pending_set->AddTiling(2.f, pile);
- pending_set->AddTiling(3.f, pile);
+ pending_set->AddTiling(1.f, raster_source);
+ pending_set->AddTiling(2.f, raster_source);
+ pending_set->AddTiling(3.f, raster_source);
// Set some expected things for the tiling set to function.
pending_set->tiling_at(0)->set_resolution(HIGH_RESOLUTION);
@@ -425,14 +428,14 @@ TEST(PictureLayerTilingSetTest, MaxContentScale) {
// everything.
float max_content_scale = 3.f;
pending_set->UpdateTilingsToCurrentRasterSourceForCommit(
- pile.get(), Region(), 1.f, max_content_scale);
+ raster_source.get(), Region(), 1.f, max_content_scale);
// All the tilings are there still.
EXPECT_EQ(3u, pending_set->num_tilings());
// Clone from the pending to the active tree with the same max content size.
active_set->UpdateTilingsToCurrentRasterSourceForActivation(
- pile.get(), pending_set.get(), Region(), 1.f, max_content_scale);
+ raster_source.get(), pending_set.get(), Region(), 1.f, max_content_scale);
// All the tilings are on the active tree.
EXPECT_EQ(3u, active_set->num_tilings());
@@ -440,7 +443,7 @@ TEST(PictureLayerTilingSetTest, MaxContentScale) {
// tiling.
max_content_scale = 2.9f;
pending_set->UpdateTilingsToCurrentRasterSourceForCommit(
- pile.get(), Region(), 1.f, max_content_scale);
+ raster_source.get(), Region(), 1.f, max_content_scale);
// All the tilings are there still.
EXPECT_EQ(2u, pending_set->num_tilings());
@@ -448,7 +451,7 @@ TEST(PictureLayerTilingSetTest, MaxContentScale) {
// Clone from the pending to the active tree with the same max content size.
active_set->UpdateTilingsToCurrentRasterSourceForActivation(
- pile.get(), pending_set.get(), Region(), 1.f, max_content_scale);
+ raster_source.get(), pending_set.get(), Region(), 1.f, max_content_scale);
// All the tilings are on the active tree.
EXPECT_EQ(2u, active_set->num_tilings());
}
diff --git a/chromium/cc/tiles/picture_layer_tiling_unittest.cc b/chromium/cc/tiles/picture_layer_tiling_unittest.cc
index 1c8a3978eb2..ec3b87024d7 100644
--- a/chromium/cc/tiles/picture_layer_tiling_unittest.cc
+++ b/chromium/cc/tiles/picture_layer_tiling_unittest.cc
@@ -6,10 +6,10 @@
#include <set>
#include "cc/base/math_util.h"
+#include "cc/test/fake_display_list_raster_source.h"
#include "cc/test/fake_output_surface.h"
#include "cc/test/fake_output_surface_client.h"
#include "cc/test/fake_picture_layer_tiling_client.h"
-#include "cc/test/fake_picture_pile_impl.h"
#include "cc/test/test_context_provider.h"
#include "cc/test/test_shared_bitmap_manager.h"
#include "cc/tiles/picture_layer_tiling.h"
@@ -31,9 +31,8 @@ static gfx::Rect ViewportInLayerSpace(
if (!transform.GetInverse(&inverse))
return gfx::Rect();
- gfx::RectF viewport_in_layer_space = MathUtil::ProjectClippedRect(
- inverse, gfx::RectF(gfx::Point(0, 0), device_viewport));
- return ToEnclosingRect(viewport_in_layer_space);
+ return MathUtil::ProjectEnclosingClippedRect(inverse,
+ gfx::Rect(device_viewport));
}
class TestablePictureLayerTiling : public PictureLayerTiling {
@@ -49,7 +48,7 @@ class TestablePictureLayerTiling : public PictureLayerTiling {
const LayerTreeSettings& settings) {
return make_scoped_ptr(new TestablePictureLayerTiling(
tree, contents_scale, raster_source, client,
- settings.max_tiles_for_interest_area,
+ settings.tiling_interest_area_padding,
settings.skewport_target_time_in_seconds,
settings.skewport_extrapolation_limit_in_content_pixels));
}
@@ -64,14 +63,14 @@ class TestablePictureLayerTiling : public PictureLayerTiling {
float contents_scale,
scoped_refptr<RasterSource> raster_source,
PictureLayerTilingClient* client,
- size_t max_tiles_for_interest_area,
+ size_t tiling_interest_area_padding,
float skewport_target_time,
int skewport_extrapolation_limit)
: PictureLayerTiling(tree,
contents_scale,
raster_source,
client,
- max_tiles_for_interest_area,
+ tiling_interest_area_padding,
skewport_target_time,
skewport_extrapolation_limit) {}
};
@@ -85,20 +84,24 @@ class PictureLayerTilingIteratorTest : public testing::Test {
float contents_scale,
const gfx::Size& layer_bounds) {
client_.SetTileSize(tile_size);
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(layer_bounds);
- tiling_ = TestablePictureLayerTiling::Create(
- PENDING_TREE, contents_scale, pile, &client_, LayerTreeSettings());
+ scoped_refptr<FakeDisplayListRasterSource> raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
+ tiling_ = TestablePictureLayerTiling::Create(PENDING_TREE, contents_scale,
+ raster_source, &client_,
+ LayerTreeSettings());
+ tiling_->set_resolution(HIGH_RESOLUTION);
}
void InitializeActive(const gfx::Size& tile_size,
float contents_scale,
const gfx::Size& layer_bounds) {
client_.SetTileSize(tile_size);
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(layer_bounds);
- tiling_ = TestablePictureLayerTiling::Create(
- ACTIVE_TREE, contents_scale, pile, &client_, LayerTreeSettings());
+ scoped_refptr<FakeDisplayListRasterSource> raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
+ tiling_ = TestablePictureLayerTiling::Create(ACTIVE_TREE, contents_scale,
+ raster_source, &client_,
+ LayerTreeSettings());
+ tiling_->set_resolution(HIGH_RESOLUTION);
}
void SetLiveRectAndVerifyTiles(const gfx::Rect& live_tiles_rect) {
@@ -209,12 +212,13 @@ TEST_F(PictureLayerTilingIteratorTest, ResizeDeletesTiles) {
// Stop creating tiles so that any invalidations are left as holes.
gfx::Size new_layer_size(200, 200);
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateEmptyPileWithDefaultTileSize(new_layer_size);
+ scoped_refptr<FakeDisplayListRasterSource> raster_source =
+ FakeDisplayListRasterSource::CreatePartiallyFilled(new_layer_size,
+ gfx::Rect());
Region invalidation =
SubtractRegions(gfx::Rect(tile_size), gfx::Rect(original_layer_size));
- tiling_->SetRasterSourceAndResize(pile);
+ tiling_->SetRasterSourceAndResize(raster_source);
EXPECT_TRUE(tiling_->TileAt(0, 0));
tiling_->Invalidate(invalidation);
EXPECT_FALSE(tiling_->TileAt(0, 0));
@@ -270,14 +274,14 @@ TEST_F(PictureLayerTilingIteratorTest, ResizeTilingOverTileBorders) {
// Shrink the tiling so that the last tile row/column is entirely in the
// border pixels of the interior tiles. That row/column is removed.
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
+ scoped_refptr<FakeDisplayListRasterSource> raster_source =
+ FakeDisplayListRasterSource::CreateFilled(
gfx::Size(right + 1, bottom + 1));
- tiling_->SetRasterSourceAndResize(pile);
+ tiling_->SetRasterSourceAndResize(raster_source);
EXPECT_EQ(2, tiling_->TilingDataForTesting().num_tiles_x());
EXPECT_EQ(3, tiling_->TilingDataForTesting().num_tiles_y());
- // The live tiles rect was clamped to the pile size.
+ // The live tiles rect was clamped to the raster source size.
EXPECT_EQ(gfx::Rect(right + 1, bottom + 1), tiling_->live_tiles_rect());
// Since the row/column is gone, the tiles should be gone too.
@@ -290,9 +294,9 @@ TEST_F(PictureLayerTilingIteratorTest, ResizeTilingOverTileBorders) {
// Growing outside the current right/bottom tiles border pixels should create
// the tiles again, even though the live rect has not changed size.
- pile = FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
+ raster_source = FakeDisplayListRasterSource::CreateFilled(
gfx::Size(right + 2, bottom + 2));
- tiling_->SetRasterSourceAndResize(pile);
+ tiling_->SetRasterSourceAndResize(raster_source);
EXPECT_EQ(3, tiling_->TilingDataForTesting().num_tiles_x());
EXPECT_EQ(4, tiling_->TilingDataForTesting().num_tiles_y());
@@ -424,10 +428,10 @@ TEST_F(PictureLayerTilingIteratorTest, ResizeOverBorderPixelsDeletesTiles) {
EXPECT_TRUE(tiling_->TileAt(0, 0));
// Stop creating tiles so that any invalidations are left as holes.
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateEmptyPileWithDefaultTileSize(
- gfx::Size(200, 200));
- tiling_->SetRasterSourceAndResize(pile);
+ scoped_refptr<FakeDisplayListRasterSource> raster_source =
+ FakeDisplayListRasterSource::CreatePartiallyFilled(gfx::Size(200, 200),
+ gfx::Rect());
+ tiling_->SetRasterSourceAndResize(raster_source);
Region invalidation =
SubtractRegions(gfx::Rect(tile_size), gfx::Rect(original_layer_size));
@@ -499,7 +503,7 @@ TEST_F(PictureLayerTilingIteratorTest, IteratorCoversLayerBoundsBothScale) {
float scale = 6.7f;
gfx::Size bounds(800, 600);
- gfx::Rect full_rect(gfx::ToCeiledSize(gfx::ScaleSize(bounds, scale)));
+ gfx::Rect full_rect(gfx::ScaleToCeiledSize(bounds, scale));
Initialize(gfx::Size(256, 512), 5.2f, bounds);
VerifyTilesExactlyCoverRect(scale, full_rect);
VerifyTilesExactlyCoverRect(scale, gfx::Rect(2014, 1579, 867, 1033));
@@ -550,14 +554,13 @@ TEST(PictureLayerTilingTest, SkewportLimits) {
client.SetTileSize(gfx::Size(100, 100));
LayerTreeSettings settings;
- settings.max_tiles_for_interest_area = 10000;
settings.skewport_extrapolation_limit_in_content_pixels = 75;
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
scoped_ptr<TestablePictureLayerTiling> tiling =
- TestablePictureLayerTiling::Create(ACTIVE_TREE, 1.0f, pile, &client,
- settings);
+ TestablePictureLayerTiling::Create(ACTIVE_TREE, 1.0f, raster_source,
+ &client, settings);
tiling->ComputeTilePriorityRects(viewport, 1.f, 1.0, Occlusion());
@@ -637,11 +640,11 @@ TEST(PictureLayerTilingTest, ComputeSkewportExtremeCases) {
gfx::Size layer_bounds(200, 200);
client.SetTileSize(gfx::Size(100, 100));
LayerTreeSettings settings;
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
scoped_ptr<TestablePictureLayerTiling> tiling =
- TestablePictureLayerTiling::Create(ACTIVE_TREE, 1.0f, pile, &client,
- settings);
+ TestablePictureLayerTiling::Create(ACTIVE_TREE, 1.0f, raster_source,
+ &client, settings);
gfx::Rect viewport1(-1918, 255860, 4010, 2356);
gfx::Rect viewport2(-7088, -91738, 14212, 8350);
@@ -663,11 +666,11 @@ TEST(PictureLayerTilingTest, ComputeSkewport) {
client.SetTileSize(gfx::Size(100, 100));
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
scoped_ptr<TestablePictureLayerTiling> tiling =
- TestablePictureLayerTiling::Create(ACTIVE_TREE, 1.0f, pile, &client,
- LayerTreeSettings());
+ TestablePictureLayerTiling::Create(ACTIVE_TREE, 1.0f, raster_source,
+ &client, LayerTreeSettings());
tiling->ComputeTilePriorityRects(viewport, 1.f, 1.0, Occlusion());
@@ -725,11 +728,11 @@ TEST(PictureLayerTilingTest, SkewportThroughUpdateTilePriorities) {
client.SetTileSize(gfx::Size(100, 100));
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
scoped_ptr<TestablePictureLayerTiling> tiling =
- TestablePictureLayerTiling::Create(ACTIVE_TREE, 1.0f, pile, &client,
- LayerTreeSettings());
+ TestablePictureLayerTiling::Create(ACTIVE_TREE, 1.0f, raster_source,
+ &client, LayerTreeSettings());
tiling->ComputeTilePriorityRects(viewport, 1.f, 1.0, Occlusion());
@@ -793,20 +796,20 @@ TEST(PictureLayerTilingTest, ViewportDistanceWithScale) {
client.SetTileSize(gfx::Size(10, 10));
LayerTreeSettings settings;
- settings.max_tiles_for_interest_area = 10000;
// Tiling at 0.25 scale: this should create 47x47 tiles of size 10x10.
// The reason is that each tile has a one pixel border, so tile at (1, 2)
// for instance begins at (8, 16) pixels. So tile at (46, 46) will begin at
// (368, 368) and extend to the end of 1500 * 0.25 = 375 edge of the
// tiling.
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
scoped_ptr<TestablePictureLayerTiling> tiling =
- TestablePictureLayerTiling::Create(ACTIVE_TREE, 0.25f, pile, &client,
- settings);
+ TestablePictureLayerTiling::Create(ACTIVE_TREE, 0.25f, raster_source,
+ &client, settings);
+ tiling->set_resolution(HIGH_RESOLUTION);
gfx::Rect viewport_in_content_space =
- gfx::ToEnclosedRect(gfx::ScaleRect(viewport, 0.25f));
+ gfx::ScaleToEnclosedRect(viewport, 0.25f);
tiling->ComputeTilePriorityRects(viewport, 1.f, 1.0, Occlusion());
auto prioritized_tiles = tiling->UpdateAndGetAllPrioritizedTilesForTesting();
@@ -881,8 +884,7 @@ TEST(PictureLayerTilingTest, ViewportDistanceWithScale) {
// Move the viewport down 40 pixels.
viewport = gfx::Rect(0, 40, 100, 100);
- viewport_in_content_space =
- gfx::ToEnclosedRect(gfx::ScaleRect(viewport, 0.25f));
+ viewport_in_content_space = gfx::ScaleToEnclosedRect(viewport, 0.25f);
gfx::Rect skewport = tiling->ComputeSkewport(2.0, viewport_in_content_space);
// Compute the soon border.
@@ -961,8 +963,9 @@ TEST(PictureLayerTilingTest, ViewportDistanceWithScale) {
EXPECT_FLOAT_EQ(8.f, priority.distance_to_visible);
// Test additional scales.
- tiling = TestablePictureLayerTiling::Create(ACTIVE_TREE, 0.2f, pile, &client,
- LayerTreeSettings());
+ tiling = TestablePictureLayerTiling::Create(ACTIVE_TREE, 0.2f, raster_source,
+ &client, LayerTreeSettings());
+ tiling->set_resolution(HIGH_RESOLUTION);
tiling->ComputeTilePriorityRects(viewport, 1.0f, 4.0, Occlusion());
prioritized_tiles = tiling->UpdateAndGetAllPrioritizedTilesForTesting();
@@ -988,228 +991,6 @@ TEST(PictureLayerTilingTest, ViewportDistanceWithScale) {
EXPECT_FLOAT_EQ(30.f, priority.distance_to_visible);
}
-TEST(PictureLayerTilingTest, ExpandRectEqual) {
- gfx::Rect in(40, 50, 100, 200);
- gfx::Rect bounds(-1000, -1000, 10000, 10000);
- int64 target_area = 100 * 200;
- gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
- in, target_area, bounds, NULL);
- EXPECT_EQ(in.ToString(), out.ToString());
-}
-
-TEST(PictureLayerTilingTest, ExpandRectSmaller) {
- gfx::Rect in(40, 50, 100, 200);
- gfx::Rect bounds(-1000, -1000, 10000, 10000);
- int64 target_area = 100 * 100;
- gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
- in, target_area, bounds, NULL);
- EXPECT_EQ(out.bottom() - in.bottom(), in.y() - out.y());
- EXPECT_EQ(out.right() - in.right(), in.x() - out.x());
- EXPECT_EQ(out.width() - in.width(), out.height() - in.height());
-
- // |in| represents the visible rect, and |out| represents the eventually rect.
- // If the eventually rect doesn't contain the visible rect, we will start
- // losing tiles.
- EXPECT_TRUE(out.Contains(in));
- EXPECT_TRUE(bounds.Contains(out));
-}
-
-TEST(PictureLayerTilingTest, ExpandRectUnbounded) {
- gfx::Rect in(40, 50, 100, 200);
- gfx::Rect bounds(-1000, -1000, 10000, 10000);
- int64 target_area = 200 * 200;
- gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
- in, target_area, bounds, NULL);
- EXPECT_EQ(out.bottom() - in.bottom(), in.y() - out.y());
- EXPECT_EQ(out.right() - in.right(), in.x() - out.x());
- EXPECT_EQ(out.width() - in.width(), out.height() - in.height());
- EXPECT_NEAR(200 * 200, out.width() * out.height(), 100);
- EXPECT_TRUE(bounds.Contains(out));
-}
-
-TEST(PictureLayerTilingTest, ExpandRectBoundedSmaller) {
- gfx::Rect in(40, 50, 100, 200);
- gfx::Rect bounds(50, 60, 40, 30);
- int64 target_area = 200 * 200;
- gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
- in, target_area, bounds, NULL);
- EXPECT_EQ(bounds.ToString(), out.ToString());
-}
-
-TEST(PictureLayerTilingTest, ExpandRectBoundedEqual) {
- gfx::Rect in(40, 50, 100, 200);
- gfx::Rect bounds = in;
- int64 target_area = 200 * 200;
- gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
- in, target_area, bounds, NULL);
- EXPECT_EQ(bounds.ToString(), out.ToString());
-}
-
-TEST(PictureLayerTilingTest, ExpandRectBoundedSmallerStretchVertical) {
- gfx::Rect in(40, 50, 100, 200);
- gfx::Rect bounds(45, 0, 90, 300);
- int64 target_area = 200 * 200;
- gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
- in, target_area, bounds, NULL);
- EXPECT_EQ(bounds.ToString(), out.ToString());
-}
-
-TEST(PictureLayerTilingTest, ExpandRectBoundedEqualStretchVertical) {
- gfx::Rect in(40, 50, 100, 200);
- gfx::Rect bounds(40, 0, 100, 300);
- int64 target_area = 200 * 200;
- gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
- in, target_area, bounds, NULL);
- EXPECT_EQ(bounds.ToString(), out.ToString());
-}
-
-TEST(PictureLayerTilingTest, ExpandRectBoundedSmallerStretchHorizontal) {
- gfx::Rect in(40, 50, 100, 200);
- gfx::Rect bounds(0, 55, 180, 190);
- int64 target_area = 200 * 200;
- gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
- in, target_area, bounds, NULL);
- EXPECT_EQ(bounds.ToString(), out.ToString());
-}
-
-TEST(PictureLayerTilingTest, ExpandRectBoundedEqualStretchHorizontal) {
- gfx::Rect in(40, 50, 100, 200);
- gfx::Rect bounds(0, 50, 180, 200);
- int64 target_area = 200 * 200;
- gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
- in, target_area, bounds, NULL);
- EXPECT_EQ(bounds.ToString(), out.ToString());
-}
-
-TEST(PictureLayerTilingTest, ExpandRectBoundedLeft) {
- gfx::Rect in(40, 50, 100, 200);
- gfx::Rect bounds(20, -1000, 10000, 10000);
- int64 target_area = 200 * 200;
- gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
- in, target_area, bounds, NULL);
- EXPECT_EQ(out.bottom() - in.bottom(), in.y() - out.y());
- EXPECT_EQ(out.bottom() - in.bottom(), out.right() - in.right());
- EXPECT_LE(out.width() * out.height(), target_area);
- EXPECT_GT(out.width() * out.height(),
- target_area - out.width() - out.height() * 2);
- EXPECT_TRUE(bounds.Contains(out));
-}
-
-TEST(PictureLayerTilingTest, ExpandRectBoundedRight) {
- gfx::Rect in(40, 50, 100, 200);
- gfx::Rect bounds(-1000, -1000, 1000+120, 10000);
- int64 target_area = 200 * 200;
- gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
- in, target_area, bounds, NULL);
- EXPECT_EQ(out.bottom() - in.bottom(), in.y() - out.y());
- EXPECT_EQ(out.bottom() - in.bottom(), in.x() - out.x());
- EXPECT_LE(out.width() * out.height(), target_area);
- EXPECT_GT(out.width() * out.height(),
- target_area - out.width() - out.height() * 2);
- EXPECT_TRUE(bounds.Contains(out));
-}
-
-TEST(PictureLayerTilingTest, ExpandRectBoundedTop) {
- gfx::Rect in(40, 50, 100, 200);
- gfx::Rect bounds(-1000, 30, 10000, 10000);
- int64 target_area = 200 * 200;
- gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
- in, target_area, bounds, NULL);
- EXPECT_EQ(out.right() - in.right(), in.x() - out.x());
- EXPECT_EQ(out.right() - in.right(), out.bottom() - in.bottom());
- EXPECT_LE(out.width() * out.height(), target_area);
- EXPECT_GT(out.width() * out.height(),
- target_area - out.width() * 2 - out.height());
- EXPECT_TRUE(bounds.Contains(out));
-}
-
-TEST(PictureLayerTilingTest, ExpandRectBoundedBottom) {
- gfx::Rect in(40, 50, 100, 200);
- gfx::Rect bounds(-1000, -1000, 10000, 1000 + 220);
- int64 target_area = 200 * 200;
- gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
- in, target_area, bounds, NULL);
- EXPECT_EQ(out.right() - in.right(), in.x() - out.x());
- EXPECT_EQ(out.right() - in.right(), in.y() - out.y());
- EXPECT_LE(out.width() * out.height(), target_area);
- EXPECT_GT(out.width() * out.height(),
- target_area - out.width() * 2 - out.height());
- EXPECT_TRUE(bounds.Contains(out));
-}
-
-TEST(PictureLayerTilingTest, ExpandRectSquishedHorizontally) {
- gfx::Rect in(40, 50, 100, 200);
- gfx::Rect bounds(0, -4000, 100+40+20, 100000);
- int64 target_area = 400 * 400;
- gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
- in, target_area, bounds, NULL);
- EXPECT_EQ(20, out.right() - in.right());
- EXPECT_EQ(40, in.x() - out.x());
- EXPECT_EQ(out.bottom() - in.bottom(), in.y() - out.y());
- EXPECT_LE(out.width() * out.height(), target_area);
- EXPECT_GT(out.width() * out.height(),
- target_area - out.width() * 2);
- EXPECT_TRUE(bounds.Contains(out));
-}
-
-TEST(PictureLayerTilingTest, ExpandRectSquishedVertically) {
- gfx::Rect in(40, 50, 100, 200);
- gfx::Rect bounds(-4000, 0, 100000, 200+50+30);
- int64 target_area = 400 * 400;
- gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
- in, target_area, bounds, NULL);
- EXPECT_EQ(30, out.bottom() - in.bottom());
- EXPECT_EQ(50, in.y() - out.y());
- EXPECT_EQ(out.right() - in.right(), in.x() - out.x());
- EXPECT_LE(out.width() * out.height(), target_area);
- EXPECT_GT(out.width() * out.height(),
- target_area - out.height() * 2);
- EXPECT_TRUE(bounds.Contains(out));
-}
-
-TEST(PictureLayerTilingTest, ExpandRectOutOfBoundsFarAway) {
- gfx::Rect in(400, 500, 100, 200);
- gfx::Rect bounds(0, 0, 10, 10);
- int64 target_area = 400 * 400;
- gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
- in, target_area, bounds, NULL);
- EXPECT_TRUE(out.IsEmpty());
-}
-
-TEST(PictureLayerTilingTest, ExpandRectOutOfBoundsExpandedFullyCover) {
- gfx::Rect in(40, 50, 100, 100);
- gfx::Rect bounds(0, 0, 10, 10);
- int64 target_area = 400 * 400;
- gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
- in, target_area, bounds, NULL);
- EXPECT_EQ(bounds.ToString(), out.ToString());
-}
-
-TEST(PictureLayerTilingTest, ExpandRectOutOfBoundsExpandedPartlyCover) {
- gfx::Rect in(600, 600, 100, 100);
- gfx::Rect bounds(0, 0, 500, 500);
- int64 target_area = 400 * 400;
- gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
- in, target_area, bounds, NULL);
- EXPECT_EQ(bounds.right(), out.right());
- EXPECT_EQ(bounds.bottom(), out.bottom());
- EXPECT_LE(out.width() * out.height(), target_area);
- EXPECT_GT(out.width() * out.height(),
- target_area - out.width() - out.height());
- EXPECT_TRUE(bounds.Contains(out));
-}
-
-TEST(PictureLayerTilingTest, EmptyStartingRect) {
- // If a layer has a non-invertible transform, then the starting rect
- // for the layer would be empty.
- gfx::Rect in(40, 40, 0, 0);
- gfx::Rect bounds(0, 0, 10, 10);
- int64 target_area = 400 * 400;
- gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
- in, target_area, bounds, NULL);
- EXPECT_TRUE(out.IsEmpty());
-}
-
static void TileExists(bool exists, Tile* tile,
const gfx::Rect& geometry_rect) {
EXPECT_EQ(exists, tile != NULL) << geometry_rect.ToString();
@@ -1293,12 +1074,13 @@ TEST_F(PictureLayerTilingIteratorTest,
gfx::Size layer_bounds(10000, 10000);
client_.SetTileSize(gfx::Size(100, 100));
LayerTreeSettings settings;
- settings.max_tiles_for_interest_area = 1;
+ settings.tiling_interest_area_padding = 1;
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(layer_bounds);
- tiling_ = TestablePictureLayerTiling::Create(PENDING_TREE, 1.f, pile,
+ scoped_refptr<FakeDisplayListRasterSource> raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
+ tiling_ = TestablePictureLayerTiling::Create(PENDING_TREE, 1.f, raster_source,
&client_, settings);
+ tiling_->set_resolution(HIGH_RESOLUTION);
VerifyTilesExactlyCoverRect(1.f, gfx::Rect(layer_bounds));
VerifyTiles(1.f, gfx::Rect(layer_bounds), base::Bind(&TileExists, false));
@@ -1330,12 +1112,12 @@ TEST(ComputeTilePriorityRectsTest, VisibleTiles) {
client.SetTileSize(gfx::Size(100, 100));
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
- current_layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> raster_source =
+ FakeDisplayListRasterSource::CreateFilled(current_layer_bounds);
scoped_ptr<TestablePictureLayerTiling> tiling =
- TestablePictureLayerTiling::Create(ACTIVE_TREE, 1.0f, pile, &client,
- LayerTreeSettings());
+ TestablePictureLayerTiling::Create(ACTIVE_TREE, 1.0f, raster_source,
+ &client, LayerTreeSettings());
+ tiling->set_resolution(HIGH_RESOLUTION);
tiling->ComputeTilePriorityRects(viewport_in_layer_space,
current_layer_contents_scale,
@@ -1385,12 +1167,12 @@ TEST(ComputeTilePriorityRectsTest, OffscreenTiles) {
client.SetTileSize(gfx::Size(100, 100));
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
- current_layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> raster_source =
+ FakeDisplayListRasterSource::CreateFilled(current_layer_bounds);
scoped_ptr<TestablePictureLayerTiling> tiling =
- TestablePictureLayerTiling::Create(ACTIVE_TREE, 1.0f, pile, &client,
- LayerTreeSettings());
+ TestablePictureLayerTiling::Create(ACTIVE_TREE, 1.0f, raster_source,
+ &client, LayerTreeSettings());
+ tiling->set_resolution(HIGH_RESOLUTION);
tiling->ComputeTilePriorityRects(viewport_in_layer_space,
current_layer_contents_scale,
@@ -1450,12 +1232,12 @@ TEST(ComputeTilePriorityRectsTest, PartiallyOffscreenLayer) {
client.SetTileSize(gfx::Size(100, 100));
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
- current_layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> raster_source =
+ FakeDisplayListRasterSource::CreateFilled(current_layer_bounds);
scoped_ptr<TestablePictureLayerTiling> tiling =
- TestablePictureLayerTiling::Create(ACTIVE_TREE, 1.0f, pile, &client,
- LayerTreeSettings());
+ TestablePictureLayerTiling::Create(ACTIVE_TREE, 1.0f, raster_source,
+ &client, LayerTreeSettings());
+ tiling->set_resolution(HIGH_RESOLUTION);
tiling->ComputeTilePriorityRects(viewport_in_layer_space,
current_layer_contents_scale,
@@ -1509,12 +1291,12 @@ TEST(ComputeTilePriorityRectsTest, PartiallyOffscreenRotatedLayer) {
client.SetTileSize(gfx::Size(100, 100));
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
- current_layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> raster_source =
+ FakeDisplayListRasterSource::CreateFilled(current_layer_bounds);
scoped_ptr<TestablePictureLayerTiling> tiling =
- TestablePictureLayerTiling::Create(ACTIVE_TREE, 1.0f, pile, &client,
- LayerTreeSettings());
+ TestablePictureLayerTiling::Create(ACTIVE_TREE, 1.0f, raster_source,
+ &client, LayerTreeSettings());
+ tiling->set_resolution(HIGH_RESOLUTION);
tiling->ComputeTilePriorityRects(viewport_in_layer_space,
current_layer_contents_scale,
@@ -1593,12 +1375,12 @@ TEST(ComputeTilePriorityRectsTest, PerspectiveLayer) {
client.SetTileSize(gfx::Size(100, 100));
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
- current_layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> raster_source =
+ FakeDisplayListRasterSource::CreateFilled(current_layer_bounds);
scoped_ptr<TestablePictureLayerTiling> tiling =
- TestablePictureLayerTiling::Create(ACTIVE_TREE, 1.0f, pile, &client,
- LayerTreeSettings());
+ TestablePictureLayerTiling::Create(ACTIVE_TREE, 1.0f, raster_source,
+ &client, LayerTreeSettings());
+ tiling->set_resolution(HIGH_RESOLUTION);
tiling->ComputeTilePriorityRects(viewport_in_layer_space,
current_layer_contents_scale,
@@ -1687,12 +1469,12 @@ TEST(ComputeTilePriorityRectsTest, PerspectiveLayerClippedByW) {
client.SetTileSize(gfx::Size(100, 100));
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
- current_layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> raster_source =
+ FakeDisplayListRasterSource::CreateFilled(current_layer_bounds);
scoped_ptr<TestablePictureLayerTiling> tiling =
- TestablePictureLayerTiling::Create(ACTIVE_TREE, 1.0f, pile, &client,
- LayerTreeSettings());
+ TestablePictureLayerTiling::Create(ACTIVE_TREE, 1.0f, raster_source,
+ &client, LayerTreeSettings());
+ tiling->set_resolution(HIGH_RESOLUTION);
tiling->ComputeTilePriorityRects(viewport_in_layer_space,
current_layer_contents_scale,
@@ -1750,14 +1532,13 @@ TEST(ComputeTilePriorityRectsTest, BasicMotion) {
client.SetTileSize(gfx::Size(100, 100));
LayerTreeSettings settings;
- settings.max_tiles_for_interest_area = 10000;
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
- current_layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> raster_source =
+ FakeDisplayListRasterSource::CreateFilled(current_layer_bounds);
scoped_ptr<TestablePictureLayerTiling> tiling =
- TestablePictureLayerTiling::Create(ACTIVE_TREE, 1.0f, pile, &client,
- settings);
+ TestablePictureLayerTiling::Create(ACTIVE_TREE, 1.0f, raster_source,
+ &client, settings);
+ tiling->set_resolution(HIGH_RESOLUTION);
// previous ("last") frame
tiling->ComputeTilePriorityRects(viewport_in_layer_space,
@@ -1830,11 +1611,11 @@ TEST(ComputeTilePriorityRectsTest, RotationMotion) {
client.SetTileSize(gfx::Size(100, 100));
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
- current_layer_bounds);
- tiling = TestablePictureLayerTiling::Create(ACTIVE_TREE, 1.0f, pile, &client,
- LayerTreeSettings());
+ scoped_refptr<FakeDisplayListRasterSource> raster_source =
+ FakeDisplayListRasterSource::CreateFilled(current_layer_bounds);
+ tiling = TestablePictureLayerTiling::Create(ACTIVE_TREE, 1.0f, raster_source,
+ &client, LayerTreeSettings());
+ tiling->set_resolution(HIGH_RESOLUTION);
// previous ("last") frame
tiling->ComputeTilePriorityRects(viewport_in_layer_space,
@@ -1880,14 +1661,13 @@ TEST(PictureLayerTilingTest, RecycledTilesCleared) {
active_client.SetTileSize(gfx::Size(100, 100));
LayerTreeSettings settings;
- settings.max_tiles_for_interest_area = 10;
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
- gfx::Size(10000, 10000));
+ scoped_refptr<FakeDisplayListRasterSource> raster_source =
+ FakeDisplayListRasterSource::CreateFilled(gfx::Size(10000, 10000));
scoped_ptr<TestablePictureLayerTiling> active_tiling =
- TestablePictureLayerTiling::Create(ACTIVE_TREE, 1.0f, pile,
+ TestablePictureLayerTiling::Create(ACTIVE_TREE, 1.0f, raster_source,
&active_client, settings);
+ active_tiling->set_resolution(HIGH_RESOLUTION);
// Create all tiles on this tiling.
active_tiling->ComputeTilePriorityRects(gfx::Rect(0, 0, 100, 100), 1.0f, 1.0f,
Occlusion());
@@ -1896,11 +1676,12 @@ TEST(PictureLayerTilingTest, RecycledTilesCleared) {
recycle_client.SetTileSize(gfx::Size(100, 100));
recycle_client.set_twin_tiling(active_tiling.get());
- pile = FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
- gfx::Size(10000, 10000));
+ raster_source =
+ FakeDisplayListRasterSource::CreateFilled(gfx::Size(10000, 10000));
scoped_ptr<TestablePictureLayerTiling> recycle_tiling =
- TestablePictureLayerTiling::Create(PENDING_TREE, 1.0f, pile,
+ TestablePictureLayerTiling::Create(PENDING_TREE, 1.0f, raster_source,
&recycle_client, settings);
+ recycle_tiling->set_resolution(HIGH_RESOLUTION);
// Create all tiles on the second tiling. All tiles should be shared.
recycle_tiling->ComputeTilePriorityRects(gfx::Rect(0, 0, 100, 100), 1.0f,
@@ -1933,12 +1714,12 @@ TEST(PictureLayerTilingTest, RecycledTilesClearedOnReset) {
FakePictureLayerTilingClient active_client;
active_client.SetTileSize(gfx::Size(100, 100));
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
- gfx::Size(100, 100));
+ scoped_refptr<FakeDisplayListRasterSource> raster_source =
+ FakeDisplayListRasterSource::CreateFilled(gfx::Size(100, 100));
scoped_ptr<TestablePictureLayerTiling> active_tiling =
- TestablePictureLayerTiling::Create(ACTIVE_TREE, 1.0f, pile,
+ TestablePictureLayerTiling::Create(ACTIVE_TREE, 1.0f, raster_source,
&active_client, LayerTreeSettings());
+ active_tiling->set_resolution(HIGH_RESOLUTION);
// Create all tiles on this tiling.
active_tiling->ComputeTilePriorityRects(gfx::Rect(0, 0, 100, 100), 1.0f, 1.0f,
Occlusion());
@@ -1948,13 +1729,13 @@ TEST(PictureLayerTilingTest, RecycledTilesClearedOnReset) {
recycle_client.set_twin_tiling(active_tiling.get());
LayerTreeSettings settings;
- settings.max_tiles_for_interest_area = 10;
- pile = FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
- gfx::Size(100, 100));
+ raster_source =
+ FakeDisplayListRasterSource::CreateFilled(gfx::Size(100, 100));
scoped_ptr<TestablePictureLayerTiling> recycle_tiling =
- TestablePictureLayerTiling::Create(PENDING_TREE, 1.0f, pile,
+ TestablePictureLayerTiling::Create(PENDING_TREE, 1.0f, raster_source,
&recycle_client, settings);
+ recycle_tiling->set_resolution(HIGH_RESOLUTION);
// Create all tiles on the recycle tiling. All tiles should be shared.
recycle_tiling->ComputeTilePriorityRects(gfx::Rect(0, 0, 100, 100), 1.0f,
@@ -1988,10 +1769,9 @@ TEST_F(PictureLayerTilingIteratorTest, ResizeTilesAndUpdateToCurrent) {
EXPECT_EQ(100, tiling_->TilingDataForTesting().max_texture_size().height());
// The layer's size isn't changed, but the tile size was.
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
- gfx::Size(250, 150));
- tiling_->SetRasterSourceAndResize(pile);
+ scoped_refptr<FakeDisplayListRasterSource> raster_source =
+ FakeDisplayListRasterSource::CreateFilled(gfx::Size(250, 150));
+ tiling_->SetRasterSourceAndResize(raster_source);
// Tile size in the tiling should be resized to 250x200.
EXPECT_EQ(250, tiling_->TilingDataForTesting().max_texture_size().width());
@@ -1999,5 +1779,22 @@ TEST_F(PictureLayerTilingIteratorTest, ResizeTilesAndUpdateToCurrent) {
EXPECT_EQ(0u, tiling_->AllTilesForTesting().size());
}
+// This test runs into floating point issues because of big numbers.
+TEST_F(PictureLayerTilingIteratorTest, GiantRect) {
+ gfx::Size tile_size(256, 256);
+ gfx::Size layer_size(33554432, 33554432);
+ float contents_scale = 1.f;
+
+ client_.SetTileSize(tile_size);
+ scoped_refptr<FakeDisplayListRasterSource> raster_source =
+ FakeDisplayListRasterSource::CreateEmpty(layer_size);
+ tiling_ = TestablePictureLayerTiling::Create(PENDING_TREE, contents_scale,
+ raster_source, &client_,
+ LayerTreeSettings());
+
+ gfx::Rect content_rect(25554432, 25554432, 950, 860);
+ VerifyTilesExactlyCoverRect(contents_scale, content_rect);
+}
+
} // namespace
} // namespace cc
diff --git a/chromium/cc/tiles/prioritized_tile.cc b/chromium/cc/tiles/prioritized_tile.cc
index 67f33c9dbc8..2e0246c34c9 100644
--- a/chromium/cc/tiles/prioritized_tile.cc
+++ b/chromium/cc/tiles/prioritized_tile.cc
@@ -33,6 +33,7 @@ void PrioritizedTile::AsValueInto(base::trace_event::TracedValue* value) const {
value->BeginDictionary("combined_priority");
priority().AsValueInto(value);
+ value->SetBoolean("is_occluded", is_occluded_);
value->EndDictionary();
value->SetString("resolution", TileResolutionToString(priority().resolution));
diff --git a/chromium/cc/tiles/raster_tile_priority_queue_all.cc b/chromium/cc/tiles/raster_tile_priority_queue_all.cc
index 8f7bdbf0436..ea3c14f8dd0 100644
--- a/chromium/cc/tiles/raster_tile_priority_queue_all.cc
+++ b/chromium/cc/tiles/raster_tile_priority_queue_all.cc
@@ -136,13 +136,14 @@ RasterTilePriorityQueueAll::GetNextQueues() const {
switch (tree_priority_) {
case SMOOTHNESS_TAKES_PRIORITY: {
- // If we're down to eventually bin tiles on the active tree, process the
- // pending tree to allow tiles required for activation to be initialized
- // when memory policy only allows prepaint.
- if (active_priority.priority_bin == TilePriority::EVENTUALLY &&
- pending_priority.priority_bin == TilePriority::NOW) {
+ // If we're down to eventually bin tiles on the active tree and there
+ // is a pending tree, process the entire pending tree to allow tiles
+ // required for activation to be initialized when memory policy only
+ // allows prepaint. The eventually bin tiles on the active tree are
+ // lowest priority since that work is likely to be thrown away when
+ // we activate.
+ if (active_priority.priority_bin == TilePriority::EVENTUALLY)
return pending_queues_;
- }
return active_queues_;
}
case NEW_CONTENT_TAKES_PRIORITY: {
diff --git a/chromium/cc/tiles/tile.cc b/chromium/cc/tiles/tile.cc
index 6052e5e0457..87ec3f7befd 100644
--- a/chromium/cc/tiles/tile.cc
+++ b/chromium/cc/tiles/tile.cc
@@ -14,30 +14,25 @@
namespace cc {
-Tile::Id Tile::s_next_id_ = 1;
-
Tile::Tile(TileManager* tile_manager,
- const gfx::Size& desired_texture_size,
- const gfx::Rect& content_rect,
- float contents_scale,
+ const CreateInfo& info,
int layer_id,
int source_frame_number,
int flags)
: tile_manager_(tile_manager),
- desired_texture_size_(desired_texture_size),
- content_rect_(content_rect),
- contents_scale_(contents_scale),
+ content_rect_(info.content_rect),
+ enclosing_layer_rect_(info.enclosing_layer_rect),
+ contents_scale_(info.contents_scale),
layer_id_(layer_id),
source_frame_number_(source_frame_number),
flags_(flags),
- tiling_i_index_(-1),
- tiling_j_index_(-1),
+ tiling_i_index_(info.tiling_i_index),
+ tiling_j_index_(info.tiling_j_index),
required_for_activation_(false),
required_for_draw_(false),
- id_(s_next_id_++),
+ id_(tile_manager->GetUniqueTileId()),
invalidated_id_(0),
- scheduled_priority_(0) {
-}
+ scheduled_priority_(0) {}
Tile::~Tile() {
TRACE_EVENT_OBJECT_DELETED_WITH_ID(
@@ -71,15 +66,14 @@ size_t Tile::GPUMemoryUsageInBytes() const {
if (draw_info_.resource_) {
// We can use UncheckedSizeInBytes, since the tile size is determined by the
// compositor.
- return Resource::UncheckedMemorySizeBytes(draw_info_.resource_->size(),
- draw_info_.resource_->format());
+ return ResourceUtil::UncheckedSizeInBytes<size_t>(
+ draw_info_.resource_->size(), draw_info_.resource_->format());
}
return 0;
}
void Tile::Deleter::operator()(Tile* tile) const {
- TileManager* tile_manager = tile->tile_manager_;
- tile_manager->Release(tile);
+ tile->tile_manager_->Release(tile);
}
} // namespace cc
diff --git a/chromium/cc/tiles/tile.h b/chromium/cc/tiles/tile.h
index e53c2ac52f8..e245e0111d9 100644
--- a/chromium/cc/tiles/tile.h
+++ b/chromium/cc/tiles/tile.h
@@ -23,7 +23,27 @@ class CC_EXPORT Tile {
void operator()(Tile* tile) const;
};
- enum TileRasterFlags { USE_PICTURE_ANALYSIS = 1 << 0 };
+ class CC_EXPORT CreateInfo {
+ public:
+ int tiling_i_index;
+ int tiling_j_index;
+ gfx::Rect enclosing_layer_rect;
+ gfx::Rect content_rect;
+ float contents_scale;
+
+ CreateInfo(int tiling_i_index,
+ int tiling_j_index,
+ const gfx::Rect& enclosing_layer_rect,
+ const gfx::Rect& content_rect,
+ float contents_scale)
+ : tiling_i_index(tiling_i_index),
+ tiling_j_index(tiling_j_index),
+ enclosing_layer_rect(enclosing_layer_rect),
+ content_rect(content_rect),
+ contents_scale(contents_scale) {}
+ };
+
+ enum TileRasterFlags { USE_PICTURE_ANALYSIS = 1 << 0, IS_OPAQUE = 1 << 1 };
typedef uint64 Id;
@@ -45,13 +65,18 @@ class CC_EXPORT Tile {
return !!(flags_ & USE_PICTURE_ANALYSIS);
}
+ bool is_opaque() const { return !!(flags_ & IS_OPAQUE); }
+
void AsValueInto(base::trace_event::TracedValue* value) const;
const TileDrawInfo& draw_info() const { return draw_info_; }
TileDrawInfo& draw_info() { return draw_info_; }
float contents_scale() const { return contents_scale_; }
- gfx::Rect content_rect() const { return content_rect_; }
+ const gfx::Rect& content_rect() const { return content_rect_; }
+ const gfx::Rect& enclosing_layer_rect() const {
+ return enclosing_layer_rect_;
+ }
int layer_id() const { return layer_id_; }
@@ -59,12 +84,8 @@ class CC_EXPORT Tile {
size_t GPUMemoryUsageInBytes() const;
- gfx::Size desired_texture_size() const { return desired_texture_size_; }
+ const gfx::Size& desired_texture_size() const { return content_rect_.size(); }
- void set_tiling_index(int i, int j) {
- tiling_i_index_ = i;
- tiling_j_index_ = j;
- }
int tiling_i_index() const { return tiling_i_index_; }
int tiling_j_index() const { return tiling_j_index_; }
@@ -86,9 +107,7 @@ class CC_EXPORT Tile {
// Methods called by by tile manager.
Tile(TileManager* tile_manager,
- const gfx::Size& desired_texture_size,
- const gfx::Rect& content_rect,
- float contents_scale,
+ const CreateInfo& info,
int layer_id,
int source_frame_number,
int flags);
@@ -96,23 +115,22 @@ class CC_EXPORT Tile {
bool HasRasterTask() const { return !!raster_task_.get(); }
- TileManager* tile_manager_;
- gfx::Size desired_texture_size_;
- gfx::Rect content_rect_;
- float contents_scale_;
+ TileManager* const tile_manager_;
+ const gfx::Rect content_rect_;
+ const gfx::Rect enclosing_layer_rect_;
+ const float contents_scale_;
TileDrawInfo draw_info_;
- int layer_id_;
- int source_frame_number_;
- int flags_;
- int tiling_i_index_;
- int tiling_j_index_;
+ const int layer_id_;
+ const int source_frame_number_;
+ const int flags_;
+ const int tiling_i_index_;
+ const int tiling_j_index_;
bool required_for_activation_ : 1;
bool required_for_draw_ : 1;
Id id_;
- static Id s_next_id_;
// The rect bounding the changes in this Tile vs the previous tile it
// replaced.
diff --git a/chromium/cc/tiles/tile_draw_info.cc b/chromium/cc/tiles/tile_draw_info.cc
index 6b12e73f5c6..c1042ceff3d 100644
--- a/chromium/cc/tiles/tile_draw_info.cc
+++ b/chromium/cc/tiles/tile_draw_info.cc
@@ -12,10 +12,10 @@ namespace cc {
TileDrawInfo::TileDrawInfo()
: mode_(RESOURCE_MODE),
solid_color_(SK_ColorWHITE),
+ resource_(nullptr),
contents_swizzled_(false),
was_ever_ready_to_draw_(false),
- was_ever_used_to_draw_(false) {
-}
+ was_ever_used_to_draw_(false) {}
TileDrawInfo::~TileDrawInfo() {
DCHECK(!resource_);
diff --git a/chromium/cc/tiles/tile_draw_info.h b/chromium/cc/tiles/tile_draw_info.h
index dcb755ad34e..05596ba9216 100644
--- a/chromium/cc/tiles/tile_draw_info.h
+++ b/chromium/cc/tiles/tile_draw_info.h
@@ -74,9 +74,6 @@ class CC_EXPORT TileDrawInfo {
inline bool has_resource() const { return !!resource_; }
void SetSolidColorForTesting(SkColor color) { set_solid_color(color); }
- void SetResourceForTesting(scoped_ptr<ScopedResource> resource) {
- resource_ = resource.Pass();
- }
void AsValueInto(base::trace_event::TracedValue* state) const;
@@ -98,7 +95,7 @@ class CC_EXPORT TileDrawInfo {
Mode mode_;
SkColor solid_color_;
- scoped_ptr<ScopedResource> resource_;
+ Resource* resource_;
bool contents_swizzled_;
// Used for gathering UMA stats.
diff --git a/chromium/cc/tiles/tile_manager.cc b/chromium/cc/tiles/tile_manager.cc
index 23d2eca12bc..b9d3ab7fd15 100644
--- a/chromium/cc/tiles/tile_manager.cc
+++ b/chromium/cc/tiles/tile_manager.cc
@@ -33,8 +33,8 @@ const bool kUseColorEstimator = true;
DEFINE_SCOPED_UMA_HISTOGRAM_AREA_TIMER(
ScopedRasterTaskTimer,
- "Compositing.RasterTask.RasterUs",
- "Compositing.RasterTask.RasterPixelsPerMs");
+ "Compositing.%s.RasterTask.RasterUs",
+ "Compositing.%s.RasterTask.RasterPixelsPerMs");
class RasterTaskImpl : public RasterTask {
public:
@@ -56,7 +56,8 @@ class RasterTaskImpl : public RasterTask {
const base::Callback<void(const RasterSource::SolidColorAnalysis&, bool)>&
reply,
ImageDecodeTask::Vector* dependencies)
- : RasterTask(resource, dependencies),
+ : RasterTask(dependencies),
+ resource_(resource),
raster_source_(raster_source),
content_rect_(content_rect),
invalid_content_rect_(invalid_content_rect),
@@ -93,13 +94,10 @@ class RasterTaskImpl : public RasterTask {
void ScheduleOnOriginThread(TileTaskClient* client) override {
DCHECK(!raster_buffer_);
raster_buffer_ = client->AcquireBufferForRaster(
- resource(), resource_content_id_, previous_content_id_);
+ resource_, resource_content_id_, previous_content_id_);
}
void CompleteOnOriginThread(TileTaskClient* client) override {
client->ReleaseBufferForRaster(raster_buffer_.Pass());
- }
- void RunReplyOnOriginThread() override {
- DCHECK(!raster_buffer_);
reply_.Run(analysis_, !HasFinishedRunning());
}
@@ -127,11 +125,13 @@ class RasterTaskImpl : public RasterTask {
DCHECK(raster_source);
+ bool include_images = tile_resolution_ != LOW_RESOLUTION;
raster_buffer_->Playback(raster_source_.get(), content_rect_,
invalid_content_rect_, new_content_id_,
- contents_scale_);
+ contents_scale_, include_images);
}
+ const Resource* resource_;
RasterSource::SolidColorAnalysis analysis_;
scoped_refptr<RasterSource> raster_source_;
gfx::Rect content_rect_;
@@ -153,47 +153,6 @@ class RasterTaskImpl : public RasterTask {
DISALLOW_COPY_AND_ASSIGN(RasterTaskImpl);
};
-class ImageDecodeTaskImpl : public ImageDecodeTask {
- public:
- ImageDecodeTaskImpl(SkPixelRef* pixel_ref,
- uint64_t source_prepare_tiles_id,
- const base::Callback<void(bool was_canceled)>& reply)
- : pixel_ref_(skia::SharePtr(pixel_ref)),
- source_prepare_tiles_id_(source_prepare_tiles_id),
- reply_(reply) {}
-
- // Overridden from Task:
- void RunOnWorkerThread() override {
- TRACE_EVENT1("cc", "ImageDecodeTaskImpl::RunOnWorkerThread",
- "source_prepare_tiles_id", source_prepare_tiles_id_);
-
- devtools_instrumentation::ScopedImageDecodeTask image_decode_task(
- pixel_ref_.get());
- // This will cause the image referred to by pixel ref to be decoded.
- pixel_ref_->lockPixels();
- pixel_ref_->unlockPixels();
-
- // Release the reference after decoding image to ensure that it is not
- // kept alive unless needed.
- pixel_ref_.clear();
- }
-
- // Overridden from TileTask:
- void ScheduleOnOriginThread(TileTaskClient* client) override {}
- void CompleteOnOriginThread(TileTaskClient* client) override {}
- void RunReplyOnOriginThread() override { reply_.Run(!HasFinishedRunning()); }
-
- protected:
- ~ImageDecodeTaskImpl() override {}
-
- private:
- skia::RefPtr<SkPixelRef> pixel_ref_;
- uint64_t source_prepare_tiles_id_;
- const base::Callback<void(bool was_canceled)> reply_;
-
- DISALLOW_COPY_AND_ASSIGN(ImageDecodeTaskImpl);
-};
-
const char* TaskSetName(TaskSet task_set) {
switch (task_set) {
case TileManager::ALL:
@@ -253,8 +212,8 @@ TileManager::TileManager(
base::Bind(&TileManager::CheckAndIssueSignals,
base::Unretained(this))),
has_scheduled_tile_tasks_(false),
- prepare_tiles_count_(0u) {
-}
+ prepare_tiles_count_(0u),
+ next_tile_id_(0u) {}
TileManager::~TileManager() {
FinishTasksAndCleanUp();
@@ -300,13 +259,6 @@ void TileManager::Release(Tile* tile) {
released_tiles_.push_back(tile);
}
-TaskSetCollection TileManager::TasksThatShouldBeForcedToComplete() const {
- TaskSetCollection tasks_that_should_be_forced_to_complete;
- if (global_state_.tree_priority != SMOOTHNESS_TAKES_PRIORITY)
- tasks_that_should_be_forced_to_complete[REQUIRED_FOR_ACTIVATION] = true;
- return tasks_that_should_be_forced_to_complete;
-}
-
void TileManager::FreeResourcesForReleasedTiles() {
for (auto* tile : released_tiles_)
FreeResourcesForTile(tile);
@@ -324,14 +276,7 @@ void TileManager::CleanUpReleasedTiles() {
DCHECK(tiles_.find(tile->id()) != tiles_.end());
tiles_.erase(tile->id());
- LayerCountMap::iterator layer_it =
- used_layer_counts_.find(tile->layer_id());
- DCHECK_GT(layer_it->second, 0);
- if (--layer_it->second == 0) {
- used_layer_counts_.erase(layer_it);
- image_decode_tasks_.erase(tile->layer_id());
- }
-
+ image_decode_controller_.SubtractLayerUsedCount(tile->layer_id());
delete tile;
}
released_tiles_.swap(tiles_to_retain);
@@ -347,9 +292,8 @@ void TileManager::DidFinishRunningTileTasks(TaskSet task_set) {
case ALL: {
has_scheduled_tile_tasks_ = false;
- bool memory_usage_above_limit =
- resource_pool_->total_memory_usage_bytes() >
- global_state_.soft_memory_limit_in_bytes;
+ bool memory_usage_above_limit = resource_pool_->memory_usage_bytes() >
+ global_state_.soft_memory_limit_in_bytes;
if (all_tiles_that_need_to_be_rasterized_are_scheduled_ &&
!memory_usage_above_limit) {
@@ -423,10 +367,6 @@ bool TileManager::PrepareTiles(
TRACE_EVENT_INSTANT1("cc", "DidPrepareTiles", TRACE_EVENT_SCOPE_THREAD,
"state", BasicStateAsValue());
-
- TRACE_COUNTER_ID1("cc", "unused_memory_bytes", this,
- resource_pool_->total_memory_usage_bytes() -
- resource_pool_->acquired_memory_usage_bytes());
return true;
}
@@ -541,7 +481,7 @@ void TileManager::AssignGpuMemoryToTiles(
// or deleted. If this operation becomes expensive too, only do this after
// some resource(s) was returned. Note that in that case, one also need to
// invalidate when releasing some resource from the pool.
- resource_pool_->CheckBusyResources(false);
+ resource_pool_->CheckBusyResources();
// Now give memory out to the tiles until we're out, and build
// the needs-to-be-rasterized queue.
@@ -553,8 +493,8 @@ void TileManager::AssignGpuMemoryToTiles(
global_state_.num_resources_limit);
MemoryUsage soft_memory_limit(global_state_.soft_memory_limit_in_bytes,
global_state_.num_resources_limit);
- MemoryUsage memory_usage(resource_pool_->acquired_memory_usage_bytes(),
- resource_pool_->acquired_resource_count());
+ MemoryUsage memory_usage(resource_pool_->memory_usage_bytes(),
+ resource_pool_->resource_count());
scoped_ptr<EvictionTilePriorityQueue> eviction_priority_queue;
for (; !raster_priority_queue->IsEmpty(); raster_priority_queue->Pop()) {
@@ -587,7 +527,7 @@ void TileManager::AssignGpuMemoryToTiles(
MemoryUsage memory_required_by_tile_to_be_scheduled;
if (!tile->raster_task_.get()) {
memory_required_by_tile_to_be_scheduled = MemoryUsage::FromConfig(
- tile->desired_texture_size(), tile_task_runner_->GetResourceFormat());
+ tile->desired_texture_size(), DetermineResourceFormat(tile));
}
bool tile_is_needed_now = priority.priority_bin == TilePriority::NOW;
@@ -646,8 +586,10 @@ void TileManager::AssignGpuMemoryToTiles(
void TileManager::FreeResourcesForTile(Tile* tile) {
TileDrawInfo& draw_info = tile->draw_info();
- if (draw_info.resource_)
- resource_pool_->ReleaseResource(draw_info.resource_.Pass(), tile->id());
+ if (draw_info.resource_) {
+ resource_pool_->ReleaseResource(draw_info.resource_, tile->id());
+ draw_info.resource_ = nullptr;
+ }
}
void TileManager::FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw(
@@ -712,21 +654,11 @@ void TileManager::ScheduleTasks(
did_check_for_completed_tasks_since_last_schedule_tasks_ = false;
}
-scoped_refptr<ImageDecodeTask> TileManager::CreateImageDecodeTask(
- Tile* tile,
- SkPixelRef* pixel_ref) {
- return make_scoped_refptr(new ImageDecodeTaskImpl(
- pixel_ref, prepare_tiles_count_,
- base::Bind(&TileManager::OnImageDecodeTaskCompleted,
- base::Unretained(this), tile->layer_id(),
- base::Unretained(pixel_ref))));
-}
-
scoped_refptr<RasterTask> TileManager::CreateRasterTask(
const PrioritizedTile& prioritized_tile) {
Tile* tile = prioritized_tile.tile();
uint64_t resource_content_id = 0;
- scoped_ptr<ScopedResource> resource;
+ Resource* resource = nullptr;
if (tile->invalidated_id()) {
// TODO(danakj): For resources that are in use, we should still grab them
// and copy from them instead of rastering everything. crbug.com/492754
@@ -735,73 +667,39 @@ scoped_refptr<RasterTask> TileManager::CreateRasterTask(
}
if (resource) {
resource_content_id = tile->invalidated_id();
- DCHECK_EQ(tile_task_runner_->GetResourceFormat(), resource->format());
+ DCHECK_EQ(DetermineResourceFormat(tile), resource->format());
DCHECK_EQ(tile->desired_texture_size().ToString(),
resource->size().ToString());
} else {
- resource = resource_pool_->AcquireResource(
- tile->desired_texture_size(), tile_task_runner_->GetResourceFormat());
+ resource = resource_pool_->AcquireResource(tile->desired_texture_size(),
+ DetermineResourceFormat(tile));
}
- const ScopedResource* const_resource = resource.get();
// Create and queue all image decode tasks that this tile depends on.
ImageDecodeTask::Vector decode_tasks;
- PixelRefTaskMap& existing_pixel_refs = image_decode_tasks_[tile->layer_id()];
- std::vector<SkPixelRef*> pixel_refs;
- prioritized_tile.raster_source()->GatherPixelRefs(
- tile->content_rect(), tile->contents_scale(), &pixel_refs);
- for (SkPixelRef* pixel_ref : pixel_refs) {
- uint32_t id = pixel_ref->getGenerationID();
-
- // Append existing image decode task if available.
- PixelRefTaskMap::iterator decode_task_it = existing_pixel_refs.find(id);
- if (decode_task_it != existing_pixel_refs.end()) {
- decode_tasks.push_back(decode_task_it->second);
- continue;
- }
-
- // Create and append new image decode task for this pixel ref.
- scoped_refptr<ImageDecodeTask> decode_task =
- CreateImageDecodeTask(tile, pixel_ref);
- decode_tasks.push_back(decode_task);
- existing_pixel_refs[id] = decode_task;
+ std::vector<PositionImage> images;
+ prioritized_tile.raster_source()->GetDiscardableImagesInRect(
+ tile->enclosing_layer_rect(), &images);
+ for (const auto& image : images) {
+ decode_tasks.push_back(image_decode_controller_.GetTaskForImage(
+ image, tile->layer_id(), prepare_tiles_count_));
}
return make_scoped_refptr(new RasterTaskImpl(
- const_resource, prioritized_tile.raster_source(), tile->content_rect(),
+ resource, prioritized_tile.raster_source(), tile->content_rect(),
tile->invalidated_content_rect(), tile->contents_scale(),
prioritized_tile.priority().resolution, tile->layer_id(),
prepare_tiles_count_, static_cast<const void*>(tile), tile->id(),
tile->invalidated_id(), resource_content_id, tile->source_frame_number(),
tile->use_picture_analysis(),
base::Bind(&TileManager::OnRasterTaskCompleted, base::Unretained(this),
- tile->id(), base::Passed(&resource)),
+ tile->id(), resource),
&decode_tasks));
}
-void TileManager::OnImageDecodeTaskCompleted(int layer_id,
- SkPixelRef* pixel_ref,
- bool was_canceled) {
- // If the task was canceled, we need to clean it up
- // from |image_decode_tasks_|.
- if (!was_canceled)
- return;
-
- LayerPixelRefTaskMap::iterator layer_it = image_decode_tasks_.find(layer_id);
- if (layer_it == image_decode_tasks_.end())
- return;
-
- PixelRefTaskMap& pixel_ref_tasks = layer_it->second;
- PixelRefTaskMap::iterator task_it =
- pixel_ref_tasks.find(pixel_ref->getGenerationID());
-
- if (task_it != pixel_ref_tasks.end())
- pixel_ref_tasks.erase(task_it);
-}
-
void TileManager::OnRasterTaskCompleted(
Tile::Id tile_id,
- scoped_ptr<ScopedResource> resource,
+ Resource* resource,
const RasterSource::SolidColorAnalysis& analysis,
bool was_canceled) {
DCHECK(tiles_.find(tile_id) != tiles_.end());
@@ -813,16 +711,20 @@ void TileManager::OnRasterTaskCompleted(
if (was_canceled) {
++flush_stats_.canceled_count;
- resource_pool_->ReleaseResource(resource.Pass(), tile->invalidated_id());
+ // TODO(ericrk): If more partial raster work is done in the future, it may
+ // be worth returning the resource to the pool with its previous ID (not
+ // currently tracked). crrev.com/1370333002/#ps40001 has a possible method
+ // of achieving this.
+ resource_pool_->ReleaseResource(resource, 0 /* content_id */);
return;
}
- UpdateTileDrawInfo(tile, resource.Pass(), analysis);
+ UpdateTileDrawInfo(tile, resource, analysis);
}
void TileManager::UpdateTileDrawInfo(
Tile* tile,
- scoped_ptr<ScopedResource> resource,
+ Resource* resource,
const RasterSource::SolidColorAnalysis& analysis) {
TileDrawInfo& draw_info = tile->draw_info();
@@ -831,16 +733,17 @@ void TileManager::UpdateTileDrawInfo(
if (analysis.is_solid_color) {
draw_info.set_solid_color(analysis.solid_color);
if (resource) {
- // Pass the old tile id here because the tile is solid color so we did not
- // raster anything into the tile resource.
- resource_pool_->ReleaseResource(resource.Pass(), tile->invalidated_id());
+ // TODO(ericrk): If more partial raster work is done in the future, it may
+ // be worth returning the resource to the pool with its previous ID (not
+ // currently tracked). crrev.com/1370333002/#ps40001 has a possible method
+ // of achieving this.
+ resource_pool_->ReleaseResource(resource, 0 /* content_id */);
}
} else {
DCHECK(resource);
draw_info.set_use_resource();
- draw_info.resource_ = resource.Pass();
- draw_info.contents_swizzled_ =
- tile_task_runner_->GetResourceRequiresSwizzle();
+ draw_info.resource_ = resource;
+ draw_info.contents_swizzled_ = DetermineResourceRequiresSwizzle(tile);
}
DCHECK(draw_info.IsReadyToDraw());
draw_info.set_was_ever_ready_to_draw();
@@ -848,22 +751,19 @@ void TileManager::UpdateTileDrawInfo(
client_->NotifyTileStateChanged(tile);
}
-ScopedTilePtr TileManager::CreateTile(const gfx::Size& desired_texture_size,
- const gfx::Rect& content_rect,
- float contents_scale,
+ScopedTilePtr TileManager::CreateTile(const Tile::CreateInfo& info,
int layer_id,
int source_frame_number,
int flags) {
// We need to have a tile task worker pool to do anything meaningful with
// tiles.
DCHECK(tile_task_runner_);
- ScopedTilePtr tile(new Tile(this, desired_texture_size, content_rect,
- contents_scale, layer_id, source_frame_number,
- flags));
+ ScopedTilePtr tile(
+ new Tile(this, info, layer_id, source_frame_number, flags));
DCHECK(tiles_.find(tile->id()) == tiles_.end());
tiles_[tile->id()] = tile.get();
- used_layer_counts_[tile->layer_id()]++;
+ image_decode_controller_.AddLayerUsedCount(tile->layer_id());
return tile;
}
@@ -1024,6 +924,14 @@ void TileManager::CheckIfMoreTilesNeedToBePrepared() {
signals_check_notifier_.Schedule();
}
+ResourceFormat TileManager::DetermineResourceFormat(const Tile* tile) const {
+ return tile_task_runner_->GetResourceFormat(!tile->is_opaque());
+}
+
+bool TileManager::DetermineResourceRequiresSwizzle(const Tile* tile) const {
+ return tile_task_runner_->GetResourceRequiresSwizzle(!tile->is_opaque());
+}
+
TileManager::MemoryUsage::MemoryUsage() : memory_bytes_(0), resource_count_(0) {
}
@@ -1045,9 +953,10 @@ TileManager::MemoryUsage::MemoryUsage(size_t memory_bytes,
TileManager::MemoryUsage TileManager::MemoryUsage::FromConfig(
const gfx::Size& size,
ResourceFormat format) {
- // We can use UncheckedMemorySizeBytes here since this is used with a tile
+ // We can use UncheckedSizeInBytes here since this is used with a tile
// size which is determined by the compositor (it's at most max texture size).
- return MemoryUsage(Resource::UncheckedMemorySizeBytes(size, format), 1);
+ return MemoryUsage(ResourceUtil::UncheckedSizeInBytes<size_t>(size, format),
+ 1);
}
// static
diff --git a/chromium/cc/tiles/tile_manager.h b/chromium/cc/tiles/tile_manager.h
index a69e5a27dcf..d0ba944b32d 100644
--- a/chromium/cc/tiles/tile_manager.h
+++ b/chromium/cc/tiles/tile_manager.h
@@ -20,6 +20,7 @@
#include "cc/resources/memory_history.h"
#include "cc/resources/resource_pool.h"
#include "cc/tiles/eviction_tile_priority_queue.h"
+#include "cc/tiles/image_decode_controller.h"
#include "cc/tiles/raster_tile_priority_queue.h"
#include "cc/tiles/tile.h"
#include "cc/tiles/tile_draw_info.h"
@@ -132,9 +133,7 @@ class CC_EXPORT TileManager : public TileTaskRunnerClient {
// date draw information.
void Flush();
- ScopedTilePtr CreateTile(const gfx::Size& desired_texture_size,
- const gfx::Rect& content_rect,
- float contents_scale,
+ ScopedTilePtr CreateTile(const Tile::CreateInfo& info,
int layer_id,
int source_frame_number,
int flags);
@@ -155,7 +154,7 @@ class CC_EXPORT TileManager : public TileTaskRunnerClient {
TileDrawInfo& draw_info = tiles[i]->draw_info();
draw_info.resource_ = resource_pool_->AcquireResource(
tiles[i]->desired_texture_size(),
- tile_task_runner_->GetResourceFormat());
+ tile_task_runner_->GetResourceFormat(false));
}
}
@@ -214,10 +213,10 @@ class CC_EXPORT TileManager : public TileTaskRunnerClient {
friend class Tile;
// Virtual for testing.
virtual void Release(Tile* tile);
+ Tile::Id GetUniqueTileId() { return ++next_tile_id_; }
// Overriden from TileTaskRunnerClient:
void DidFinishRunningTileTasks(TaskSet task_set) override;
- TaskSetCollection TasksThatShouldBeForcedToComplete() const override;
typedef std::vector<PrioritizedTile> PrioritizedTileVector;
typedef std::set<Tile*> TileSet;
@@ -252,21 +251,16 @@ class CC_EXPORT TileManager : public TileTaskRunnerClient {
int resource_count_;
};
- void OnImageDecodeTaskCompleted(int layer_id,
- SkPixelRef* pixel_ref,
- bool was_canceled);
void OnRasterTaskCompleted(Tile::Id tile,
- scoped_ptr<ScopedResource> resource,
+ Resource* resource,
const RasterSource::SolidColorAnalysis& analysis,
bool was_canceled);
void UpdateTileDrawInfo(Tile* tile,
- scoped_ptr<ScopedResource> resource,
+ Resource* resource,
const RasterSource::SolidColorAnalysis& analysis);
void FreeResourcesForTile(Tile* tile);
void FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw(Tile* tile);
- scoped_refptr<ImageDecodeTask> CreateImageDecodeTask(Tile* tile,
- SkPixelRef* pixel_ref);
scoped_refptr<RasterTask> CreateRasterTask(
const PrioritizedTile& prioritized_tile);
@@ -286,6 +280,9 @@ class CC_EXPORT TileManager : public TileTaskRunnerClient {
void CheckIfMoreTilesNeedToBePrepared();
void CheckAndIssueSignals();
+ ResourceFormat DetermineResourceFormat(const Tile* tile) const;
+ bool DetermineResourceRequiresSwizzle(const Tile* tile) const;
+
TileManagerClient* client_;
scoped_refptr<base::SequencedTaskRunner> task_runner_;
ResourcePool* resource_pool_;
@@ -302,13 +299,7 @@ class CC_EXPORT TileManager : public TileTaskRunnerClient {
bool did_check_for_completed_tasks_since_last_schedule_tasks_;
bool did_oom_on_last_assign_;
- typedef base::hash_map<uint32_t, scoped_refptr<ImageDecodeTask>>
- PixelRefTaskMap;
- typedef base::hash_map<int, PixelRefTaskMap> LayerPixelRefTaskMap;
- LayerPixelRefTaskMap image_decode_tasks_;
-
- typedef base::hash_map<int, int> LayerCountMap;
- LayerCountMap used_layer_counts_;
+ ImageDecodeController image_decode_controller_;
RasterTaskCompletionStats flush_stats_;
@@ -339,6 +330,7 @@ class CC_EXPORT TileManager : public TileTaskRunnerClient {
bool has_scheduled_tile_tasks_;
uint64_t prepare_tiles_count_;
+ uint64_t next_tile_id_;
DISALLOW_COPY_AND_ASSIGN(TileManager);
};
diff --git a/chromium/cc/tiles/tile_manager_perftest.cc b/chromium/cc/tiles/tile_manager_perftest.cc
index eea9b94922b..c7337cfbbad 100644
--- a/chromium/cc/tiles/tile_manager_perftest.cc
+++ b/chromium/cc/tiles/tile_manager_perftest.cc
@@ -2,18 +2,19 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/lazy_instance.h"
#include "base/location.h"
#include "base/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "cc/debug/lap_timer.h"
#include "cc/raster/raster_buffer.h"
#include "cc/test/begin_frame_args_test.h"
+#include "cc/test/fake_display_list_raster_source.h"
#include "cc/test/fake_impl_proxy.h"
#include "cc/test/fake_layer_tree_host_impl.h"
#include "cc/test/fake_output_surface.h"
#include "cc/test/fake_output_surface_client.h"
#include "cc/test/fake_picture_layer_impl.h"
-#include "cc/test/fake_picture_pile_impl.h"
#include "cc/test/fake_tile_manager.h"
#include "cc/test/fake_tile_manager_client.h"
#include "cc/test/test_shared_bitmap_manager.h"
@@ -59,14 +60,15 @@ class FakeTileTaskRunnerImpl : public TileTaskRunner, public TileTaskClient {
task->WillComplete();
task->CompleteOnOriginThread(this);
task->DidComplete();
-
- task->RunReplyOnOriginThread();
}
completed_tasks_.clear();
}
- ResourceFormat GetResourceFormat() const override { return RGBA_8888; }
- bool GetResourceRequiresSwizzle() const override {
- return !PlatformColor::SameComponentOrder(GetResourceFormat());
+ ResourceFormat GetResourceFormat(bool must_support_alpha) const override {
+ return RGBA_8888;
+ }
+ bool GetResourceRequiresSwizzle(bool must_support_alpha) const override {
+ return !PlatformColor::SameComponentOrder(
+ GetResourceFormat(must_support_alpha));
}
// Overridden from TileTaskClient:
@@ -91,6 +93,7 @@ class TileManagerPerfTest : public testing::Test {
max_tiles_(10000),
id_(7),
proxy_(base::ThreadTaskRunnerHandle::Get()),
+ output_surface_(FakeOutputSurface::Create3d()),
host_impl_(LayerTreeSettings(),
&proxy_,
&shared_bitmap_manager_,
@@ -111,7 +114,7 @@ class TileManagerPerfTest : public testing::Test {
global_state_ = state;
host_impl_.resource_pool()->SetResourceUsageLimits(
- state.soft_memory_limit_in_bytes, 0, state.num_resources_limit);
+ state.soft_memory_limit_in_bytes, state.num_resources_limit);
host_impl_.tile_manager()->SetGlobalStateForTesting(state);
}
@@ -121,18 +124,18 @@ class TileManagerPerfTest : public testing::Test {
}
virtual void InitializeRenderer() {
- host_impl_.InitializeRenderer(FakeOutputSurface::Create3d().Pass());
+ host_impl_.InitializeRenderer(output_surface_.get());
tile_manager()->SetTileTaskRunnerForTesting(
g_fake_tile_task_runner.Pointer());
}
void SetupDefaultTrees(const gfx::Size& layer_bounds) {
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(kDefaultTileSize, layer_bounds);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateFilledPile(kDefaultTileSize, layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> active_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
- SetupTrees(pending_pile, active_pile);
+ SetupTrees(pending_raster_source, active_raster_source);
}
void ActivateTree() {
@@ -150,21 +153,22 @@ class TileManagerPerfTest : public testing::Test {
active_root_layer_->set_fixed_tile_size(tile_size);
}
- void SetupTrees(scoped_refptr<PicturePileImpl> pending_pile,
- scoped_refptr<PicturePileImpl> active_pile) {
- SetupPendingTree(active_pile);
+ void SetupTrees(scoped_refptr<RasterSource> pending_raster_source,
+ scoped_refptr<RasterSource> active_raster_source) {
+ SetupPendingTree(active_raster_source);
ActivateTree();
- SetupPendingTree(pending_pile);
+ SetupPendingTree(pending_raster_source);
}
- void SetupPendingTree(scoped_refptr<PicturePileImpl> pile) {
+ void SetupPendingTree(scoped_refptr<RasterSource> raster_source) {
host_impl_.CreatePendingTree();
LayerTreeImpl* pending_tree = host_impl_.pending_tree();
// Clear recycled tree.
pending_tree->DetachLayerTree();
scoped_ptr<FakePictureLayerImpl> pending_layer =
- FakePictureLayerImpl::CreateWithRasterSource(pending_tree, id_, pile);
+ FakePictureLayerImpl::CreateWithRasterSource(pending_tree, id_,
+ raster_source);
pending_layer->SetDrawsContent(true);
pending_layer->SetHasRenderSurface(true);
pending_tree->SetRootLayer(pending_layer.Pass());
@@ -346,12 +350,12 @@ class TileManagerPerfTest : public testing::Test {
int next_id = id_ + 1;
// Create the rest of the layers as children of the root layer.
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPile(kDefaultTileSize, layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
while (static_cast<int>(layers.size()) < layer_count) {
scoped_ptr<FakePictureLayerImpl> layer =
FakePictureLayerImpl::CreateWithRasterSource(
- host_impl_.pending_tree(), next_id, pile);
+ host_impl_.pending_tree(), next_id, raster_source);
layer->SetBounds(layer_bounds);
layer->SetDrawsContent(true);
layers.push_back(layer.get());
@@ -414,17 +418,14 @@ class TileManagerPerfTest : public testing::Test {
int max_tiles_;
int id_;
FakeImplProxy proxy_;
+ scoped_ptr<OutputSurface> output_surface_;
FakeLayerTreeHostImpl host_impl_;
FakePictureLayerImpl* pending_root_layer_;
FakePictureLayerImpl* active_root_layer_;
LapTimer timer_;
LayerTreeSettings settings_;
-
- static const gfx::Size kDefaultTileSize;
};
-const gfx::Size TileManagerPerfTest::kDefaultTileSize(100, 100);
-
TEST_F(TileManagerPerfTest, PrepareTiles) {
RunPrepareTilesTest("2_100", 2, 100);
RunPrepareTilesTest("2_500", 2, 500);
diff --git a/chromium/cc/tiles/tile_manager_unittest.cc b/chromium/cc/tiles/tile_manager_unittest.cc
index 4a663cefaf5..e68ea1ff779 100644
--- a/chromium/cc/tiles/tile_manager_unittest.cc
+++ b/chromium/cc/tiles/tile_manager_unittest.cc
@@ -4,16 +4,21 @@
#include "base/run_loop.h"
#include "base/thread_task_runner_handle.h"
+#include "cc/playback/display_list_raster_source.h"
+#include "cc/playback/display_list_recording_source.h"
+#include "cc/raster/raster_buffer.h"
#include "cc/resources/resource_pool.h"
#include "cc/test/begin_frame_args_test.h"
+#include "cc/test/fake_display_list_raster_source.h"
+#include "cc/test/fake_display_list_recording_source.h"
#include "cc/test/fake_impl_proxy.h"
#include "cc/test/fake_layer_tree_host_impl.h"
#include "cc/test/fake_output_surface.h"
#include "cc/test/fake_output_surface_client.h"
#include "cc/test/fake_picture_layer_impl.h"
#include "cc/test/fake_picture_layer_tiling_client.h"
-#include "cc/test/fake_picture_pile_impl.h"
#include "cc/test/fake_tile_manager.h"
+#include "cc/test/test_gpu_memory_buffer_manager.h"
#include "cc/test/test_shared_bitmap_manager.h"
#include "cc/test/test_task_graph_runner.h"
#include "cc/test/test_tile_priorities.h"
@@ -25,6 +30,7 @@
#include "cc/trees/layer_tree_impl.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkSurface.h"
namespace cc {
namespace {
@@ -42,10 +48,12 @@ class TileManagerTilePriorityQueueTest : public testing::Test {
ready_to_activate_(false),
id_(7),
proxy_(base::ThreadTaskRunnerHandle::Get()),
+ output_surface_(FakeOutputSurface::Create3d()),
host_impl_(LowResTilingsSettings(),
&proxy_,
&shared_bitmap_manager_,
- &task_graph_runner_) {}
+ &task_graph_runner_,
+ &gpu_memory_buffer_manager_) {}
void SetTreePriority(TreePriority tree_priority) {
GlobalStateThatImpactsTilePriority state;
@@ -60,7 +68,6 @@ class TileManagerTilePriorityQueueTest : public testing::Test {
global_state_ = state;
host_impl_.resource_pool()->SetResourceUsageLimits(
state.soft_memory_limit_in_bytes,
- state.soft_memory_limit_in_bytes,
state.num_resources_limit);
host_impl_.tile_manager()->SetGlobalStateForTesting(state);
}
@@ -71,26 +78,27 @@ class TileManagerTilePriorityQueueTest : public testing::Test {
}
virtual void InitializeRenderer() {
- host_impl_.InitializeRenderer(FakeOutputSurface::Create3d());
+ host_impl_.InitializeRenderer(output_surface_.get());
}
void SetupDefaultTrees(const gfx::Size& layer_bounds) {
- gfx::Size tile_size(100, 100);
-
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> active_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
- SetupTrees(pending_pile, active_pile);
+ SetupTrees(pending_raster_source, active_raster_source);
}
+ // This matches picture_layer_impl_unittest's ActivateTree.
void ActivateTree() {
host_impl_.ActivateSyncTree();
CHECK(!host_impl_.pending_tree());
pending_layer_ = NULL;
active_layer_ = static_cast<FakePictureLayerImpl*>(
host_impl_.active_tree()->LayerById(id_));
+ bool update_lcd_text = false;
+ host_impl_.active_tree()->UpdateDrawProperties(update_lcd_text);
}
void SetupDefaultTreesWithFixedTileSize(const gfx::Size& layer_bounds,
@@ -100,14 +108,14 @@ class TileManagerTilePriorityQueueTest : public testing::Test {
active_layer_->set_fixed_tile_size(tile_size);
}
- void SetupTrees(scoped_refptr<PicturePileImpl> pending_pile,
- scoped_refptr<PicturePileImpl> active_pile) {
- SetupPendingTree(active_pile);
+ void SetupTrees(scoped_refptr<RasterSource> pending_raster_source,
+ scoped_refptr<RasterSource> active_raster_source) {
+ SetupPendingTree(active_raster_source);
ActivateTree();
- SetupPendingTree(pending_pile);
+ SetupPendingTree(pending_raster_source);
}
- void SetupPendingTree(scoped_refptr<PicturePileImpl> pile) {
+ void SetupPendingTree(scoped_refptr<RasterSource> raster_source) {
host_impl_.CreatePendingTree();
LayerTreeImpl* pending_tree = host_impl_.pending_tree();
@@ -119,14 +127,14 @@ class TileManagerTilePriorityQueueTest : public testing::Test {
if (old_pending_root) {
pending_layer.reset(
static_cast<FakePictureLayerImpl*>(old_pending_root.release()));
- pending_layer->SetRasterSourceOnPending(pile, Region());
+ pending_layer->SetRasterSourceOnPending(raster_source, Region());
} else {
- pending_layer =
- FakePictureLayerImpl::CreateWithRasterSource(pending_tree, id_, pile);
+ pending_layer = FakePictureLayerImpl::CreateWithRasterSource(
+ pending_tree, id_, raster_source);
pending_layer->SetDrawsContent(true);
pending_layer->SetHasRenderSurface(true);
}
- // The bounds() just mirror the pile size.
+ // The bounds() just mirror the raster source size.
pending_layer->SetBounds(pending_layer->raster_source()->GetSize());
pending_tree->SetRootLayer(pending_layer.Pass());
@@ -145,11 +153,13 @@ class TileManagerTilePriorityQueueTest : public testing::Test {
TestSharedBitmapManager shared_bitmap_manager_;
TestTaskGraphRunner task_graph_runner_;
+ TestGpuMemoryBufferManager gpu_memory_buffer_manager_;
TileMemoryLimitPolicy memory_limit_policy_;
int max_tiles_;
bool ready_to_activate_;
int id_;
FakeImplProxy proxy_;
+ scoped_ptr<OutputSurface> output_surface_;
FakeLayerTreeHostImpl host_impl_;
FakePictureLayerImpl* pending_layer_;
FakePictureLayerImpl* active_layer_;
@@ -225,14 +235,11 @@ TEST_F(TileManagerTilePriorityQueueTest, RasterTilePriorityQueue) {
// Invalidate the pending tree.
pending_layer_->set_invalidation(invalidation);
pending_layer_->HighResTiling()->Invalidate(invalidation);
- pending_layer_->LowResTiling()->Invalidate(invalidation);
// Renew all of the tile priorities.
gfx::Rect viewport(50, 50, 100, 100);
pending_layer_->HighResTiling()->ComputeTilePriorityRects(viewport, 1.0f, 1.0,
Occlusion());
- pending_layer_->LowResTiling()->ComputeTilePriorityRects(viewport, 1.0f, 1.0,
- Occlusion());
active_layer_->HighResTiling()->ComputeTilePriorityRects(viewport, 1.0f, 1.0,
Occlusion());
active_layer_->LowResTiling()->ComputeTilePriorityRects(viewport, 1.0f, 1.0,
@@ -248,11 +255,6 @@ TEST_F(TileManagerTilePriorityQueueTest, RasterTilePriorityQueue) {
high_res_tiles.insert(pending_high_res_tiles[i]);
}
- std::vector<Tile*> pending_low_res_tiles =
- pending_layer_->LowResTiling()->AllTilesForTesting();
- for (size_t i = 0; i < pending_low_res_tiles.size(); ++i)
- all_tiles.insert(pending_low_res_tiles[i]);
-
std::vector<Tile*> active_high_res_tiles =
active_layer_->HighResTiling()->AllTilesForTesting();
for (size_t i = 0; i < active_high_res_tiles.size(); ++i) {
@@ -501,8 +503,6 @@ TEST_F(TileManagerTilePriorityQueueTest, RasterTilePriorityQueueInvalidation) {
pending_layer_->set_invalidation(invalidation);
pending_layer_->HighResTiling()->Invalidate(invalidation);
pending_layer_->HighResTiling()->CreateMissingTilesInLiveTilesRect();
- pending_layer_->LowResTiling()->Invalidate(invalidation);
- pending_layer_->LowResTiling()->CreateMissingTilesInLiveTilesRect();
// Sanity checks: Tile at 0, 0 not exist on the pending tree (it's not
// invalidated). Tile 1, 0 should exist on both.
@@ -602,12 +602,11 @@ TEST_F(TileManagerTilePriorityQueueTest, ActivationComesBeforeEventually) {
SetupDefaultTrees(layer_bounds);
// Create a pending child layer.
- gfx::Size tile_size(256, 256);
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
scoped_ptr<FakePictureLayerImpl> pending_child =
- FakePictureLayerImpl::CreateWithRasterSource(host_impl_.pending_tree(),
- id_ + 1, pending_pile);
+ FakePictureLayerImpl::CreateWithRasterSource(
+ host_impl_.pending_tree(), id_ + 1, pending_raster_source);
FakePictureLayerImpl* pending_child_raw = pending_child.get();
pending_child_raw->SetDrawsContent(true);
pending_layer_->AddChild(pending_child.Pass());
@@ -646,6 +645,10 @@ TEST_F(TileManagerTilePriorityQueueTest, EvictionTilePriorityQueue) {
const gfx::Size layer_bounds(1000, 1000);
host_impl_.SetViewportSize(layer_bounds);
SetupDefaultTrees(layer_bounds);
+ ASSERT_TRUE(active_layer_->HighResTiling());
+ ASSERT_TRUE(active_layer_->LowResTiling());
+ ASSERT_TRUE(pending_layer_->HighResTiling());
+ EXPECT_FALSE(pending_layer_->LowResTiling());
scoped_ptr<EvictionTilePriorityQueue> empty_queue(
host_impl_.BuildEvictionQueue(SAME_PRIORITY_FOR_BOTH_TREES));
@@ -693,15 +696,12 @@ TEST_F(TileManagerTilePriorityQueueTest, EvictionTilePriorityQueue) {
pending_layer_->set_invalidation(invalidation);
pending_layer_->HighResTiling()->Invalidate(invalidation);
pending_layer_->HighResTiling()->CreateMissingTilesInLiveTilesRect();
- pending_layer_->LowResTiling()->Invalidate(invalidation);
- pending_layer_->LowResTiling()->CreateMissingTilesInLiveTilesRect();
+ EXPECT_FALSE(pending_layer_->LowResTiling());
// Renew all of the tile priorities.
gfx::Rect viewport(50, 50, 100, 100);
pending_layer_->HighResTiling()->ComputeTilePriorityRects(viewport, 1.0f, 1.0,
Occlusion());
- pending_layer_->LowResTiling()->ComputeTilePriorityRects(viewport, 1.0f, 1.0,
- Occlusion());
active_layer_->HighResTiling()->ComputeTilePriorityRects(viewport, 1.0f, 1.0,
Occlusion());
active_layer_->LowResTiling()->ComputeTilePriorityRects(viewport, 1.0f, 1.0,
@@ -714,11 +714,6 @@ TEST_F(TileManagerTilePriorityQueueTest, EvictionTilePriorityQueue) {
for (size_t i = 0; i < pending_high_res_tiles.size(); ++i)
all_tiles.insert(pending_high_res_tiles[i]);
- std::vector<Tile*> pending_low_res_tiles =
- pending_layer_->LowResTiling()->AllTilesForTesting();
- for (size_t i = 0; i < pending_low_res_tiles.size(); ++i)
- all_tiles.insert(pending_low_res_tiles[i]);
-
std::vector<Tile*> active_high_res_tiles =
active_layer_->HighResTiling()->AllTilesForTesting();
for (size_t i = 0; i < active_high_res_tiles.size(); ++i)
@@ -772,7 +767,7 @@ TEST_F(TileManagerTilePriorityQueueTest, EvictionTilePriorityQueue) {
// Ensure that the distance is decreasing many more times than increasing.
EXPECT_EQ(3, distance_increasing);
- EXPECT_EQ(17, distance_decreasing);
+ EXPECT_EQ(16, distance_decreasing);
EXPECT_EQ(tile_count, smoothness_tiles.size());
EXPECT_EQ(all_tiles, smoothness_tiles);
@@ -813,7 +808,7 @@ TEST_F(TileManagerTilePriorityQueueTest, EvictionTilePriorityQueue) {
// Ensure that the distance is decreasing many more times than increasing.
EXPECT_EQ(3, distance_increasing);
- EXPECT_EQ(17, distance_decreasing);
+ EXPECT_EQ(16, distance_decreasing);
EXPECT_EQ(tile_count, new_content_tiles.size());
EXPECT_EQ(all_tiles, new_content_tiles);
}
@@ -822,18 +817,17 @@ TEST_F(TileManagerTilePriorityQueueTest,
EvictionTilePriorityQueueWithOcclusion) {
host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));
- gfx::Size tile_size(102, 102);
gfx::Size layer_bounds(1000, 1000);
host_impl_.SetViewportSize(layer_bounds);
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- SetupPendingTree(pending_pile);
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
+ SetupPendingTree(pending_raster_source);
scoped_ptr<FakePictureLayerImpl> pending_child =
FakePictureLayerImpl::CreateWithRasterSource(host_impl_.pending_tree(), 2,
- pending_pile);
+ pending_raster_source);
pending_layer_->AddChild(pending_child.Pass());
FakePictureLayerImpl* pending_child_layer =
@@ -845,7 +839,7 @@ TEST_F(TileManagerTilePriorityQueueTest,
host_impl_.pending_tree()->UpdateDrawProperties(update_lcd_text);
ActivateTree();
- SetupPendingTree(pending_pile);
+ SetupPendingTree(pending_raster_source);
FakePictureLayerImpl* active_child_layer =
static_cast<FakePictureLayerImpl*>(active_layer_->children()[0]);
@@ -867,12 +861,8 @@ TEST_F(TileManagerTilePriorityQueueTest,
gfx::Rect viewport(layer_bounds);
pending_layer_->HighResTiling()->ComputeTilePriorityRects(viewport, 1.0f, 1.0,
Occlusion());
- pending_layer_->LowResTiling()->ComputeTilePriorityRects(viewport, 1.0f, 1.0,
- Occlusion());
pending_child_layer->HighResTiling()->ComputeTilePriorityRects(
viewport, 1.0f, 1.0, Occlusion());
- pending_child_layer->LowResTiling()->ComputeTilePriorityRects(
- viewport, 1.0f, 1.0, Occlusion());
active_layer_->HighResTiling()->ComputeTilePriorityRects(viewport, 1.0f, 1.0,
Occlusion());
@@ -890,24 +880,12 @@ TEST_F(TileManagerTilePriorityQueueTest,
all_tiles.insert(pending_high_res_tiles.begin(),
pending_high_res_tiles.end());
- std::vector<Tile*> pending_low_res_tiles =
- pending_layer_->LowResTiling()->AllTilesForTesting();
- all_tiles.insert(pending_low_res_tiles.begin(), pending_low_res_tiles.end());
-
// Set all tiles on the pending_child_layer as occluded on the pending tree.
std::vector<Tile*> pending_child_high_res_tiles =
pending_child_layer->HighResTiling()->AllTilesForTesting();
pending_child_layer->HighResTiling()->SetAllTilesOccludedForTesting();
active_child_layer->HighResTiling()->SetAllTilesOccludedForTesting();
- all_tiles.insert(pending_child_high_res_tiles.begin(),
- pending_child_high_res_tiles.end());
-
- std::vector<Tile*> pending_child_low_res_tiles =
- pending_child_layer->LowResTiling()->AllTilesForTesting();
- pending_child_layer->LowResTiling()->SetAllTilesOccludedForTesting();
active_child_layer->LowResTiling()->SetAllTilesOccludedForTesting();
- all_tiles.insert(pending_child_low_res_tiles.begin(),
- pending_child_low_res_tiles.end());
tile_manager()->InitializeTilesWithResourcesForTesting(
std::vector<Tile*>(all_tiles.begin(), all_tiles.end()));
@@ -947,8 +925,7 @@ TEST_F(TileManagerTilePriorityQueueTest,
last_tile = prioritized_tile;
queue->Pop();
}
- size_t expected_occluded_count =
- pending_child_high_res_tiles.size() + pending_child_low_res_tiles.size();
+ size_t expected_occluded_count = pending_child_high_res_tiles.size();
EXPECT_EQ(expected_occluded_count, occluded_count);
}
@@ -956,16 +933,15 @@ TEST_F(TileManagerTilePriorityQueueTest,
EvictionTilePriorityQueueWithTransparentLayer) {
host_impl_.AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));
- gfx::Size tile_size(102, 102);
gfx::Size layer_bounds(1000, 1000);
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- SetupPendingTree(pending_pile);
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
+ SetupPendingTree(pending_raster_source);
scoped_ptr<FakePictureLayerImpl> pending_child =
FakePictureLayerImpl::CreateWithRasterSource(host_impl_.pending_tree(), 2,
- pending_pile);
+ pending_raster_source);
FakePictureLayerImpl* pending_child_layer = pending_child.get();
pending_layer_->AddChild(pending_child.Pass());
@@ -986,12 +962,8 @@ TEST_F(TileManagerTilePriorityQueueTest,
gfx::Rect viewport(layer_bounds);
pending_layer_->HighResTiling()->ComputeTilePriorityRects(viewport, 1.0f, 1.0,
Occlusion());
- pending_layer_->LowResTiling()->ComputeTilePriorityRects(viewport, 1.0f, 1.0,
- Occlusion());
pending_child_layer->HighResTiling()->ComputeTilePriorityRects(
viewport, 1.0f, 1.0, Occlusion());
- pending_child_layer->LowResTiling()->ComputeTilePriorityRects(
- viewport, 1.0f, 1.0, Occlusion());
// Populate all tiles directly from the tilings.
std::set<Tile*> all_pending_tiles;
@@ -1001,12 +973,6 @@ TEST_F(TileManagerTilePriorityQueueTest,
pending_high_res_tiles.end());
EXPECT_EQ(16u, pending_high_res_tiles.size());
- std::vector<Tile*> pending_low_res_tiles =
- pending_layer_->LowResTiling()->AllTilesForTesting();
- all_pending_tiles.insert(pending_low_res_tiles.begin(),
- pending_low_res_tiles.end());
- EXPECT_EQ(1u, pending_low_res_tiles.size());
-
std::set<Tile*> all_pending_child_tiles;
std::vector<Tile*> pending_child_high_res_tiles =
pending_child_layer->HighResTiling()->AllTilesForTesting();
@@ -1014,12 +980,6 @@ TEST_F(TileManagerTilePriorityQueueTest,
pending_child_high_res_tiles.end());
EXPECT_EQ(16u, pending_child_high_res_tiles.size());
- std::vector<Tile*> pending_child_low_res_tiles =
- pending_child_layer->LowResTiling()->AllTilesForTesting();
- all_pending_child_tiles.insert(pending_child_low_res_tiles.begin(),
- pending_child_low_res_tiles.end());
- EXPECT_EQ(1u, pending_child_low_res_tiles.size());
-
std::set<Tile*> all_tiles = all_pending_tiles;
all_tiles.insert(all_pending_child_tiles.begin(),
all_pending_child_tiles.end());
@@ -1161,16 +1121,15 @@ TEST_F(TileManagerTilePriorityQueueTest,
client.SetTileSize(gfx::Size(30, 30));
LayerTreeSettings settings;
- settings.max_tiles_for_interest_area = 10000;
scoped_ptr<PictureLayerTilingSet> tiling_set = PictureLayerTilingSet::Create(
- ACTIVE_TREE, &client, settings.max_tiles_for_interest_area,
+ ACTIVE_TREE, &client, settings.tiling_interest_area_padding,
settings.skewport_target_time_in_seconds,
settings.skewport_extrapolation_limit_in_content_pixels);
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(layer_bounds);
- PictureLayerTiling* tiling = tiling_set->AddTiling(1.0f, pile);
+ scoped_refptr<FakeDisplayListRasterSource> raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
+ PictureLayerTiling* tiling = tiling_set->AddTiling(1.0f, raster_source);
tiling->set_resolution(HIGH_RESOLUTION);
tiling_set->UpdateTilePriorities(viewport, 1.0f, 1.0, Occlusion(), true);
@@ -1271,16 +1230,15 @@ TEST_F(TileManagerTilePriorityQueueTest,
client.SetTileSize(gfx::Size(30, 30));
LayerTreeSettings settings;
- settings.max_tiles_for_interest_area = 10000;
scoped_ptr<PictureLayerTilingSet> tiling_set = PictureLayerTilingSet::Create(
- ACTIVE_TREE, &client, settings.max_tiles_for_interest_area,
+ ACTIVE_TREE, &client, settings.tiling_interest_area_padding,
settings.skewport_target_time_in_seconds,
settings.skewport_extrapolation_limit_in_content_pixels);
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(layer_bounds);
- PictureLayerTiling* tiling = tiling_set->AddTiling(1.0f, pile);
+ scoped_refptr<FakeDisplayListRasterSource> raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
+ PictureLayerTiling* tiling = tiling_set->AddTiling(1.0f, raster_source);
tiling->set_resolution(HIGH_RESOLUTION);
tiling_set->UpdateTilePriorities(viewport, 1.0f, 1.0, Occlusion(), true);
@@ -1388,22 +1346,21 @@ TEST_F(TileManagerTilePriorityQueueTest,
EXPECT_EQ(RGBA_8888, host_impl_.resource_provider()->best_texture_format());
ManagedMemoryPolicy policy = host_impl_.ActualManagedMemoryPolicy();
- policy.bytes_limit_when_visible =
- Resource::UncheckedMemorySizeBytes(gfx::Size(256, 256), RGBA_8888);
+ policy.bytes_limit_when_visible = ResourceUtil::UncheckedSizeInBytes<size_t>(
+ gfx::Size(256, 256), RGBA_8888);
host_impl_.SetMemoryPolicy(policy);
EXPECT_FALSE(host_impl_.is_likely_to_require_a_draw());
host_impl_.tile_manager()->PrepareTiles(host_impl_.global_tile_state());
EXPECT_TRUE(host_impl_.is_likely_to_require_a_draw());
- scoped_ptr<ScopedResource> resource =
- host_impl_.resource_pool()->AcquireResource(gfx::Size(256, 256),
- RGBA_8888);
+ Resource* resource = host_impl_.resource_pool()->AcquireResource(
+ gfx::Size(256, 256), RGBA_8888);
host_impl_.tile_manager()->CheckIfMoreTilesNeedToBePreparedForTesting();
EXPECT_FALSE(host_impl_.is_likely_to_require_a_draw());
- host_impl_.resource_pool()->ReleaseResource(resource.Pass(), 0);
+ host_impl_.resource_pool()->ReleaseResource(resource, 0);
}
TEST_F(TileManagerTilePriorityQueueTest, RasterQueueAllUsesCorrectTileBounds) {
@@ -1411,20 +1368,20 @@ TEST_F(TileManagerTilePriorityQueueTest, RasterQueueAllUsesCorrectTileBounds) {
// tile iteration.
gfx::Size layer_bounds(1, 1);
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(layer_bounds);
+ scoped_refptr<FakeDisplayListRasterSource> raster_source =
+ FakeDisplayListRasterSource::CreateFilled(layer_bounds);
FakePictureLayerTilingClient pending_client;
pending_client.SetTileSize(gfx::Size(64, 64));
- auto tiling_set = PictureLayerTilingSet::Create(
+ scoped_ptr<PictureLayerTilingSet> tiling_set = PictureLayerTilingSet::Create(
WhichTree::ACTIVE_TREE, &pending_client, 1.0f, 1.0f, 1000);
pending_client.set_twin_tiling_set(tiling_set.get());
- auto tiling = tiling_set->AddTiling(1.0f, pile);
+ auto* tiling = tiling_set->AddTiling(1.0f, raster_source);
- tiling->CreateAllTilesForTesting();
tiling->set_resolution(HIGH_RESOLUTION);
+ tiling->CreateAllTilesForTesting();
// The tile is (0, 0, 1, 1), create an intersecting and non-intersecting
// rectangle to test the advance phase with. The tile size is (64, 64), so
@@ -1467,7 +1424,13 @@ TEST_F(TileManagerTilePriorityQueueTest, RasterQueueAllUsesCorrectTileBounds) {
class TileManagerTest : public testing::Test {
public:
TileManagerTest()
- : host_impl_(&proxy_, &shared_bitmap_manager_, &task_graph_runner_) {}
+ : output_surface_(FakeOutputSurface::CreateSoftware(
+ make_scoped_ptr(new SoftwareOutputDevice))),
+ host_impl_(new MockLayerTreeHostImpl(&proxy_,
+ &shared_bitmap_manager_,
+ &task_graph_runner_)) {
+ host_impl_->InitializeRenderer(output_surface_.get());
+ }
protected:
// MockLayerTreeHostImpl allows us to intercept tile manager callbacks.
@@ -1476,9 +1439,7 @@ class TileManagerTest : public testing::Test {
MockLayerTreeHostImpl(Proxy* proxy,
SharedBitmapManager* manager,
TaskGraphRunner* task_graph_runner)
- : FakeLayerTreeHostImpl(proxy, manager, task_graph_runner) {
- InitializeRenderer(FakeOutputSurface::Create3d());
- }
+ : FakeLayerTreeHostImpl(proxy, manager, task_graph_runner) {}
MOCK_METHOD0(NotifyAllTileTasksCompleted, void());
};
@@ -1486,7 +1447,8 @@ class TileManagerTest : public testing::Test {
TestSharedBitmapManager shared_bitmap_manager_;
TestTaskGraphRunner task_graph_runner_;
FakeImplProxy proxy_;
- MockLayerTreeHostImpl host_impl_;
+ scoped_ptr<OutputSurface> output_surface_;
+ scoped_ptr<MockLayerTreeHostImpl> host_impl_;
};
// Test to ensure that we call NotifyAllTileTasksCompleted when PrepareTiles is
@@ -1495,11 +1457,11 @@ TEST_F(TileManagerTest, AllWorkFinishedTest) {
// Check with no tile work enqueued.
{
base::RunLoop run_loop;
- EXPECT_FALSE(host_impl_.tile_manager()->HasScheduledTileTasksForTesting());
- EXPECT_CALL(host_impl_, NotifyAllTileTasksCompleted())
+ EXPECT_FALSE(host_impl_->tile_manager()->HasScheduledTileTasksForTesting());
+ EXPECT_CALL(*host_impl_, NotifyAllTileTasksCompleted())
.WillOnce(testing::Invoke([&run_loop]() { run_loop.Quit(); }));
- host_impl_.tile_manager()->PrepareTiles(host_impl_.global_tile_state());
- EXPECT_TRUE(host_impl_.tile_manager()->HasScheduledTileTasksForTesting());
+ host_impl_->tile_manager()->PrepareTiles(host_impl_->global_tile_state());
+ EXPECT_TRUE(host_impl_->tile_manager()->HasScheduledTileTasksForTesting());
run_loop.Run();
}
@@ -1507,15 +1469,189 @@ TEST_F(TileManagerTest, AllWorkFinishedTest) {
// callback.
{
base::RunLoop run_loop;
- EXPECT_FALSE(host_impl_.tile_manager()->HasScheduledTileTasksForTesting());
- EXPECT_CALL(host_impl_, NotifyAllTileTasksCompleted())
+ EXPECT_FALSE(host_impl_->tile_manager()->HasScheduledTileTasksForTesting());
+ EXPECT_CALL(*host_impl_, NotifyAllTileTasksCompleted())
+ .WillOnce(testing::Invoke([&run_loop]() { run_loop.Quit(); }));
+ host_impl_->tile_manager()->PrepareTiles(host_impl_->global_tile_state());
+ host_impl_->tile_manager()->SetMoreTilesNeedToBeRasterizedForTesting();
+ EXPECT_TRUE(host_impl_->tile_manager()->HasScheduledTileTasksForTesting());
+ run_loop.Run();
+ }
+}
+
+TEST_F(TileManagerTest, LowResHasNoImage) {
+ gfx::Size size(10, 12);
+ TileResolution resolutions[] = {HIGH_RESOLUTION, LOW_RESOLUTION};
+
+ for (size_t i = 0; i < arraysize(resolutions); ++i) {
+ SCOPED_TRACE(resolutions[i]);
+
+ // Make a RasterSource that will draw a blue bitmap image.
+ skia::RefPtr<SkSurface> surface = skia::AdoptRef(
+ SkSurface::NewRasterN32Premul(size.width(), size.height()));
+ ASSERT_NE(surface, nullptr);
+ surface->getCanvas()->clear(SK_ColorBLUE);
+ skia::RefPtr<SkImage> blue_image =
+ skia::AdoptRef(surface->newImageSnapshot());
+
+ scoped_ptr<FakeDisplayListRecordingSource> recording_source =
+ FakeDisplayListRecordingSource::CreateFilledRecordingSource(size);
+ recording_source->SetBackgroundColor(SK_ColorTRANSPARENT);
+ recording_source->SetRequiresClear(true);
+ recording_source->SetClearCanvasWithDebugColor(false);
+ SkPaint paint;
+ paint.setColor(SK_ColorGREEN);
+ recording_source->add_draw_rect_with_paint(gfx::Rect(size), paint);
+ recording_source->add_draw_image(blue_image.get(), gfx::Point());
+ recording_source->Rerecord();
+ scoped_refptr<DisplayListRasterSource> raster =
+ DisplayListRasterSource::CreateFromDisplayListRecordingSource(
+ recording_source.get(), false);
+
+ FakePictureLayerTilingClient tiling_client;
+ tiling_client.SetTileSize(size);
+
+ scoped_ptr<PictureLayerImpl> layer =
+ PictureLayerImpl::Create(host_impl_->active_tree(), 1, false, nullptr);
+ PictureLayerTilingSet* tiling_set = layer->picture_layer_tiling_set();
+
+ auto* tiling = tiling_set->AddTiling(1.0f, raster);
+ tiling->set_resolution(resolutions[i]);
+ tiling->CreateAllTilesForTesting();
+ tiling->SetTilePriorityRectsForTesting(
+ gfx::Rect(size), // Visible rect.
+ gfx::Rect(size), // Skewport rect.
+ gfx::Rect(size), // Soon rect.
+ gfx::Rect(size)); // Eventually rect.
+
+ // SMOOTHNESS_TAKES_PRIORITY ensures that we will actually raster
+ // LOW_RESOLUTION tiles, otherwise they are skipped.
+ host_impl_->SetTreePriority(SMOOTHNESS_TAKES_PRIORITY);
+
+ // Call PrepareTiles and wait for it to complete.
+ auto* tile_manager = host_impl_->tile_manager();
+ base::RunLoop run_loop;
+ EXPECT_CALL(*host_impl_, NotifyAllTileTasksCompleted())
.WillOnce(testing::Invoke([&run_loop]() { run_loop.Quit(); }));
- host_impl_.tile_manager()->PrepareTiles(host_impl_.global_tile_state());
- host_impl_.tile_manager()->SetMoreTilesNeedToBeRasterizedForTesting();
- EXPECT_TRUE(host_impl_.tile_manager()->HasScheduledTileTasksForTesting());
+ tile_manager->PrepareTiles(host_impl_->global_tile_state());
run_loop.Run();
+ tile_manager->Flush();
+
+ Tile* tile = tiling->TileAt(0, 0);
+ // The tile in the tiling was rastered.
+ EXPECT_EQ(TileDrawInfo::RESOURCE_MODE, tile->draw_info().mode());
+ EXPECT_TRUE(tile->draw_info().IsReadyToDraw());
+
+ ResourceProvider::ScopedReadLockSoftware lock(
+ host_impl_->resource_provider(), tile->draw_info().resource_id());
+ const SkBitmap* bitmap = lock.sk_bitmap();
+ for (int x = 0; x < size.width(); ++x) {
+ for (int y = 0; y < size.height(); ++y) {
+ SCOPED_TRACE(y);
+ SCOPED_TRACE(x);
+ if (resolutions[i] == LOW_RESOLUTION) {
+ // Since it's low res, the bitmap was not drawn, and the background
+ // (green) is visible instead.
+ ASSERT_EQ(SK_ColorGREEN, bitmap->getColor(x, y));
+ } else {
+ EXPECT_EQ(HIGH_RESOLUTION, resolutions[i]);
+ // Since it's high res, the bitmap (blue) was drawn, and the
+ // background is not visible.
+ ASSERT_EQ(SK_ColorBLUE, bitmap->getColor(x, y));
+ }
+ }
+ }
}
}
+// Fake TileTaskRunner that just cancels all scheduled tasks immediately.
+class CancellingTileTaskRunner : public TileTaskRunner, public TileTaskClient {
+ public:
+ CancellingTileTaskRunner() {}
+
+ // TileTaskRunner methods.
+ void SetClient(TileTaskRunnerClient* client) override {}
+ void Shutdown() override {}
+ void CheckForCompletedTasks() override {}
+ ResourceFormat GetResourceFormat(bool must_support_alpha) const override {
+ return ResourceFormat::RGBA_8888;
+ }
+ bool GetResourceRequiresSwizzle(bool must_support_alpha) const override {
+ return false;
+ }
+
+ void ScheduleTasks(TileTaskQueue* queue) override {
+ // Just call CompleteOnOriginThread on each item in the queue. As none of
+ // these items have run yet, they will be treated as cancelled tasks.
+ for (const auto& task : queue->items) {
+ task.task->CompleteOnOriginThread(this);
+ }
+ }
+
+ // TileTaskClient methods.
+ scoped_ptr<RasterBuffer> AcquireBufferForRaster(
+ const Resource* resource,
+ uint64_t resource_content_id,
+ uint64_t previous_content_id) override {
+ NOTREACHED();
+ return nullptr;
+ }
+ void ReleaseBufferForRaster(scoped_ptr<RasterBuffer> buffer) override {}
+
+ ~CancellingTileTaskRunner() override {}
+};
+
+// Ensures that if a raster task is cancelled, it gets returned to the resource
+// pool with an invalid content ID, not with its invalidated content ID.
+TEST_F(TileManagerTest, CancelledTasksHaveNoContentId) {
+ // Create a CancellingTaskRunner and set it on the tile manager so that all
+ // scheduled work is immediately cancelled.
+ CancellingTileTaskRunner cancelling_runner;
+ host_impl_->tile_manager()->SetTileTaskRunnerForTesting(&cancelling_runner);
+
+ // Pick arbitrary IDs - they don't really matter as long as they're constant.
+ int layer_id = 7;
+ int invalidated_id = 43;
+
+ scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+ FakeDisplayListRasterSource::CreateFilled(gfx::Size(128, 128));
+ host_impl_->CreatePendingTree();
+ LayerTreeImpl* pending_tree = host_impl_->pending_tree();
+
+ // Steal from the recycled tree.
+ scoped_ptr<FakePictureLayerImpl> pending_layer =
+ FakePictureLayerImpl::CreateWithRasterSource(pending_tree, layer_id,
+ pending_raster_source);
+ pending_layer->SetDrawsContent(true);
+ pending_layer->SetHasRenderSurface(true);
+
+ // The bounds() just mirror the raster source size.
+ pending_layer->SetBounds(pending_layer->raster_source()->GetSize());
+ pending_tree->SetRootLayer(pending_layer.Pass());
+
+ // Add tilings/tiles for the layer.
+ host_impl_->pending_tree()->UpdateDrawProperties(false /* update_lcd_text */);
+
+ // Build the raster queue and invalidate the top tile.
+ scoped_ptr<RasterTilePriorityQueue> queue(host_impl_->BuildRasterQueue(
+ SAME_PRIORITY_FOR_BOTH_TREES, RasterTilePriorityQueue::Type::ALL));
+ EXPECT_FALSE(queue->IsEmpty());
+ queue->Top().tile()->SetInvalidated(gfx::Rect(), invalidated_id);
+
+ // PrepareTiles to schedule tasks. Due to the CancellingTileTaskRunner, these
+ // tasks will immediately be canceled.
+ host_impl_->tile_manager()->PrepareTiles(host_impl_->global_tile_state());
+
+ // Make sure that the tile we invalidated above was not returned to the pool
+ // with its invalidated resource ID.
+ host_impl_->resource_pool()->CheckBusyResources();
+ EXPECT_FALSE(host_impl_->resource_pool()->TryAcquireResourceWithContentId(
+ invalidated_id));
+
+ // Free our host_impl_ before the cancelling_runner we passed it, as it will
+ // use that class in clean up.
+ host_impl_ = nullptr;
+}
+
} // namespace
} // namespace cc
diff --git a/chromium/cc/trees/channel_impl.h b/chromium/cc/trees/channel_impl.h
new file mode 100644
index 00000000000..dcaf41687af
--- /dev/null
+++ b/chromium/cc/trees/channel_impl.h
@@ -0,0 +1,27 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_TREES_CHANNEL_IMPL_H_
+#define CC_TREES_CHANNEL_IMPL_H_
+
+#include "cc/base/cc_export.h"
+
+namespace cc {
+
+// Channel used to send commands to and receive commands from ProxyMain.
+// The ChannelImpl implementation creates and owns ProxyImpl on receiving the
+// InitializeImpl call from ChannelMain.
+// See channel_main.h
+class CC_EXPORT ChannelImpl {
+ public:
+ // Interface for commands sent to ProxyMain
+ virtual void DidCompleteSwapBuffers() = 0;
+
+ protected:
+ virtual ~ChannelImpl() {}
+};
+
+} // namespace cc
+
+#endif // CC_TREES_CHANNEL_IMPL_H_
diff --git a/chromium/cc/trees/channel_main.h b/chromium/cc/trees/channel_main.h
new file mode 100644
index 00000000000..964d1aa5db9
--- /dev/null
+++ b/chromium/cc/trees/channel_main.h
@@ -0,0 +1,33 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_TREES_CHANNEL_MAIN_H_
+#define CC_TREES_CHANNEL_MAIN_H_
+
+#include "cc/base/cc_export.h"
+
+namespace cc {
+
+// ChannelMain and ChannelImpl provide an abstract communication layer for
+// the main and impl side of the compositor.
+//
+// The communication sequence between the 2 sides is:
+//
+// LayerTreeHost<-->ProxyMain<-->ChannelMain
+// |
+// |
+// ChannelImpl<-->ProxyImpl<-->LayerTreeHostImpl
+
+class CC_EXPORT ChannelMain {
+ public:
+ // Interface for commands sent to the ProxyImpl
+ virtual void SetThrottleFrameProductionOnImpl(bool throttle) = 0;
+ virtual void SetLayerTreeHostClientReadyOnImpl() = 0;
+
+ virtual ~ChannelMain() {}
+};
+
+} // namespace cc
+
+#endif // CC_TREES_CHANNEL_MAIN_H_
diff --git a/chromium/cc/trees/damage_tracker.cc b/chromium/cc/trees/damage_tracker.cc
index de11b47c1a9..65d3fd32172 100644
--- a/chromium/cc/trees/damage_tracker.cc
+++ b/chromium/cc/trees/damage_tracker.cc
@@ -142,13 +142,7 @@ void DamageTracker::UpdateDamageTrackingState(
damage_rect_for_this_update.Union(damage_from_surface_mask);
damage_rect_for_this_update.Union(damage_from_leftover_rects);
- if (filters.HasReferenceFilter()) {
- // TODO(senorblanco): Once SkImageFilter reports its outsets, use
- // those here to limit damage.
- damage_rect_for_this_update = target_surface_content_rect;
- } else if (filters.HasFilterThatMovesPixels()) {
- ExpandRectWithFilters(&damage_rect_for_this_update, filters);
- }
+ ExpandRectWithFilters(&damage_rect_for_this_update, filters);
}
// Damage accumulates until we are notified that we actually did draw on that
@@ -286,10 +280,6 @@ void DamageTracker::ExtendDamageForLayer(LayerImpl* layer,
gfx::Rect rect_in_target_space = layer->GetEnclosingRectInTargetSpace();
data.Update(rect_in_target_space, mailboxId_);
- gfx::RectF damage_rect =
- gfx::UnionRects(layer->update_rect(), layer->damage_rect());
- damage_rect.Intersect(gfx::RectF(layer->bounds()));
-
if (layer_is_new || layer->LayerPropertyChanged()) {
// If a layer is new or has changed, then its entire layer rect affects the
// target surface.
@@ -298,11 +288,17 @@ void DamageTracker::ExtendDamageForLayer(LayerImpl* layer,
// The layer's old region is now exposed on the target surface, too.
// Note old_rect_in_target_space is already in target space.
target_damage_rect->Union(old_rect_in_target_space);
- } else if (!damage_rect.IsEmpty()) {
- // If the layer properties haven't changed, then the the target surface is
- // only affected by the layer's damaged area, which could be empty.
- gfx::Rect damage_rect_in_target_space = gfx::ToEnclosingRect(
- MathUtil::MapClippedRect(layer->draw_transform(), damage_rect));
+ return;
+ }
+
+ // If the layer properties haven't changed, then the the target surface is
+ // only affected by the layer's damaged area, which could be empty.
+ gfx::Rect damage_rect =
+ gfx::UnionRects(layer->update_rect(), layer->damage_rect());
+ damage_rect.Intersect(gfx::Rect(layer->bounds()));
+ if (!damage_rect.IsEmpty()) {
+ gfx::Rect damage_rect_in_target_space =
+ MathUtil::MapEnclosingClippedRect(layer->draw_transform(), damage_rect);
target_damage_rect->Union(damage_rect_in_target_space);
}
}
diff --git a/chromium/cc/trees/damage_tracker_unittest.cc b/chromium/cc/trees/damage_tracker_unittest.cc
index 831b1f718ec..9935e8603fd 100644
--- a/chromium/cc/trees/damage_tracker_unittest.cc
+++ b/chromium/cc/trees/damage_tracker_unittest.cc
@@ -266,7 +266,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForLayerDamageRects) {
// CASE 1: Adding the layer damage rect should cause the corresponding damage
// to the surface.
ClearDamageForAllSurfaces(root.get());
- child->AddDamageRect(gfx::RectF(10.f, 11.f, 12.f, 13.f));
+ child->AddDamageRect(gfx::Rect(10, 11, 12, 13));
EmulateDrawingOneFrame(root.get());
// Damage position on the surface should be: position of layer damage_rect
@@ -278,7 +278,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForLayerDamageRects) {
// CASE 2: The same layer damage rect twice in a row still produces the same
// damage.
ClearDamageForAllSurfaces(root.get());
- child->AddDamageRect(gfx::RectF(10.f, 11.f, 12.f, 13.f));
+ child->AddDamageRect(gfx::Rect(10, 11, 12, 13));
EmulateDrawingOneFrame(root.get());
root_damage_rect =
root->render_surface()->damage_tracker()->current_damage_rect();
@@ -287,7 +287,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForLayerDamageRects) {
// CASE 3: Adding a different layer damage rect should cause damage on the
// new damaged region, but no additional exposed old region.
ClearDamageForAllSurfaces(root.get());
- child->AddDamageRect(gfx::RectF(20.f, 25.f, 1.f, 2.f));
+ child->AddDamageRect(gfx::Rect(20, 25, 1, 2));
EmulateDrawingOneFrame(root.get());
// Damage position on the surface should be: position of layer damage_rect
@@ -299,8 +299,8 @@ TEST_F(DamageTrackerTest, VerifyDamageForLayerDamageRects) {
// CASE 4: Adding multiple layer damage rects should cause a unified
// damage on root damage rect.
ClearDamageForAllSurfaces(root.get());
- child->AddDamageRect(gfx::RectF(20.f, 25.f, 1.f, 2.f));
- child->AddDamageRect(gfx::RectF(10.f, 15.f, 3.f, 4.f));
+ child->AddDamageRect(gfx::Rect(20, 25, 1, 2));
+ child->AddDamageRect(gfx::Rect(10, 15, 3, 4));
EmulateDrawingOneFrame(root.get());
// Damage position on the surface should be: position of layer damage_rect
@@ -318,7 +318,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForLayerUpdateAndDamageRects) {
// CASE 1: Adding the layer damage rect and update rect should cause the
// corresponding damage to the surface.
ClearDamageForAllSurfaces(root.get());
- child->AddDamageRect(gfx::RectF(5.f, 6.f, 12.f, 13.f));
+ child->AddDamageRect(gfx::Rect(5, 6, 12, 13));
child->SetUpdateRect(gfx::Rect(15, 16, 14, 10));
EmulateDrawingOneFrame(root.get());
@@ -332,7 +332,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForLayerUpdateAndDamageRects) {
// CASE 2: The same layer damage rect and update rect twice in a row still
// produces the same damage.
ClearDamageForAllSurfaces(root.get());
- child->AddDamageRect(gfx::RectF(10.f, 11.f, 12.f, 13.f));
+ child->AddDamageRect(gfx::Rect(10, 11, 12, 13));
child->SetUpdateRect(gfx::Rect(10, 11, 14, 15));
EmulateDrawingOneFrame(root.get());
root_damage_rect =
@@ -342,7 +342,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForLayerUpdateAndDamageRects) {
// CASE 3: Adding a different layer damage rect and update rect should cause
// damage on the new damaged region, but no additional exposed old region.
ClearDamageForAllSurfaces(root.get());
- child->AddDamageRect(gfx::RectF(20.f, 25.f, 2.f, 3.f));
+ child->AddDamageRect(gfx::Rect(20, 25, 2, 3));
child->SetUpdateRect(gfx::Rect(5, 10, 7, 8));
EmulateDrawingOneFrame(root.get());
@@ -535,6 +535,8 @@ TEST_F(DamageTrackerTest, VerifyDamageForImageFilter) {
SkBlurImageFilter::Create(SkIntToScalar(2), SkIntToScalar(2)));
FilterOperations filters;
filters.Append(FilterOperation::CreateReferenceFilter(filter));
+ int outset_top, outset_right, outset_bottom, outset_left;
+ filters.GetOutsets(&outset_top, &outset_right, &outset_bottom, &outset_left);
// Setting the filter will damage the whole surface.
ClearDamageForAllSurfaces(root.get());
@@ -547,7 +549,11 @@ TEST_F(DamageTrackerTest, VerifyDamageForImageFilter) {
child->render_surface()->damage_tracker()->current_damage_rect();
EXPECT_EQ(gfx::Rect(100, 100, 30, 30).ToString(),
root_damage_rect.ToString());
- EXPECT_EQ(gfx::Rect(30, 30).ToString(), child_damage_rect.ToString());
+ EXPECT_EQ(
+ gfx::Rect(-outset_left, -outset_top, 30 + (outset_left + outset_right),
+ 30 + (outset_top + outset_bottom))
+ .ToString(),
+ child_damage_rect.ToString());
// CASE 1: Setting the update rect should damage the whole surface (for now)
ClearDamageForAllSurfaces(root.get());
@@ -558,9 +564,16 @@ TEST_F(DamageTrackerTest, VerifyDamageForImageFilter) {
root->render_surface()->damage_tracker()->current_damage_rect();
child_damage_rect =
child->render_surface()->damage_tracker()->current_damage_rect();
- EXPECT_EQ(gfx::Rect(100, 100, 30, 30).ToString(),
+
+ int expect_width = 1 + outset_left + outset_right;
+ int expect_height = 1 + outset_top + outset_bottom;
+ EXPECT_EQ(gfx::Rect(100 - outset_left, 100 - outset_top, expect_width,
+ expect_height)
+ .ToString(),
root_damage_rect.ToString());
- EXPECT_EQ(gfx::Rect(30.f, 30.f).ToString(), child_damage_rect.ToString());
+ EXPECT_EQ(gfx::Rect(-outset_left, -outset_top, expect_width, expect_height)
+ .ToString(),
+ child_damage_rect.ToString());
}
TEST_F(DamageTrackerTest, VerifyDamageForBackgroundBlurredChild) {
diff --git a/chromium/cc/trees/draw_property_utils.cc b/chromium/cc/trees/draw_property_utils.cc
index 9f63421ed94..9975fad8b21 100644
--- a/chromium/cc/trees/draw_property_utils.cc
+++ b/chromium/cc/trees/draw_property_utils.cc
@@ -7,8 +7,10 @@
#include <vector>
#include "cc/base/math_util.h"
+#include "cc/layers/draw_properties.h"
#include "cc/layers/layer.h"
#include "cc/layers/layer_impl.h"
+#include "cc/layers/render_surface_draw_properties.h"
#include "cc/trees/layer_tree_impl.h"
#include "cc/trees/property_tree.h"
#include "cc/trees/property_tree_builder.h"
@@ -33,63 +35,73 @@ void CalculateVisibleRects(const std::vector<LayerType*>& visible_layer_list,
transform_tree.Node(layer->transform_tree_index());
if (has_clip) {
const ClipNode* clip_node = clip_tree.Node(layer->clip_tree_index());
- const TransformNode* clip_transform_node =
- transform_tree.Node(clip_node->data.transform_id);
- const bool target_is_root_surface =
- transform_node->data.content_target_id == 1;
- // When the target is the root surface, we need to include the root
- // transform by walking up to the root of the transform tree.
- const int target_id =
- target_is_root_surface ? 0 : transform_node->data.content_target_id;
- const TransformNode* target_node = transform_tree.Node(target_id);
-
- gfx::Transform content_to_target = transform_node->data.to_target;
-
- content_to_target.Translate(layer->offset_to_transform_parent().x(),
- layer->offset_to_transform_parent().y());
+ const TransformNode* target_node =
+ transform_tree.Node(transform_node->data.content_target_id);
+ // The clip node stores clip rect in its target space. If required,
+ // this clip rect should be mapped to the current layer's target space.
gfx::Rect clip_rect_in_target_space;
- gfx::Transform clip_to_target;
+ gfx::Rect combined_clip_rect_in_target_space;
bool success = true;
- if (clip_transform_node->data.target_id == target_node->id) {
- clip_to_target = clip_transform_node->data.to_target;
- } else {
+ if (clip_node->data.target_id != target_node->id) {
+ gfx::Transform clip_to_target;
success = transform_tree.ComputeTransformWithDestinationSublayerScale(
- clip_transform_node->id, target_node->id, &clip_to_target);
- }
-
- if (target_node->id > clip_node->data.transform_id) {
+ clip_node->data.target_id, target_node->id, &clip_to_target);
if (!success) {
- DCHECK(target_node->data.to_screen_is_animated);
-
// An animated singular transform may become non-singular during the
// animation, so we still need to compute a visible rect. In this
// situation, we treat the entire layer as visible.
layer->set_visible_rect_from_property_trees(gfx::Rect(layer_bounds));
+ layer->set_clip_rect_in_target_space_from_property_trees(gfx::Rect());
continue;
}
-
+ DCHECK_LT(clip_node->data.target_id, target_node->id);
+ combined_clip_rect_in_target_space =
+ gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
+ clip_to_target, clip_node->data.combined_clip_in_target_space));
clip_rect_in_target_space =
gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
- clip_to_target, clip_node->data.combined_clip));
+ clip_to_target, clip_node->data.clip_in_target_space));
} else {
- // Computing a transform to an ancestor should always succeed.
- DCHECK(success);
clip_rect_in_target_space =
- gfx::ToEnclosingRect(MathUtil::MapClippedRect(
- clip_to_target, clip_node->data.combined_clip));
+ gfx::ToEnclosingRect(clip_node->data.clip_in_target_space);
+ combined_clip_rect_in_target_space =
+ gfx::ToEnclosingRect(clip_node->data.combined_clip_in_target_space);
}
+ if (!clip_rect_in_target_space.IsEmpty()) {
+ layer->set_clip_rect_in_target_space_from_property_trees(
+ clip_rect_in_target_space);
+ } else {
+ layer->set_clip_rect_in_target_space_from_property_trees(gfx::Rect());
+ }
+
+ // The clip rect should be intersected with layer rect in target space.
+ gfx::Transform content_to_target = transform_node->data.to_target;
+
+ content_to_target.Translate(layer->offset_to_transform_parent().x(),
+ layer->offset_to_transform_parent().y());
gfx::Rect layer_content_rect = gfx::Rect(layer_bounds);
gfx::Rect layer_content_bounds_in_target_space =
MathUtil::MapEnclosingClippedRect(content_to_target,
layer_content_rect);
- clip_rect_in_target_space.Intersect(layer_content_bounds_in_target_space);
- if (clip_rect_in_target_space.IsEmpty()) {
+ combined_clip_rect_in_target_space.Intersect(
+ layer_content_bounds_in_target_space);
+ if (combined_clip_rect_in_target_space.IsEmpty()) {
layer->set_visible_rect_from_property_trees(gfx::Rect());
continue;
}
+ // If the layer is fully contained within the clip, treat it as fully
+ // visible. Since clip_rect_in_target_space has already been intersected
+ // with layer_content_bounds_in_target_space, the layer is fully contained
+ // within the clip iff these rects are equal.
+ if (combined_clip_rect_in_target_space ==
+ layer_content_bounds_in_target_space) {
+ layer->set_visible_rect_from_property_trees(gfx::Rect(layer_bounds));
+ continue;
+ }
+
gfx::Transform target_to_content;
gfx::Transform target_to_layer;
@@ -102,8 +114,6 @@ void CalculateVisibleRects(const std::vector<LayerType*>& visible_layer_list,
}
if (!success) {
- DCHECK(transform_node->data.to_screen_is_animated);
-
// An animated singular transform may become non-singular during the
// animation, so we still need to compute a visible rect. In this
// situation, we treat the entire layer as visible.
@@ -116,13 +126,15 @@ void CalculateVisibleRects(const std::vector<LayerType*>& visible_layer_list,
target_to_content.PreconcatTransform(target_to_layer);
gfx::Rect visible_rect = MathUtil::ProjectEnclosingClippedRect(
- target_to_content, clip_rect_in_target_space);
+ target_to_content, combined_clip_rect_in_target_space);
visible_rect.Intersect(gfx::Rect(layer_bounds));
layer->set_visible_rect_from_property_trees(visible_rect);
} else {
layer->set_visible_rect_from_property_trees(gfx::Rect(layer_bounds));
+ layer->set_clip_rect_in_target_space_from_property_trees(
+ gfx::Rect(layer_bounds));
}
}
}
@@ -137,7 +149,8 @@ static bool IsRootLayerOfNewRenderingContext(LayerType* layer) {
template <typename LayerType>
static inline bool LayerIsInExisting3DRenderingContext(LayerType* layer) {
return layer->Is3dSorted() && layer->parent() &&
- layer->parent()->Is3dSorted();
+ layer->parent()->Is3dSorted() &&
+ layer->parent()->sorting_context_id() == layer->sorting_context_id();
}
template <typename LayerType>
@@ -170,6 +183,28 @@ static bool IsLayerBackFaceVisible(LayerType* layer,
}
template <typename LayerType>
+static bool IsSurfaceBackFaceVisible(LayerType* layer,
+ const TransformTree& tree) {
+ if (LayerIsInExisting3DRenderingContext(layer)) {
+ const TransformNode* node = tree.Node(layer->transform_tree_index());
+ // Draw transform as a contributing render surface.
+ // TODO(enne): we shouldn't walk the tree during a tree walk.
+ gfx::Transform surface_draw_transform;
+ tree.ComputeTransform(node->id, node->data.target_id,
+ &surface_draw_transform);
+ return surface_draw_transform.IsBackFaceVisible();
+ }
+
+ if (IsRootLayerOfNewRenderingContext(layer))
+ return layer->transform().IsBackFaceVisible();
+
+ // If the render_surface is not part of a new or existing rendering context,
+ // then the layers that contribute to this surface will decide back-face
+ // visibility for themselves.
+ return false;
+}
+
+template <typename LayerType>
static bool IsAnimatingTransformToScreen(LayerType* layer,
const TransformTree& tree) {
const TransformNode* node = tree.Node(layer->transform_tree_index());
@@ -188,11 +223,13 @@ static inline bool TransformToScreenIsKnown(LayerImpl* layer,
template <typename LayerType>
static bool HasInvertibleOrAnimatedTransform(LayerType* layer) {
- return layer->transform_is_invertible() || layer->TransformIsAnimating();
+ return layer->transform_is_invertible() ||
+ layer->HasPotentiallyRunningTransformAnimation();
}
static inline bool SubtreeShouldBeSkipped(LayerImpl* layer,
- bool layer_is_drawn) {
+ bool layer_is_drawn,
+ const TransformTree& tree) {
// If the layer transform is not invertible, it should not be drawn.
// TODO(ajuma): Correctly process subtrees with singular transform for the
// case where we may animate to a non-singular transform and wish to
@@ -202,22 +239,36 @@ static inline bool SubtreeShouldBeSkipped(LayerImpl* layer,
// When we need to do a readback/copy of a layer's output, we can not skip
// it or any of its ancestors.
- if (layer->draw_properties().layer_or_descendant_has_copy_request)
+ if (layer->num_layer_or_descendants_with_copy_request() > 0)
return false;
// We cannot skip the the subtree if a descendant has a wheel or touch handler
// or the hit testing code will break (it requires fresh transforms, etc).
- if (layer->draw_properties().layer_or_descendant_has_input_handler)
+ // Though we don't need visible rect for hit testing, we need render surface's
+ // drawable content rect which depends on layer's drawable content rect which
+ // in turn depends on layer's clip rect that is computed while computing
+ // visible rects.
+ if (layer->layer_or_descendant_has_input_handler())
return false;
// If the layer is not drawn, then skip it and its subtree.
if (!layer_is_drawn)
return true;
+ if (layer->render_surface() && !layer->double_sided() &&
+ IsSurfaceBackFaceVisible(layer, tree))
+ return true;
+
// If layer is on the pending tree and opacity is being animated then
// this subtree can't be skipped as we need to create, prioritize and
// include tiles for this layer when deciding if tree can be activated.
- if (layer->layer_tree_impl()->IsPendingTree() && layer->OpacityIsAnimating())
+ if (layer->layer_tree_impl()->IsPendingTree() &&
+ layer->HasPotentiallyRunningOpacityAnimation())
+ return false;
+
+ // If layer has a background filter, don't skip the layer, even it the
+ // opacity is 0.
+ if (!layer->background_filters().IsEmpty())
return false;
// The opacity of a layer always applies to its children (either implicitly
@@ -226,32 +277,40 @@ static inline bool SubtreeShouldBeSkipped(LayerImpl* layer,
return !layer->opacity();
}
-static inline bool SubtreeShouldBeSkipped(Layer* layer, bool layer_is_drawn) {
+static inline bool SubtreeShouldBeSkipped(Layer* layer,
+ bool layer_is_drawn,
+ const TransformTree& tree) {
// If the layer transform is not invertible, it should not be drawn.
- if (!layer->transform_is_invertible() && !layer->TransformIsAnimating())
+ if (!layer->transform_is_invertible() &&
+ !layer->HasPotentiallyRunningTransformAnimation())
return true;
// When we need to do a readback/copy of a layer's output, we can not skip
// it or any of its ancestors.
- if (layer->draw_properties().layer_or_descendant_has_copy_request)
- return false;
-
- // We cannot skip the the subtree if a descendant has a wheel or touch handler
- // or the hit testing code will break (it requires fresh transforms, etc).
- if (layer->draw_properties().layer_or_descendant_has_input_handler)
+ if (layer->num_layer_or_descendants_with_copy_request() > 0)
return false;
// If the layer is not drawn, then skip it and its subtree.
if (!layer_is_drawn)
return true;
+ if (layer->has_render_surface() && !layer->double_sided() &&
+ !layer->HasPotentiallyRunningTransformAnimation() &&
+ IsSurfaceBackFaceVisible(layer, tree))
+ return true;
+
+ // If layer has a background filter, don't skip the layer, even it the
+ // opacity is 0.
+ if (!layer->background_filters().IsEmpty())
+ return false;
+
// If the opacity is being animated then the opacity on the main thread is
// unreliable (since the impl thread may be using a different opacity), so it
// should not be trusted.
// In particular, it should not cause the subtree to be skipped.
// Similarly, for layers that might animate opacity using an impl-only
// animation, their subtree should also not be skipped.
- return !layer->opacity() && !layer->OpacityIsAnimating() &&
+ return !layer->opacity() && !layer->HasPotentiallyRunningOpacityAnimation() &&
!layer->OpacityCanAnimateOnImplThread();
}
@@ -309,7 +368,7 @@ void FindLayersThatNeedUpdates(
layer->HasCopyRequest() ||
(subtree_is_visible_from_ancestor && !layer->hide_layer_and_subtree());
- if (layer->parent() && SubtreeShouldBeSkipped(layer, layer_is_drawn))
+ if (layer->parent() && SubtreeShouldBeSkipped(layer, layer_is_drawn, tree))
return;
if (!LayerShouldBeSkipped(layer, layer_is_drawn, tree)) {
@@ -341,19 +400,30 @@ void ComputeClips(ClipTree* clip_tree, const TransformTree& transform_tree) {
for (int i = 0; i < static_cast<int>(clip_tree->size()); ++i) {
ClipNode* clip_node = clip_tree->Node(i);
+ if (clip_node->id == 0) {
+ clip_node->data.combined_clip_in_target_space = clip_node->data.clip;
+ clip_node->data.clip_in_target_space = clip_node->data.clip;
+ continue;
+ }
+ const TransformNode* transform_node =
+ transform_tree.Node(clip_node->data.transform_id);
+
// Only descendants of a real clipping layer (i.e., not 0) may have their
// clip adjusted due to intersecting with an ancestor clip.
const bool is_clipped = clip_node->parent_id > 0;
if (!is_clipped) {
- clip_node->data.combined_clip = clip_node->data.clip;
+ clip_node->data.clip_in_target_space = MathUtil::MapClippedRect(
+ transform_node->data.to_target, clip_node->data.clip);
+ clip_node->data.combined_clip_in_target_space =
+ clip_node->data.clip_in_target_space;
continue;
}
ClipNode* parent_clip_node = clip_tree->parent(clip_node);
+ gfx::Transform parent_to_current;
const TransformNode* parent_transform_node =
transform_tree.Node(parent_clip_node->data.transform_id);
- const TransformNode* transform_node =
- transform_tree.Node(clip_node->data.transform_id);
+ bool success = true;
// Clips must be combined in target space. We cannot, for example, combine
// clips in the space of the child clip. The reason is non-affine
@@ -362,62 +432,75 @@ void ComputeClips(ClipTree* clip_tree, const TransformTree& transform_tree) {
// transform, and B and C are at different z positions. When projected into
// target space, the relative sizes and positions of B and C can shift.
// Since it's the relationship in target space that matters, that's where we
- // must combine clips.
- gfx::Transform parent_to_target;
- gfx::Transform clip_to_target;
- gfx::Transform target_to_clip;
-
- const bool target_is_root_surface = clip_node->data.target_id == 1;
- // When the target is the root surface, we need to include the root
- // transform by walking up to the root of the transform tree.
- const int target_id =
- target_is_root_surface ? 0 : clip_node->data.target_id;
-
- bool success = true;
- if (parent_transform_node->data.content_target_id ==
- clip_node->data.target_id) {
- parent_to_target = parent_transform_node->data.to_target;
- } else {
+ // must combine clips. For each clip node, we save the clip rects in its
+ // target space. So, we need to get the ancestor clip rect in the current
+ // clip node's target space.
+ gfx::RectF parent_combined_clip_in_target_space =
+ parent_clip_node->data.combined_clip_in_target_space;
+ if (parent_clip_node->data.target_id != clip_node->data.target_id) {
success &= transform_tree.ComputeTransformWithDestinationSublayerScale(
- parent_transform_node->id, target_id, &parent_to_target);
- }
-
- if (transform_node->data.content_target_id == clip_node->data.target_id) {
- clip_to_target = transform_node->data.to_target;
- } else {
- success &= transform_tree.ComputeTransformWithDestinationSublayerScale(
- transform_node->id, target_id, &clip_to_target);
+ parent_clip_node->data.target_id, clip_node->data.target_id,
+ &parent_to_current);
+ if (parent_transform_node->data.sublayer_scale.x() > 0 &&
+ parent_transform_node->data.sublayer_scale.y() > 0)
+ parent_to_current.Scale(
+ 1.f / parent_transform_node->data.sublayer_scale.x(),
+ 1.f / parent_transform_node->data.sublayer_scale.y());
+ // If we can't compute a transform, it's because we had to use the inverse
+ // of a singular transform. We won't draw in this case, so there's no need
+ // to compute clips.
+ if (!success)
+ continue;
+ parent_combined_clip_in_target_space = MathUtil::ProjectClippedRect(
+ parent_to_current,
+ parent_clip_node->data.combined_clip_in_target_space);
}
- if (transform_node->data.content_target_id == clip_node->data.target_id &&
- transform_node->data.ancestors_are_invertible) {
- target_to_clip = transform_node->data.from_target;
+ if (clip_node->data.use_only_parent_clip) {
+ clip_node->data.combined_clip_in_target_space =
+ parent_combined_clip_in_target_space;
+ if (!clip_node->data.render_surface_is_clipped) {
+ clip_node->data.clip_in_target_space =
+ parent_combined_clip_in_target_space;
+ } else {
+ // Render Surface applies clip and the owning layer itself applies
+ // no clip. So, clip_in_target_space is not used and hence we can set
+ // it to an empty rect.
+ clip_node->data.clip_in_target_space = gfx::RectF();
+ }
} else {
- success &= clip_to_target.GetInverse(&target_to_clip);
- }
-
- // If we can't compute a transform, it's because we had to use the inverse
- // of a singular transform. We won't draw in this case, so there's no need
- // to compute clips.
- if (!success)
- continue;
+ gfx::Transform source_to_target;
- // In order to intersect with as small a rect as possible, we do a
- // preliminary clip in target space so that when we project back, there's
- // less likelihood of intersecting the view plane.
- gfx::RectF inherited_clip_in_target_space = MathUtil::MapClippedRect(
- parent_to_target, parent_clip_node->data.combined_clip);
-
- gfx::RectF clip_in_target_space =
- MathUtil::MapClippedRect(clip_to_target, clip_node->data.clip);
+ if (transform_node->data.content_target_id == clip_node->data.target_id) {
+ source_to_target = transform_node->data.to_target;
+ } else {
+ success = transform_tree.ComputeTransformWithDestinationSublayerScale(
+ transform_node->id, clip_node->data.target_id, &source_to_target);
+ // source_to_target computation should be successful as target is an
+ // ancestor of the transform node.
+ DCHECK(success);
+ }
- gfx::RectF intersected_in_target_space = gfx::IntersectRects(
- inherited_clip_in_target_space, clip_in_target_space);
+ gfx::RectF source_clip_in_target_space =
+ MathUtil::MapClippedRect(source_to_target, clip_node->data.clip);
- clip_node->data.combined_clip = MathUtil::ProjectClippedRect(
- target_to_clip, intersected_in_target_space);
+ if (!clip_node->data.layer_clipping_uses_only_local_clip) {
+ gfx::RectF parent_clip_in_target_space = MathUtil::ProjectClippedRect(
+ parent_to_current, parent_clip_node->data.clip_in_target_space);
+ clip_node->data.clip_in_target_space = gfx::IntersectRects(
+ parent_clip_in_target_space, source_clip_in_target_space);
+ } else {
+ clip_node->data.clip_in_target_space = source_clip_in_target_space;
+ }
- clip_node->data.combined_clip.Intersect(clip_node->data.clip);
+ if (clip_node->data.layer_visibility_uses_only_local_clip) {
+ clip_node->data.combined_clip_in_target_space =
+ source_clip_in_target_space;
+ } else {
+ clip_node->data.combined_clip_in_target_space = gfx::IntersectRects(
+ parent_combined_clip_in_target_space, source_clip_in_target_space);
+ }
+ }
}
clip_tree->set_needs_update(false);
}
@@ -430,12 +513,12 @@ void ComputeTransforms(TransformTree* transform_tree) {
transform_tree->set_needs_update(false);
}
-void ComputeOpacities(OpacityTree* opacity_tree) {
- if (!opacity_tree->needs_update())
+void ComputeOpacities(EffectTree* effect_tree) {
+ if (!effect_tree->needs_update())
return;
- for (int i = 1; i < static_cast<int>(opacity_tree->size()); ++i)
- opacity_tree->UpdateOpacities(i);
- opacity_tree->set_needs_update(false);
+ for (int i = 1; i < static_cast<int>(effect_tree->size()); ++i)
+ effect_tree->UpdateOpacities(i);
+ effect_tree->set_needs_update(false);
}
template <typename LayerType>
@@ -447,7 +530,7 @@ void ComputeVisibleRectsUsingPropertyTreesInternal(
property_trees->clip_tree.set_needs_update(true);
ComputeTransforms(&property_trees->transform_tree);
ComputeClips(&property_trees->clip_tree, property_trees->transform_tree);
- ComputeOpacities(&property_trees->opacity_tree);
+ ComputeOpacities(&property_trees->effect_tree);
const bool subtree_is_visible_from_ancestor = true;
std::vector<LayerType*> visible_layer_list;
@@ -514,11 +597,10 @@ void ComputeVisibleRectsUsingPropertyTrees(LayerImpl* root_layer,
template <typename LayerType>
gfx::Transform DrawTransformFromPropertyTreesInternal(
const LayerType* layer,
- const TransformTree& tree) {
- const TransformNode* node = tree.Node(layer->transform_tree_index());
-
+ const TransformNode* node) {
gfx::Transform xform;
- const bool owns_non_root_surface = layer->parent() && layer->render_surface();
+ const bool owns_non_root_surface =
+ layer->parent() && layer->has_render_surface();
if (!owns_non_root_surface) {
// If you're not the root, or you don't own a surface, you need to apply
// your local offset.
@@ -536,51 +618,100 @@ gfx::Transform DrawTransformFromPropertyTreesInternal(
gfx::Transform DrawTransformFromPropertyTrees(const Layer* layer,
const TransformTree& tree) {
- return DrawTransformFromPropertyTreesInternal(layer, tree);
+ return DrawTransformFromPropertyTreesInternal(
+ layer, tree.Node(layer->transform_tree_index()));
}
gfx::Transform DrawTransformFromPropertyTrees(const LayerImpl* layer,
const TransformTree& tree) {
- return DrawTransformFromPropertyTreesInternal(layer, tree);
+ return DrawTransformFromPropertyTreesInternal(
+ layer, tree.Node(layer->transform_tree_index()));
+}
+
+gfx::Transform SurfaceDrawTransform(const RenderSurfaceImpl* render_surface,
+ const TransformTree& tree) {
+ const TransformNode* node = tree.Node(render_surface->TransformTreeIndex());
+ gfx::Transform render_surface_transform;
+ // The draw transform of root render surface is identity tranform.
+ if (node->id == 1)
+ return render_surface_transform;
+ const TransformNode* target_node = tree.Node(node->data.target_id);
+ tree.ComputeTransformWithDestinationSublayerScale(node->id, target_node->id,
+ &render_surface_transform);
+ if (node->data.sublayer_scale.x() != 0.0 &&
+ node->data.sublayer_scale.y() != 0.0)
+ render_surface_transform.Scale(1.0 / node->data.sublayer_scale.x(),
+ 1.0 / node->data.sublayer_scale.y());
+ return render_surface_transform;
+}
+
+bool SurfaceIsClipped(const RenderSurfaceImpl* render_surface,
+ const ClipNode* clip_node) {
+ // If the render surface's owning layer doesn't form a clip node, it is not
+ // clipped.
+ if (render_surface->OwningLayerId() != clip_node->owner_id)
+ return false;
+ return clip_node->data.render_surface_is_clipped;
+}
+
+gfx::Rect SurfaceClipRect(const RenderSurfaceImpl* render_surface,
+ const ClipNode* parent_clip_node,
+ bool is_clipped) {
+ if (!is_clipped)
+ return gfx::Rect();
+ return gfx::ToEnclosingRect(parent_clip_node->data.clip_in_target_space);
+}
+
+gfx::Transform SurfaceScreenSpaceTransform(
+ const RenderSurfaceImpl* render_surface,
+ const TransformTree& tree) {
+ const TransformNode* node = tree.Node(render_surface->TransformTreeIndex());
+ gfx::Transform screen_space_transform;
+ // The screen space transform of root render surface is identity tranform.
+ if (node->id == 1)
+ return screen_space_transform;
+ screen_space_transform = node->data.to_screen;
+ if (node->data.sublayer_scale.x() != 0.0 &&
+ node->data.sublayer_scale.y() != 0.0)
+ screen_space_transform.Scale(1.0 / node->data.sublayer_scale.x(),
+ 1.0 / node->data.sublayer_scale.y());
+ return screen_space_transform;
}
template <typename LayerType>
gfx::Transform ScreenSpaceTransformFromPropertyTreesInternal(
LayerType* layer,
- const TransformTree& tree) {
+ const TransformNode* node) {
gfx::Transform xform(1, 0, 0, 1, layer->offset_to_transform_parent().x(),
layer->offset_to_transform_parent().y());
- if (layer->transform_tree_index() >= 0) {
- gfx::Transform ssxform =
- tree.Node(layer->transform_tree_index())->data.to_screen;
- xform.ConcatTransform(ssxform);
- if (layer->should_flatten_transform_from_property_tree())
- xform.FlattenTo2d();
- }
+ gfx::Transform ssxform = node->data.to_screen;
+ xform.ConcatTransform(ssxform);
+ if (layer->should_flatten_transform_from_property_tree())
+ xform.FlattenTo2d();
return xform;
}
gfx::Transform ScreenSpaceTransformFromPropertyTrees(
const Layer* layer,
const TransformTree& tree) {
- return ScreenSpaceTransformFromPropertyTreesInternal(layer, tree);
+ return ScreenSpaceTransformFromPropertyTreesInternal(
+ layer, tree.Node(layer->transform_tree_index()));
}
gfx::Transform ScreenSpaceTransformFromPropertyTrees(
const LayerImpl* layer,
const TransformTree& tree) {
- return ScreenSpaceTransformFromPropertyTreesInternal(layer, tree);
+ return ScreenSpaceTransformFromPropertyTreesInternal(
+ layer, tree.Node(layer->transform_tree_index()));
}
-template <typename LayerType>
-float DrawOpacityFromPropertyTreesInternal(LayerType layer,
- const OpacityTree& tree) {
+float LayerDrawOpacity(const LayerImpl* layer, const EffectTree& tree) {
if (!layer->render_target())
return 0.f;
- const OpacityNode* target_node =
- tree.Node(layer->render_target()->opacity_tree_index());
- const OpacityNode* node = tree.Node(layer->opacity_tree_index());
+ const EffectNode* target_node =
+ tree.Node(layer->render_target()->effect_tree_index());
+ const EffectNode* node = tree.Node(layer->effect_tree_index());
if (node == target_node)
return 1.f;
@@ -592,35 +723,35 @@ float DrawOpacityFromPropertyTreesInternal(LayerType layer,
return draw_opacity;
}
-float DrawOpacityFromPropertyTrees(const Layer* layer,
- const OpacityTree& tree) {
- return DrawOpacityFromPropertyTreesInternal(layer, tree);
-}
-
-float DrawOpacityFromPropertyTrees(const LayerImpl* layer,
- const OpacityTree& tree) {
- return DrawOpacityFromPropertyTreesInternal(layer, tree);
+float SurfaceDrawOpacity(RenderSurfaceImpl* render_surface,
+ const EffectTree& tree) {
+ const EffectNode* node = tree.Node(render_surface->EffectTreeIndex());
+ float target_opacity_tree_index = render_surface->TargetEffectTreeIndex();
+ if (target_opacity_tree_index < 0)
+ return node->data.screen_space_opacity;
+ const EffectNode* target_node = tree.Node(target_opacity_tree_index);
+ float draw_opacity = 1.f;
+ while (node != target_node) {
+ draw_opacity *= node->data.opacity;
+ node = tree.parent(node);
+ }
+ return draw_opacity;
}
-bool CanUseLcdTextFromPropertyTrees(const LayerImpl* layer,
- bool layers_always_allowed_lcd_text,
- bool can_use_lcd_text,
- PropertyTrees* property_trees) {
+bool LayerCanUseLcdText(const LayerImpl* layer,
+ bool layers_always_allowed_lcd_text,
+ bool can_use_lcd_text,
+ const TransformNode* transform_node,
+ const EffectNode* effect_node) {
if (layers_always_allowed_lcd_text)
return true;
if (!can_use_lcd_text)
return false;
if (!layer->contents_opaque())
return false;
- DCHECK(!property_trees->transform_tree.needs_update());
- DCHECK(!property_trees->opacity_tree.needs_update());
- const OpacityNode* opacity_node =
- property_trees->opacity_tree.Node(layer->opacity_tree_index());
- if (opacity_node->data.screen_space_opacity != 1.f)
+ if (effect_node->data.screen_space_opacity != 1.f)
return false;
- const TransformNode* transform_node =
- property_trees->transform_tree.Node(layer->transform_tree_index());
if (!transform_node->data.node_and_ancestors_have_only_integer_translation)
return false;
if (static_cast<int>(layer->offset_to_transform_parent().x()) !=
@@ -632,4 +763,129 @@ bool CanUseLcdTextFromPropertyTrees(const LayerImpl* layer,
return true;
}
+gfx::Rect LayerDrawableContentRect(
+ const LayerImpl* layer,
+ const gfx::Rect& layer_bounds_in_target_space,
+ const gfx::Rect& clip_rect) {
+ if (layer->is_clipped())
+ return IntersectRects(layer_bounds_in_target_space, clip_rect);
+
+ return layer_bounds_in_target_space;
+}
+
+gfx::Transform ReplicaToSurfaceTransform(
+ const RenderSurfaceImpl* render_surface,
+ const TransformTree& tree) {
+ gfx::Transform replica_to_surface;
+ if (!render_surface->HasReplica())
+ return replica_to_surface;
+ const LayerImpl* replica_layer = render_surface->ReplicaLayer();
+ const TransformNode* surface_transform_node =
+ tree.Node(render_surface->TransformTreeIndex());
+ replica_to_surface.Scale(surface_transform_node->data.sublayer_scale.x(),
+ surface_transform_node->data.sublayer_scale.y());
+ replica_to_surface.Translate(replica_layer->offset_to_transform_parent().x(),
+ replica_layer->offset_to_transform_parent().y());
+ gfx::Transform replica_transform_node_to_surface;
+ tree.ComputeTransform(replica_layer->transform_tree_index(),
+ render_surface->TransformTreeIndex(),
+ &replica_transform_node_to_surface);
+ replica_to_surface.PreconcatTransform(replica_transform_node_to_surface);
+ if (surface_transform_node->data.sublayer_scale.x() != 0 &&
+ surface_transform_node->data.sublayer_scale.y() != 0) {
+ replica_to_surface.Scale(
+ 1.0 / surface_transform_node->data.sublayer_scale.x(),
+ 1.0 / surface_transform_node->data.sublayer_scale.y());
+ }
+ return replica_to_surface;
+}
+
+gfx::Rect LayerClipRect(const LayerImpl* layer,
+ const gfx::Rect& layer_bounds_in_target_space) {
+ if (layer->is_clipped())
+ return layer->clip_rect_in_target_space_from_property_trees();
+
+ return layer_bounds_in_target_space;
+}
+
+void ComputeLayerDrawPropertiesUsingPropertyTrees(
+ const LayerImpl* layer,
+ const PropertyTrees* property_trees,
+ bool layers_always_allowed_lcd_text,
+ bool can_use_lcd_text,
+ DrawProperties* draw_properties) {
+ draw_properties->visible_layer_rect =
+ layer->visible_rect_from_property_trees();
+
+ const TransformNode* transform_node =
+ property_trees->transform_tree.Node(layer->transform_tree_index());
+ const EffectNode* effect_node =
+ property_trees->effect_tree.Node(layer->effect_tree_index());
+ const ClipNode* clip_node =
+ property_trees->clip_tree.Node(layer->clip_tree_index());
+
+ draw_properties->target_space_transform =
+ DrawTransformFromPropertyTreesInternal(layer, transform_node);
+ draw_properties->screen_space_transform =
+ ScreenSpaceTransformFromPropertyTreesInternal(layer, transform_node);
+ draw_properties->screen_space_transform_is_animating =
+ transform_node->data.to_screen_is_animated;
+ if (layer->layer_tree_impl()
+ ->settings()
+ .layer_transforms_should_scale_layer_contents) {
+ draw_properties->maximum_animation_contents_scale =
+ transform_node->data.combined_maximum_animation_target_scale;
+ draw_properties->starting_animation_contents_scale =
+ transform_node->data.combined_starting_animation_scale;
+ } else {
+ draw_properties->maximum_animation_contents_scale = 0.f;
+ draw_properties->starting_animation_contents_scale = 0.f;
+ }
+
+ draw_properties->opacity =
+ LayerDrawOpacity(layer, property_trees->effect_tree);
+ draw_properties->can_use_lcd_text =
+ LayerCanUseLcdText(layer, layers_always_allowed_lcd_text,
+ can_use_lcd_text, transform_node, effect_node);
+ draw_properties->is_clipped = clip_node->data.layers_are_clipped;
+
+ gfx::Rect bounds_in_target_space = MathUtil::MapEnclosingClippedRect(
+ draw_properties->target_space_transform, gfx::Rect(layer->bounds()));
+ draw_properties->clip_rect = LayerClipRect(layer, bounds_in_target_space);
+ draw_properties->drawable_content_rect = LayerDrawableContentRect(
+ layer, bounds_in_target_space, draw_properties->clip_rect);
+}
+
+void ComputeSurfaceDrawPropertiesUsingPropertyTrees(
+ RenderSurfaceImpl* render_surface,
+ const PropertyTrees* property_trees,
+ RenderSurfaceDrawProperties* draw_properties) {
+ const ClipNode* clip_node =
+ property_trees->clip_tree.Node(render_surface->ClipTreeIndex());
+
+ draw_properties->is_clipped = SurfaceIsClipped(render_surface, clip_node);
+ draw_properties->draw_opacity =
+ SurfaceDrawOpacity(render_surface, property_trees->effect_tree);
+ draw_properties->draw_transform =
+ SurfaceDrawTransform(render_surface, property_trees->transform_tree);
+ draw_properties->screen_space_transform = SurfaceScreenSpaceTransform(
+ render_surface, property_trees->transform_tree);
+
+ if (render_surface->HasReplica()) {
+ gfx::Transform replica_to_surface = ReplicaToSurfaceTransform(
+ render_surface, property_trees->transform_tree);
+ draw_properties->replica_draw_transform =
+ draw_properties->draw_transform * replica_to_surface;
+ draw_properties->replica_screen_space_transform =
+ draw_properties->screen_space_transform * replica_to_surface;
+ } else {
+ draw_properties->replica_draw_transform.MakeIdentity();
+ draw_properties->replica_screen_space_transform.MakeIdentity();
+ }
+
+ draw_properties->clip_rect = SurfaceClipRect(
+ render_surface, property_trees->clip_tree.parent(clip_node),
+ draw_properties->is_clipped);
+}
+
} // namespace cc
diff --git a/chromium/cc/trees/draw_property_utils.h b/chromium/cc/trees/draw_property_utils.h
index 952bef1a691..1291e0f30ba 100644
--- a/chromium/cc/trees/draw_property_utils.h
+++ b/chromium/cc/trees/draw_property_utils.h
@@ -16,9 +16,12 @@ class Transform;
namespace cc {
class ClipTree;
+struct DrawProperties;
class Layer;
class LayerImpl;
-class OpacityTree;
+struct RenderSurfaceDrawProperties;
+class RenderSurfaceImpl;
+class EffectTree;
class TransformTree;
class PropertyTrees;
@@ -34,7 +37,7 @@ ComputeClips(ClipTree* clip_tree, const TransformTree& transform_tree);
void CC_EXPORT ComputeTransforms(TransformTree* transform_tree);
// Computes screen space opacity for every node in the opacity tree.
-void CC_EXPORT ComputeOpacities(OpacityTree* opacity_tree);
+void CC_EXPORT ComputeOpacities(EffectTree* effect_tree);
// Computes the visible content rect for every layer under |root_layer|. The
// visible content rect is the clipped content space rect that will be used for
@@ -73,6 +76,18 @@ ComputeVisibleRectsUsingPropertyTrees(LayerImpl* root_layer,
PropertyTrees* property_trees,
LayerImplList* update_layer_list);
+void CC_EXPORT ComputeLayerDrawPropertiesUsingPropertyTrees(
+ const LayerImpl* layer,
+ const PropertyTrees* property_trees,
+ bool layers_always_allowed_lcd_text,
+ bool can_use_lcd_text,
+ DrawProperties* draw_properties);
+
+void CC_EXPORT ComputeSurfaceDrawPropertiesUsingPropertyTrees(
+ RenderSurfaceImpl* render_surface,
+ const PropertyTrees* property_trees,
+ RenderSurfaceDrawProperties* draw_properties);
+
gfx::Transform CC_EXPORT
DrawTransformFromPropertyTrees(const Layer* layer, const TransformTree& tree);
@@ -88,18 +103,6 @@ gfx::Transform CC_EXPORT
ScreenSpaceTransformFromPropertyTrees(const LayerImpl* layer,
const TransformTree& tree);
-float CC_EXPORT
-DrawOpacityFromPropertyTrees(const Layer* layer, const OpacityTree& tree);
-
-float CC_EXPORT
-DrawOpacityFromPropertyTrees(const LayerImpl* layer, const OpacityTree& tree);
-
-bool CC_EXPORT
-CanUseLcdTextFromPropertyTrees(const LayerImpl* layer,
- bool layers_always_allowed_lcd_text,
- bool can_use_lcd_text,
- PropertyTrees* property_trees);
-
} // namespace cc
#endif // CC_TREES_DRAW_PROPERTY_UTILS_H_
diff --git a/chromium/cc/trees/latency_info_swap_promise_monitor.cc b/chromium/cc/trees/latency_info_swap_promise_monitor.cc
index c63ac5b0a04..a57ae4c8c41 100644
--- a/chromium/cc/trees/latency_info_swap_promise_monitor.cc
+++ b/chromium/cc/trees/latency_info_swap_promise_monitor.cc
@@ -30,7 +30,7 @@ bool AddForwardingScrollUpdateToMainComponent(ui::LatencyInfo* latency_info) {
return false;
latency_info->AddLatencyNumber(
ui::INPUT_EVENT_LATENCY_FORWARD_SCROLL_UPDATE_TO_MAIN_COMPONENT, 0,
- latency_info->trace_id);
+ latency_info->trace_id());
return true;
}
@@ -59,7 +59,12 @@ void LatencyInfoSwapPromiseMonitor::OnSetNeedsCommitOnMain() {
void LatencyInfoSwapPromiseMonitor::OnSetNeedsRedrawOnImpl() {
if (AddRenderingScheduledComponent(latency_, false /* on_main */)) {
scoped_ptr<SwapPromise> swap_promise(new LatencyInfoSwapPromise(*latency_));
- layer_tree_host_impl_->active_tree()->QueueSwapPromise(swap_promise.Pass());
+ // Queue a pinned swap promise on the active tree. This will allow
+ // measurement of the time to the next SwapBuffers(). The swap
+ // promise is pinned so that it is not interrupted by new incoming
+ // activations (which would otherwise break the swap promise).
+ layer_tree_host_impl_->active_tree()->QueuePinnedSwapPromise(
+ swap_promise.Pass());
}
}
@@ -67,8 +72,8 @@ void LatencyInfoSwapPromiseMonitor::OnForwardScrollUpdateToMainThreadOnImpl() {
if (AddForwardingScrollUpdateToMainComponent(latency_)) {
int64 new_sequence_number = 0;
for (ui::LatencyInfo::LatencyMap::const_iterator it =
- latency_->latency_components.begin();
- it != latency_->latency_components.end(); ++it) {
+ latency_->latency_components().begin();
+ it != latency_->latency_components().end(); ++it) {
if (it->first.first == ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT) {
new_sequence_number =
((static_cast<int64>(base::PlatformThread::CurrentId()) << 32) ^
diff --git a/chromium/cc/trees/latency_info_swap_promise_monitor.h b/chromium/cc/trees/latency_info_swap_promise_monitor.h
index c1d9973911e..2f5e0e5d339 100644
--- a/chromium/cc/trees/latency_info_swap_promise_monitor.h
+++ b/chromium/cc/trees/latency_info_swap_promise_monitor.h
@@ -9,7 +9,7 @@
#define CC_TREES_LATENCY_INFO_SWAP_PROMISE_MONITOR_H_
namespace ui {
-struct LatencyInfo;
+class LatencyInfo;
} // namespace ui
namespace cc {
diff --git a/chromium/cc/trees/layer_tree_host.cc b/chromium/cc/trees/layer_tree_host.cc
index a348301ba49..f42311604d6 100644
--- a/chromium/cc/trees/layer_tree_host.cc
+++ b/chromium/cc/trees/layer_tree_host.cc
@@ -35,7 +35,6 @@
#include "cc/layers/layer.h"
#include "cc/layers/layer_iterator.h"
#include "cc/layers/painted_scrollbar_layer.h"
-#include "cc/layers/render_surface.h"
#include "cc/resources/ui_resource_request.h"
#include "cc/scheduler/begin_frame_source.h"
#include "cc/trees/draw_property_utils.h"
@@ -88,7 +87,6 @@ scoped_ptr<LayerTreeHost> LayerTreeHost::CreateSingleThreaded(
LayerTreeHost::LayerTreeHost(InitParams* params)
: micro_benchmark_controller_(this),
next_ui_resource_id_(1),
- inside_begin_main_frame_(false),
needs_full_tree_sync_(true),
needs_meta_info_recomputation_(true),
client_(params->client),
@@ -101,6 +99,7 @@ LayerTreeHost::LayerTreeHost(InitParams* params)
top_controls_shrink_blink_size_(false),
top_controls_height_(0.f),
top_controls_shown_ratio_(0.f),
+ hide_pinch_scrollbars_near_min_scale_(false),
device_scale_factor_(1.f),
visible_(true),
page_scale_factor_(1.f),
@@ -223,9 +222,7 @@ void LayerTreeHost::BeginMainFrameNotExpectedSoon() {
}
void LayerTreeHost::BeginMainFrame(const BeginFrameArgs& args) {
- inside_begin_main_frame_ = true;
client_->BeginMainFrame(args);
- inside_begin_main_frame_ = false;
}
void LayerTreeHost::DidStopFlinging() {
@@ -236,11 +233,6 @@ void LayerTreeHost::Layout() {
client_->Layout();
}
-void LayerTreeHost::BeginCommitOnImplThread(LayerTreeHostImpl* host_impl) {
- DCHECK(proxy_->IsImplThread());
- TRACE_EVENT0("cc", "LayerTreeHost::CommitTo");
-}
-
// This function commits the LayerTreeHost to an impl tree. When modifying
// this function, keep in mind that the function *runs* on the impl thread! Any
// code that is logically a main thread operation, e.g. deletion of a Layer,
@@ -301,6 +293,10 @@ void LayerTreeHost::FinishCommitOnImplThread(LayerTreeHostImpl* host_impl) {
// Setting property trees must happen before pushing the page scale.
sync_tree->SetPropertyTrees(property_trees_);
+
+ sync_tree->set_hide_pinch_scrollbars_near_min_scale(
+ hide_pinch_scrollbars_near_min_scale_);
+
sync_tree->PushPageScaleFromMainThread(
page_scale_factor_, min_page_scale_factor_, max_page_scale_factor_);
sync_tree->elastic_overscroll()->PushFromMainThread(elastic_overscroll_);
@@ -320,7 +316,10 @@ void LayerTreeHost::FinishCommitOnImplThread(LayerTreeHostImpl* host_impl) {
RecordGpuRasterizationHistogram();
host_impl->SetViewportSize(device_viewport_size_);
- host_impl->SetDeviceScaleFactor(device_scale_factor_);
+ // TODO(senorblanco): Move this up so that it happens before GPU rasterization
+ // properties are set, since those trigger an update of GPU rasterization
+ // status, which depends on the device scale factor. (crbug.com/535700)
+ sync_tree->SetDeviceScaleFactor(device_scale_factor_);
host_impl->SetDebugState(debug_state_);
if (pending_page_scale_animation_) {
sync_tree->SetPendingPageScaleAnimation(
@@ -389,7 +388,18 @@ void LayerTreeHost::SetOutputSurface(scoped_ptr<OutputSurface> surface) {
DCHECK(output_surface_lost_);
DCHECK(surface);
- proxy_->SetOutputSurface(surface.Pass());
+ DCHECK(!new_output_surface_);
+ new_output_surface_ = surface.Pass();
+ proxy_->SetOutputSurface(new_output_surface_.get());
+}
+
+scoped_ptr<OutputSurface> LayerTreeHost::ReleaseOutputSurface() {
+ DCHECK(!visible_);
+ DCHECK(!output_surface_lost_);
+
+ DidLoseOutputSurface();
+ proxy_->ReleaseOutputSurface();
+ return current_output_surface_.Pass();
}
void LayerTreeHost::RequestNewOutputSurface() {
@@ -397,16 +407,20 @@ void LayerTreeHost::RequestNewOutputSurface() {
}
void LayerTreeHost::DidInitializeOutputSurface() {
+ DCHECK(new_output_surface_);
output_surface_lost_ = false;
- if (root_layer()) {
- LayerTreeHostCommon::CallFunctionForSubtree(
- root_layer(), [](Layer* layer) { layer->OnOutputSurfaceCreated(); });
- }
+ current_output_surface_ = new_output_surface_.Pass();
client_->DidInitializeOutputSurface();
}
void LayerTreeHost::DidFailToInitializeOutputSurface() {
DCHECK(output_surface_lost_);
+ DCHECK(new_output_surface_);
+ // Note: It is safe to drop all output surface references here as
+ // LayerTreeHostImpl will not keep a pointer to either the old or
+ // new output surface after failing to initialize the new one.
+ current_output_surface_ = nullptr;
+ new_output_surface_ = nullptr;
client_->DidFailToInitializeOutputSurface();
}
@@ -475,6 +489,11 @@ void LayerTreeHost::SetNeedsUpdateLayers() {
NotifySwapPromiseMonitorsOfSetNeedsCommit();
}
+void LayerTreeHost::SetPropertyTreesNeedRebuild() {
+ property_trees_.needs_rebuild = true;
+ SetNeedsUpdateLayers();
+}
+
void LayerTreeHost::SetNeedsCommit() {
proxy_->SetNeedsCommit();
NotifySwapPromiseMonitorsOfSetNeedsCommit();
@@ -515,6 +534,7 @@ void LayerTreeHost::SetNextCommitWaitsForActivation() {
void LayerTreeHost::SetNextCommitForcesRedraw() {
next_commit_forces_redraw_ = true;
+ proxy_->SetNeedsUpdateLayers();
}
void LayerTreeHost::SetAnimationEvents(
@@ -562,7 +582,6 @@ void LayerTreeHost::SetDebugState(const LayerTreeDebugState& debug_state) {
debug_state_.RecordRenderingStats());
SetNeedsCommit();
- proxy_->SetDebugState(debug_state);
}
void LayerTreeHost::SetHasGpuRasterizationTrigger(bool has_trigger) {
@@ -583,7 +602,7 @@ void LayerTreeHost::SetViewportSize(const gfx::Size& device_viewport_size) {
device_viewport_size_ = device_viewport_size;
- property_trees_.needs_rebuild = true;
+ SetPropertyTreesNeedRebuild();
SetNeedsCommit();
}
@@ -610,7 +629,7 @@ void LayerTreeHost::ApplyPageScaleDeltaFromImplSide(float page_scale_delta) {
if (page_scale_delta == 1.f)
return;
page_scale_factor_ *= page_scale_delta;
- property_trees_.needs_rebuild = true;
+ SetPropertyTreesNeedRebuild();
}
void LayerTreeHost::SetPageScaleFactorAndLimits(float page_scale_factor,
@@ -624,7 +643,7 @@ void LayerTreeHost::SetPageScaleFactorAndLimits(float page_scale_factor,
page_scale_factor_ = page_scale_factor;
min_page_scale_factor_ = min_page_scale_factor;
max_page_scale_factor_ = max_page_scale_factor;
- property_trees_.needs_rebuild = true;
+ SetPropertyTreesNeedRebuild();
SetNeedsCommit();
}
@@ -632,8 +651,6 @@ void LayerTreeHost::SetVisible(bool visible) {
if (visible_ == visible)
return;
visible_ = visible;
- if (!visible)
- ReduceMemoryUsage();
proxy_->SetVisible(visible);
}
@@ -710,7 +727,9 @@ static Layer* FindFirstScrollableLayer(Layer* layer) {
}
void LayerTreeHost::RecordGpuRasterizationHistogram() {
- if (gpu_rasterization_histogram_recorded_)
+ // Gpu rasterization is only supported for Renderer compositors.
+ // Checking for proxy_->HasImplThread() to exclude Browser compositors.
+ if (gpu_rasterization_histogram_recorded_ || !proxy_->HasImplThread())
return;
// Record how widely gpu rasterization is enabled.
@@ -741,8 +760,6 @@ bool LayerTreeHost::DoUpdateLayers(Layer* root_layer) {
TRACE_EVENT1("cc", "LayerTreeHost::DoUpdateLayers", "source_frame_number",
source_frame_number());
- RenderSurfaceLayerList render_surface_layer_list;
-
UpdateHudLayer();
Layer* root_scroll = FindFirstScrollableLayer(root_layer);
@@ -756,21 +773,6 @@ bool LayerTreeHost::DoUpdateLayers(Layer* root_layer) {
}
bool can_render_to_separate_surface = true;
- // TODO(vmpstr): Passing 0 as the current render surface layer list id means
- // that we won't be able to detect if a layer is part of
- // |render_surface_layer_list|. Change this if this information is
- // required.
- int render_surface_layer_list_id = 0;
- LayerTreeHostCommon::CalcDrawPropsMainInputs inputs(
- root_layer, device_viewport_size(), gfx::Transform(),
- device_scale_factor_, page_scale_factor_, page_scale_layer,
- inner_viewport_scroll_layer_.get(), outer_viewport_scroll_layer_.get(),
- elastic_overscroll_, overscroll_elasticity_layer_.get(),
- GetRendererCapabilities().max_texture_size, settings_.can_use_lcd_text,
- settings_.layers_always_allowed_lcd_text, can_render_to_separate_surface,
- settings_.layer_transforms_should_scale_layer_contents,
- settings_.verify_property_trees, &render_surface_layer_list,
- render_surface_layer_list_id, &property_trees_);
TRACE_EVENT0("cc", "LayerTreeHost::UpdateLayers::CalcDrawProps");
@@ -799,9 +801,6 @@ bool LayerTreeHost::DoUpdateLayers(Layer* root_layer) {
base::AutoReset<bool> painting(&in_paint_layer_contents_, true);
bool did_paint_content = false;
for (const auto& layer : update_layer_list) {
- // TODO(enne): temporarily clobber draw properties visible rect.
- layer->draw_properties().visible_layer_rect =
- layer->visible_rect_from_property_trees();
did_paint_content |= layer->Update();
content_is_suitable_for_gpu_rasterization_ &=
layer->IsSuitableForGpuRasterization();
@@ -809,22 +808,15 @@ bool LayerTreeHost::DoUpdateLayers(Layer* root_layer) {
return did_paint_content;
}
-void LayerTreeHost::ReduceMemoryUsage() {
- if (!root_layer())
- return;
-
- LayerTreeHostCommon::CallFunctionForSubtree(
- root_layer(), [](Layer* layer) { layer->ReduceMemoryUsage(); });
-}
-
void LayerTreeHost::ApplyScrollAndScale(ScrollAndScaleSet* info) {
ScopedPtrVector<SwapPromise>::iterator it = info->swap_promises.begin();
for (; it != info->swap_promises.end(); ++it) {
scoped_ptr<SwapPromise> swap_promise(info->swap_promises.take(it));
- TRACE_EVENT_FLOW_STEP0("input",
+ TRACE_EVENT_WITH_FLOW1("input,benchmark",
"LatencyInfo.Flow",
TRACE_ID_DONT_MANGLE(swap_promise->TraceId()),
- "Main thread scroll update");
+ TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
+ "step", "Main thread scroll update");
QueueSwapPromise(swap_promise.Pass());
}
@@ -846,6 +838,7 @@ void LayerTreeHost::ApplyScrollAndScale(ScrollAndScaleSet* info) {
gfx::ScrollOffsetWithDelta(layer->scroll_offset(),
info->scrolls[i].scroll_delta));
}
+ SetNeedsUpdateLayers();
}
}
@@ -877,33 +870,10 @@ void LayerTreeHost::ApplyScrollAndScale(ScrollAndScaleSet* info) {
inner_viewport_scroll_delta, outer_viewport_scroll_delta,
info->elastic_overscroll_delta, info->page_scale_delta,
info->top_controls_delta);
+ SetNeedsUpdateLayers();
}
}
-void LayerTreeHost::StartRateLimiter() {
- if (inside_begin_main_frame_)
- return;
-
- if (!rate_limit_timer_.IsRunning()) {
- rate_limit_timer_.Start(FROM_HERE,
- base::TimeDelta(),
- this,
- &LayerTreeHost::RateLimit);
- }
-}
-
-void LayerTreeHost::StopRateLimiter() {
- rate_limit_timer_.Stop();
-}
-
-void LayerTreeHost::RateLimit() {
- // Force a no-op command on the compositor context, so that any ratelimiting
- // commands will wait for the compositing context, and therefore for the
- // SwapBuffers.
- proxy_->ForceSerializeOnSwapBuffers();
- client_->RateLimitSharedMainThreadContext();
-}
-
void LayerTreeHost::SetDeviceScaleFactor(float device_scale_factor) {
if (device_scale_factor == device_scale_factor_)
return;
@@ -1002,6 +972,8 @@ void LayerTreeHost::RegisterViewportLayers(
scoped_refptr<Layer> page_scale_layer,
scoped_refptr<Layer> inner_viewport_scroll_layer,
scoped_refptr<Layer> outer_viewport_scroll_layer) {
+ DCHECK_IMPLIES(inner_viewport_scroll_layer,
+ inner_viewport_scroll_layer != outer_viewport_scroll_layer);
overscroll_elasticity_layer_ = overscroll_elasticity_layer;
page_scale_layer_ = page_scale_layer;
inner_viewport_scroll_layer_ = inner_viewport_scroll_layer;
@@ -1111,7 +1083,7 @@ void LayerTreeHost::UnregisterLayer(Layer* layer) {
}
bool LayerTreeHost::IsLayerInTree(int layer_id, LayerTreeType tree_type) const {
- return tree_type == LayerTreeType::ACTIVE;
+ return tree_type == LayerTreeType::ACTIVE && LayerById(layer_id);
}
void LayerTreeHost::SetMutatorsNeedCommit() {
@@ -1151,6 +1123,15 @@ void LayerTreeHost::SetLayerScrollOffsetMutated(
layer->OnScrollOffsetAnimated(scroll_offset);
}
+void LayerTreeHost::LayerTransformIsPotentiallyAnimatingChanged(
+ int layer_id,
+ LayerTreeType tree_type,
+ bool is_animating) {
+ LayerAnimationValueObserver* layer = LayerById(layer_id);
+ DCHECK(layer);
+ layer->OnTransformIsPotentiallyAnimatingChanged(is_animating);
+}
+
gfx::ScrollOffset LayerTreeHost::GetScrollOffsetForAnimation(
int layer_id) const {
LayerAnimationValueProvider* layer = LayerById(layer_id);
@@ -1167,19 +1148,30 @@ bool LayerTreeHost::ScrollOffsetAnimationWasInterrupted(
bool LayerTreeHost::IsAnimatingFilterProperty(const Layer* layer) const {
return animation_host_
- ? animation_host_->IsAnimatingFilterProperty(layer->id())
+ ? animation_host_->IsAnimatingFilterProperty(layer->id(),
+ LayerTreeType::ACTIVE)
: false;
}
bool LayerTreeHost::IsAnimatingOpacityProperty(const Layer* layer) const {
return animation_host_
- ? animation_host_->IsAnimatingOpacityProperty(layer->id())
+ ? animation_host_->IsAnimatingOpacityProperty(
+ layer->id(), LayerTreeType::ACTIVE)
: false;
}
bool LayerTreeHost::IsAnimatingTransformProperty(const Layer* layer) const {
return animation_host_
- ? animation_host_->IsAnimatingTransformProperty(layer->id())
+ ? animation_host_->IsAnimatingTransformProperty(
+ layer->id(), LayerTreeType::ACTIVE)
+ : false;
+}
+
+bool LayerTreeHost::HasPotentiallyRunningFilterAnimation(
+ const Layer* layer) const {
+ return animation_host_
+ ? animation_host_->HasPotentiallyRunningFilterAnimation(
+ layer->id(), LayerTreeType::ACTIVE)
: false;
}
@@ -1187,7 +1179,7 @@ bool LayerTreeHost::HasPotentiallyRunningOpacityAnimation(
const Layer* layer) const {
return animation_host_
? animation_host_->HasPotentiallyRunningOpacityAnimation(
- layer->id())
+ layer->id(), LayerTreeType::ACTIVE)
: false;
}
@@ -1195,7 +1187,39 @@ bool LayerTreeHost::HasPotentiallyRunningTransformAnimation(
const Layer* layer) const {
return animation_host_
? animation_host_->HasPotentiallyRunningTransformAnimation(
- layer->id())
+ layer->id(), LayerTreeType::ACTIVE)
+ : false;
+}
+
+bool LayerTreeHost::HasOnlyTranslationTransforms(const Layer* layer) const {
+ return animation_host_
+ ? animation_host_->HasOnlyTranslationTransforms(
+ layer->id(), LayerTreeType::ACTIVE)
+ : false;
+}
+
+bool LayerTreeHost::MaximumTargetScale(const Layer* layer,
+ float* max_scale) const {
+ return animation_host_
+ ? animation_host_->MaximumTargetScale(
+ layer->id(), LayerTreeType::ACTIVE, max_scale)
+ : false;
+}
+
+bool LayerTreeHost::AnimationStartScale(const Layer* layer,
+ float* start_scale) const {
+ return animation_host_
+ ? animation_host_->AnimationStartScale(
+ layer->id(), LayerTreeType::ACTIVE, start_scale)
+ : false;
+}
+
+bool LayerTreeHost::HasAnyAnimationTargetingProperty(
+ const Layer* layer,
+ Animation::TargetProperty property) const {
+ return animation_host_
+ ? animation_host_->HasAnyAnimationTargetingProperty(layer->id(),
+ property)
: false;
}
diff --git a/chromium/cc/trees/layer_tree_host.h b/chromium/cc/trees/layer_tree_host.h
index 4f38352f9c6..5c92f97689c 100644
--- a/chromium/cc/trees/layer_tree_host.h
+++ b/chromium/cc/trees/layer_tree_host.h
@@ -17,7 +17,6 @@
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
-#include "base/timer/timer.h"
#include "cc/animation/animation_events.h"
#include "cc/base/cc_export.h"
#include "cc/base/scoped_ptr_vector.h"
@@ -107,11 +106,11 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient {
void AnimateLayers(base::TimeTicks monotonic_frame_begin_time);
void DidStopFlinging();
void Layout();
- void BeginCommitOnImplThread(LayerTreeHostImpl* host_impl);
void FinishCommitOnImplThread(LayerTreeHostImpl* host_impl);
void WillCommit();
void CommitComplete();
void SetOutputSurface(scoped_ptr<OutputSurface> output_surface);
+ scoped_ptr<OutputSurface> ReleaseOutputSurface();
void RequestNewOutputSurface();
void DidInitializeOutputSurface();
void DidFailToInitializeOutputSurface();
@@ -211,6 +210,10 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient {
void SetTopControlsHeight(float height, bool shrink);
void SetTopControlsShownRatio(float ratio);
+ void set_hide_pinch_scrollbars_near_min_scale(bool hide) {
+ hide_pinch_scrollbars_near_min_scale_ = hide;
+ }
+
gfx::Size device_viewport_size() const { return device_viewport_size_; }
void ApplyPageScaleDeltaFromImplSide(float page_scale_delta);
@@ -240,12 +243,6 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient {
void ApplyScrollAndScale(ScrollAndScaleSet* info);
void SetImplTransform(const gfx::Transform& transform);
- // Virtual for tests.
- virtual void StartRateLimiter();
- virtual void StopRateLimiter();
-
- void RateLimit();
-
void SetDeviceScaleFactor(float device_scale_factor);
float device_scale_factor() const { return device_scale_factor_; }
@@ -339,6 +336,9 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient {
int layer_id,
LayerTreeType tree_type,
const gfx::ScrollOffset& scroll_offset) override;
+ void LayerTransformIsPotentiallyAnimatingChanged(int layer_id,
+ LayerTreeType tree_type,
+ bool is_animating) override;
void ScrollOffsetAnimationFinished() override {}
gfx::ScrollOffset GetScrollOffsetForAnimation(int layer_id) const override;
@@ -346,8 +346,15 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient {
bool IsAnimatingFilterProperty(const Layer* layer) const;
bool IsAnimatingOpacityProperty(const Layer* layer) const;
bool IsAnimatingTransformProperty(const Layer* layer) const;
+ bool HasPotentiallyRunningFilterAnimation(const Layer* layer) const;
bool HasPotentiallyRunningOpacityAnimation(const Layer* layer) const;
bool HasPotentiallyRunningTransformAnimation(const Layer* layer) const;
+ bool HasOnlyTranslationTransforms(const Layer* layer) const;
+ bool MaximumTargetScale(const Layer* layer, float* max_scale) const;
+ bool AnimationStartScale(const Layer* layer, float* start_scale) const;
+ bool HasAnyAnimationTargetingProperty(
+ const Layer* layer,
+ Animation::TargetProperty property) const;
bool AnimationsPreserveAxisAlignment(const Layer* layer) const;
bool HasAnyAnimation(const Layer* layer) const;
bool HasActiveAnimation(const Layer* layer) const;
@@ -388,8 +395,6 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient {
bool DoUpdateLayers(Layer* root_layer);
void UpdateHudLayer();
- void ReduceMemoryUsage();
-
bool AnimateLayersRecursive(Layer* current, base::TimeTicks time);
struct UIResourceClientData {
@@ -410,7 +415,8 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient {
void NotifySwapPromiseMonitorsOfSetNeedsCommit();
- bool inside_begin_main_frame_;
+ void SetPropertyTreesNeedRebuild();
+
bool needs_full_tree_sync_;
bool needs_meta_info_recomputation_;
@@ -421,6 +427,13 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient {
int meta_information_sequence_number_;
scoped_ptr<RenderingStatsInstrumentation> rendering_stats_instrumentation_;
+ // |current_output_surface_| can't be updated until we've successfully
+ // initialized a new output surface. |new_output_surface_| contains the
+ // new output surface that is currently being initialized. If initialization
+ // is successful then |new_output_surface_| replaces
+ // |current_output_surface_|.
+ scoped_ptr<OutputSurface> new_output_surface_;
+ scoped_ptr<OutputSurface> current_output_surface_;
bool output_surface_lost_;
scoped_refptr<Layer> root_layer_;
@@ -436,12 +449,11 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient {
bool top_controls_shrink_blink_size_;
float top_controls_height_;
float top_controls_shown_ratio_;
+ bool hide_pinch_scrollbars_near_min_scale_;
float device_scale_factor_;
bool visible_;
- base::OneShotTimer<LayerTreeHost> rate_limit_timer_;
-
float page_scale_factor_;
float min_page_scale_factor_;
float max_page_scale_factor_;
diff --git a/chromium/cc/trees/layer_tree_host_client.h b/chromium/cc/trees/layer_tree_host_client.h
index 56a128f4bad..3bc70c5e13b 100644
--- a/chromium/cc/trees/layer_tree_host_client.h
+++ b/chromium/cc/trees/layer_tree_host_client.h
@@ -58,12 +58,6 @@ class LayerTreeHostClient {
// implementation is ready.
virtual void SendBeginFramesToChildren(const BeginFrameArgs& args) {}
- // Requests that the client insert a rate limiting token in the shared main
- // thread context's command stream that will block if the context gets too far
- // ahead of the compositor's command stream. Only needed if the tree contains
- // a TextureLayer that calls SetRateLimitContext(true).
- virtual void RateLimitSharedMainThreadContext() {}
-
protected:
virtual ~LayerTreeHostClient() {}
};
diff --git a/chromium/cc/trees/layer_tree_host_common.cc b/chromium/cc/trees/layer_tree_host_common.cc
index 427a3c825e1..2d2bd3e7caa 100644
--- a/chromium/cc/trees/layer_tree_host_common.cc
+++ b/chromium/cc/trees/layer_tree_host_common.cc
@@ -12,7 +12,7 @@
#include "cc/layers/layer.h"
#include "cc/layers/layer_impl.h"
#include "cc/layers/layer_iterator.h"
-#include "cc/layers/render_surface.h"
+#include "cc/layers/render_surface_draw_properties.h"
#include "cc/layers/render_surface_impl.h"
#include "cc/trees/draw_property_utils.h"
#include "cc/trees/layer_tree_host.h"
@@ -24,14 +24,130 @@
namespace cc {
+LayerTreeHostCommon::CalcDrawPropsMainInputs::CalcDrawPropsMainInputs(
+ Layer* root_layer,
+ const gfx::Size& device_viewport_size,
+ const gfx::Transform& device_transform,
+ float device_scale_factor,
+ float page_scale_factor,
+ const Layer* page_scale_layer,
+ const Layer* inner_viewport_scroll_layer,
+ const Layer* outer_viewport_scroll_layer)
+ : root_layer(root_layer),
+ device_viewport_size(device_viewport_size),
+ device_transform(device_transform),
+ device_scale_factor(device_scale_factor),
+ page_scale_factor(page_scale_factor),
+ page_scale_layer(page_scale_layer),
+ inner_viewport_scroll_layer(inner_viewport_scroll_layer),
+ outer_viewport_scroll_layer(outer_viewport_scroll_layer) {}
+
+LayerTreeHostCommon::CalcDrawPropsMainInputs::CalcDrawPropsMainInputs(
+ Layer* root_layer,
+ const gfx::Size& device_viewport_size,
+ const gfx::Transform& device_transform)
+ : CalcDrawPropsMainInputs(root_layer,
+ device_viewport_size,
+ device_transform,
+ 1.f,
+ 1.f,
+ NULL,
+ NULL,
+ NULL) {}
+
+LayerTreeHostCommon::CalcDrawPropsMainInputs::CalcDrawPropsMainInputs(
+ Layer* root_layer,
+ const gfx::Size& device_viewport_size)
+ : CalcDrawPropsMainInputs(root_layer,
+ device_viewport_size,
+ gfx::Transform()) {}
+
+LayerTreeHostCommon::CalcDrawPropsImplInputs::CalcDrawPropsImplInputs(
+ LayerImpl* root_layer,
+ const gfx::Size& device_viewport_size,
+ const gfx::Transform& device_transform,
+ float device_scale_factor,
+ float page_scale_factor,
+ const LayerImpl* page_scale_layer,
+ const LayerImpl* inner_viewport_scroll_layer,
+ const LayerImpl* outer_viewport_scroll_layer,
+ const gfx::Vector2dF& elastic_overscroll,
+ const LayerImpl* elastic_overscroll_application_layer,
+ int max_texture_size,
+ bool can_use_lcd_text,
+ bool layers_always_allowed_lcd_text,
+ bool can_render_to_separate_surface,
+ bool can_adjust_raster_scales,
+ bool verify_property_trees,
+ LayerImplList* render_surface_layer_list,
+ int current_render_surface_layer_list_id,
+ PropertyTrees* property_trees)
+ : root_layer(root_layer),
+ device_viewport_size(device_viewport_size),
+ device_transform(device_transform),
+ device_scale_factor(device_scale_factor),
+ page_scale_factor(page_scale_factor),
+ page_scale_layer(page_scale_layer),
+ inner_viewport_scroll_layer(inner_viewport_scroll_layer),
+ outer_viewport_scroll_layer(outer_viewport_scroll_layer),
+ elastic_overscroll(elastic_overscroll),
+ elastic_overscroll_application_layer(
+ elastic_overscroll_application_layer),
+ max_texture_size(max_texture_size),
+ can_use_lcd_text(can_use_lcd_text),
+ layers_always_allowed_lcd_text(layers_always_allowed_lcd_text),
+ can_render_to_separate_surface(can_render_to_separate_surface),
+ can_adjust_raster_scales(can_adjust_raster_scales),
+ verify_property_trees(verify_property_trees),
+ render_surface_layer_list(render_surface_layer_list),
+ current_render_surface_layer_list_id(
+ current_render_surface_layer_list_id),
+ property_trees(property_trees) {}
+
+LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting::
+ CalcDrawPropsImplInputsForTesting(LayerImpl* root_layer,
+ const gfx::Size& device_viewport_size,
+ const gfx::Transform& device_transform,
+ LayerImplList* render_surface_layer_list)
+ : CalcDrawPropsImplInputs(root_layer,
+ device_viewport_size,
+ device_transform,
+ 1.f,
+ 1.f,
+ NULL,
+ NULL,
+ NULL,
+ gfx::Vector2dF(),
+ NULL,
+ std::numeric_limits<int>::max() / 2,
+ false,
+ false,
+ true,
+ false,
+ true,
+ render_surface_layer_list,
+ 0,
+ GetPropertyTrees(root_layer)) {
+ DCHECK(root_layer);
+ DCHECK(render_surface_layer_list);
+}
+
+LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting::
+ CalcDrawPropsImplInputsForTesting(LayerImpl* root_layer,
+ const gfx::Size& device_viewport_size,
+ LayerImplList* render_surface_layer_list)
+ : CalcDrawPropsImplInputsForTesting(root_layer,
+ device_viewport_size,
+ gfx::Transform(),
+ render_surface_layer_list) {}
+
ScrollAndScaleSet::ScrollAndScaleSet()
: page_scale_delta(1.f), top_controls_delta(0.f) {
}
ScrollAndScaleSet::~ScrollAndScaleSet() {}
-template <typename LayerType>
-static gfx::Vector2dF GetEffectiveScrollDelta(LayerType* layer) {
+static gfx::Vector2dF GetEffectiveScrollDelta(LayerImpl* layer) {
// Layer's scroll offset can have an integer part and fractional part.
// Due to Blink's limitation, it only counter-scrolls the position-fixed
// layer using the integer part of Layer's scroll offset.
@@ -51,8 +167,7 @@ static gfx::Vector2dF GetEffectiveScrollDelta(LayerType* layer) {
return scroll_delta;
}
-template <typename LayerType>
-static gfx::ScrollOffset GetEffectiveCurrentScrollOffset(LayerType* layer) {
+static gfx::ScrollOffset GetEffectiveCurrentScrollOffset(LayerImpl* layer) {
gfx::ScrollOffset offset = layer->CurrentScrollOffset();
// The scroll parent's total scroll offset (scroll offset + scroll delta)
// can't be used because its scroll offset has already been applied to the
@@ -112,8 +227,7 @@ gfx::Rect LayerTreeHostCommon::CalculateVisibleRect(
target_surface_rect, layer_bound_rect, layer_in_surface_space, transform);
}
-template <typename LayerType>
-static LayerType* NextTargetSurface(LayerType* layer) {
+static const LayerImpl* NextTargetSurface(const LayerImpl* layer) {
return layer->parent() ? layer->parent()->render_target() : 0;
}
@@ -122,18 +236,17 @@ static LayerType* NextTargetSurface(LayerType* layer) {
// translation components of the draw transforms of each target between the
// ancestor and descendant. These transforms must be 2D translations, and this
// requirement is enforced at every step.
-template <typename LayerType>
static gfx::Vector2dF ComputeChangeOfBasisTranslation(
- const LayerType& ancestor_layer,
- const LayerType& descendant_layer) {
+ const LayerImpl& ancestor_layer,
+ const LayerImpl& descendant_layer) {
DCHECK(descendant_layer.HasAncestor(&ancestor_layer));
- const LayerType* descendant_target = descendant_layer.render_target();
+ const LayerImpl* descendant_target = descendant_layer.render_target();
DCHECK(descendant_target);
- const LayerType* ancestor_target = ancestor_layer.render_target();
+ const LayerImpl* ancestor_target = ancestor_layer.render_target();
DCHECK(ancestor_target);
gfx::Vector2dF translation;
- for (const LayerType* target = descendant_target; target != ancestor_target;
+ for (const LayerImpl* target = descendant_target; target != ancestor_target;
target = NextTargetSurface(target)) {
const gfx::Transform& trans = target->render_surface()->draw_transform();
// Ensure that this translation is truly 2d.
@@ -150,30 +263,29 @@ enum TranslateRectDirection {
TRANSLATE_RECT_DIRECTION_TO_DESCENDANT
};
-template <typename LayerType>
-static gfx::Rect TranslateRectToTargetSpace(const LayerType& ancestor_layer,
- const LayerType& descendant_layer,
+static gfx::Rect TranslateRectToTargetSpace(const LayerImpl& ancestor_layer,
+ const LayerImpl& descendant_layer,
const gfx::Rect& rect,
TranslateRectDirection direction) {
- gfx::Vector2dF translation = ComputeChangeOfBasisTranslation<LayerType>(
- ancestor_layer, descendant_layer);
+ gfx::Vector2dF translation =
+ ComputeChangeOfBasisTranslation(ancestor_layer, descendant_layer);
if (direction == TRANSLATE_RECT_DIRECTION_TO_DESCENDANT)
translation.Scale(-1.f);
+ gfx::RectF rect_f = gfx::RectF(rect);
return gfx::ToEnclosingRect(
- gfx::RectF(rect.origin() + translation, rect.size()));
+ gfx::RectF(rect_f.origin() + translation, rect_f.size()));
}
// Attempts to update the clip rects for the given layer. If the layer has a
// clip_parent, it may not inherit its immediate ancestor's clip.
-template <typename LayerType>
static void UpdateClipRectsForClipChild(
- const LayerType* layer,
+ const LayerImpl* layer,
gfx::Rect* clip_rect_in_parent_target_space,
bool* subtree_should_be_clipped) {
// If the layer has no clip_parent, or the ancestor is the same as its actual
// parent, then we don't need special clip rects. Bail now and leave the out
// parameters untouched.
- const LayerType* clip_parent = layer->scroll_parent();
+ const LayerImpl* clip_parent = layer->scroll_parent();
if (!clip_parent)
clip_parent = layer->clip_parent();
@@ -195,7 +307,7 @@ static void UpdateClipRectsForClipChild(
// CalculateDrawPropertiesInternal. If we, say, create a render surface, these
// clip rects will want to be in its target space, not ours.
if (clip_parent == layer->clip_parent()) {
- *clip_rect_in_parent_target_space = TranslateRectToTargetSpace<LayerType>(
+ *clip_rect_in_parent_target_space = TranslateRectToTargetSpace(
*clip_parent, *layer->parent(), *clip_rect_in_parent_target_space,
TRANSLATE_RECT_DIRECTION_TO_DESCENDANT);
} else {
@@ -203,7 +315,7 @@ static void UpdateClipRectsForClipChild(
// our common ancestor. This happens to be our parent, so it is sufficent to
// translate from our clip parent's space to the space of its ancestor (our
// parent).
- *clip_rect_in_parent_target_space = TranslateRectToTargetSpace<LayerType>(
+ *clip_rect_in_parent_target_space = TranslateRectToTargetSpace(
*layer->parent(), *clip_parent, *clip_rect_in_parent_target_space,
TRANSLATE_RECT_DIRECTION_TO_ANCESTOR);
}
@@ -216,9 +328,8 @@ static void UpdateClipRectsForClipChild(
// and its parent.
//
// NB: we accumulate the layer's *clipped* drawable content rect.
-template <typename LayerType>
struct AccumulatedSurfaceState {
- explicit AccumulatedSurfaceState(LayerType* render_target)
+ explicit AccumulatedSurfaceState(LayerImpl* render_target)
: render_target(render_target) {}
// The accumulated drawable content rect for the surface associated with the
@@ -229,15 +340,18 @@ struct AccumulatedSurfaceState {
// surface so that we can DCHECK that the surface's draw transform is simply
// a translation when |render_target| reports that it has no unclipped
// descendants).
- LayerType* render_target;
+ LayerImpl* render_target;
};
template <typename LayerType>
+static inline bool IsRootLayer(LayerType* layer) {
+ return !layer->parent();
+}
+
void UpdateAccumulatedSurfaceState(
- LayerType* layer,
+ LayerImpl* layer,
const gfx::Rect& drawable_content_rect,
- std::vector<AccumulatedSurfaceState<LayerType>>*
- accumulated_surface_state) {
+ std::vector<AccumulatedSurfaceState>* accumulated_surface_state) {
if (IsRootLayer(layer))
return;
@@ -248,7 +362,7 @@ void UpdateAccumulatedSurfaceState(
// render surface and we'll want to add our rect to our *surface's* target, or
// we're not and our target is the same as our parent's. In both cases, the
// parent's target gives us what we want.
- LayerType* render_target = layer->clip_parent()
+ LayerImpl* render_target = layer->clip_parent()
? layer->clip_parent()->render_target()
: layer->parent()->render_target();
@@ -266,9 +380,9 @@ void UpdateAccumulatedSurfaceState(
// If the layer has a clip parent, the clip rect may be in the wrong space,
// so we'll need to transform it before it is applied.
if (layer->clip_parent()) {
- clip_rect = TranslateRectToTargetSpace<LayerType>(
- *layer->clip_parent(), *layer, clip_rect,
- TRANSLATE_RECT_DIRECTION_TO_DESCENDANT);
+ clip_rect =
+ TranslateRectToTargetSpace(*layer->clip_parent(), *layer, clip_rect,
+ TRANSLATE_RECT_DIRECTION_TO_DESCENDANT);
}
target_rect.Intersect(clip_rect);
}
@@ -276,9 +390,8 @@ void UpdateAccumulatedSurfaceState(
// We must have at least one entry in the vector for the root.
DCHECK_LT(0ul, accumulated_surface_state->size());
- typedef typename std::vector<AccumulatedSurfaceState<LayerType>>
- AccumulatedSurfaceStateVector;
- typedef typename AccumulatedSurfaceStateVector::reverse_iterator
+ typedef std::vector<AccumulatedSurfaceState> AccumulatedSurfaceStateVector;
+ typedef AccumulatedSurfaceStateVector::reverse_iterator
AccumulatedSurfaceStateIterator;
AccumulatedSurfaceStateIterator current_state =
accumulated_surface_state->rbegin();
@@ -296,7 +409,7 @@ void UpdateAccumulatedSurfaceState(
}
// Transform rect from the current target's space to the next.
- LayerType* current_target = current_state->render_target;
+ LayerImpl* current_target = current_state->render_target;
DCHECK(current_target->render_surface());
const gfx::Transform& current_draw_transform =
current_target->render_surface()->draw_transform();
@@ -305,8 +418,8 @@ void UpdateAccumulatedSurfaceState(
DCHECK_IMPLIES(current_target->num_unclipped_descendants(),
current_draw_transform.IsIdentityOrTranslation());
- target_rect = gfx::ToEnclosingRect(
- MathUtil::MapClippedRect(current_draw_transform, target_rect));
+ target_rect =
+ MathUtil::MapEnclosingClippedRect(current_draw_transform, target_rect);
}
// It is an error to not reach |render_target|. If this happens, it means that
@@ -315,10 +428,6 @@ void UpdateAccumulatedSurfaceState(
DCHECK(found_render_target);
}
-template <typename LayerType> static inline bool IsRootLayer(LayerType* layer) {
- return !layer->parent();
-}
-
template <typename LayerType>
static inline bool LayerIsInExisting3DRenderingContext(LayerType* layer) {
return layer->Is3dSorted() && layer->parent() &&
@@ -326,16 +435,14 @@ static inline bool LayerIsInExisting3DRenderingContext(LayerType* layer) {
(layer->parent()->sorting_context_id() == layer->sorting_context_id());
}
-template <typename LayerType>
-static bool IsRootLayerOfNewRenderingContext(LayerType* layer) {
+static bool IsRootLayerOfNewRenderingContext(LayerImpl* layer) {
if (layer->parent())
return !layer->parent()->Is3dSorted() && layer->Is3dSorted();
return layer->Is3dSorted();
}
-template <typename LayerType>
-static bool IsLayerBackFaceVisible(LayerType* layer) {
+static bool IsLayerBackFaceVisible(LayerImpl* layer) {
// The current W3C spec on CSS transforms says that backface visibility should
// be determined differently depending on whether the layer is in a "3d
// rendering context" or not. For Chromium code, we can determine whether we
@@ -349,8 +456,7 @@ static bool IsLayerBackFaceVisible(LayerType* layer) {
return layer->transform().IsBackFaceVisible();
}
-template <typename LayerType>
-static bool IsSurfaceBackFaceVisible(LayerType* layer,
+static bool IsSurfaceBackFaceVisible(LayerImpl* layer,
const gfx::Transform& draw_transform) {
if (LayerIsInExisting3DRenderingContext(layer))
return draw_transform.IsBackFaceVisible();
@@ -369,9 +475,8 @@ static inline bool LayerClipsSubtree(LayerType* layer) {
return layer->masks_to_bounds() || layer->mask_layer();
}
-template <typename LayerType>
static gfx::Rect CalculateVisibleLayerRect(
- LayerType* layer,
+ LayerImpl* layer,
const gfx::Rect& clip_rect_of_target_surface_in_target_space,
const gfx::Rect& layer_rect_in_target_space) {
DCHECK(layer->render_target());
@@ -407,20 +512,7 @@ static gfx::Rect CalculateVisibleLayerRect(
layer_rect_in_target_space, layer->draw_transform());
}
-static inline bool TransformToParentIsKnown(LayerImpl* layer) { return true; }
-
-static inline bool TransformToParentIsKnown(Layer* layer) {
- return !layer->TransformIsAnimating();
-}
-
-static inline bool TransformToScreenIsKnown(LayerImpl* layer) { return true; }
-
-static inline bool TransformToScreenIsKnown(Layer* layer) {
- return !layer->screen_space_transform_is_animating();
-}
-
-template <typename LayerType>
-static bool LayerShouldBeSkipped(LayerType* layer, bool layer_is_drawn) {
+static bool LayerShouldBeSkipped(LayerImpl* layer, bool layer_is_drawn) {
// Layers can be skipped if any of these conditions are met.
// - is not drawn due to it or one of its ancestors being hidden (or having
// no copy requests).
@@ -444,7 +536,7 @@ static bool LayerShouldBeSkipped(LayerType* layer, bool layer_is_drawn) {
if (!layer->DrawsContent() || layer->bounds().IsEmpty())
return true;
- LayerType* backface_test_layer = layer;
+ LayerImpl* backface_test_layer = layer;
if (layer->use_parent_backface_visibility()) {
DCHECK(layer->parent());
DCHECK(!layer->parent()->use_parent_backface_visibility());
@@ -454,7 +546,6 @@ static bool LayerShouldBeSkipped(LayerType* layer, bool layer_is_drawn) {
// The layer should not be drawn if (1) it is not double-sided and (2) the
// back of the layer is known to be facing the screen.
if (!backface_test_layer->double_sided() &&
- TransformToScreenIsKnown(backface_test_layer) &&
IsLayerBackFaceVisible(backface_test_layer))
return true;
@@ -463,7 +554,8 @@ static bool LayerShouldBeSkipped(LayerType* layer, bool layer_is_drawn) {
template <typename LayerType>
static bool HasInvertibleOrAnimatedTransform(LayerType* layer) {
- return layer->transform_is_invertible() || layer->TransformIsAnimating();
+ return layer->transform_is_invertible() ||
+ layer->HasPotentiallyRunningTransformAnimation();
}
static inline bool SubtreeShouldBeSkipped(LayerImpl* layer,
@@ -477,12 +569,12 @@ static inline bool SubtreeShouldBeSkipped(LayerImpl* layer,
// When we need to do a readback/copy of a layer's output, we can not skip
// it or any of its ancestors.
- if (layer->draw_properties().layer_or_descendant_has_copy_request)
+ if (layer->num_layer_or_descendants_with_copy_request() > 0)
return false;
// We cannot skip the the subtree if a descendant has a wheel or touch handler
// or the hit testing code will break (it requires fresh transforms, etc).
- if (layer->draw_properties().layer_or_descendant_has_input_handler)
+ if (layer->layer_or_descendant_has_input_handler())
return false;
// If the layer is not drawn, then skip it and its subtree.
@@ -492,7 +584,13 @@ static inline bool SubtreeShouldBeSkipped(LayerImpl* layer,
// If layer is on the pending tree and opacity is being animated then
// this subtree can't be skipped as we need to create, prioritize and
// include tiles for this layer when deciding if tree can be activated.
- if (layer->layer_tree_impl()->IsPendingTree() && layer->OpacityIsAnimating())
+ if (layer->layer_tree_impl()->IsPendingTree() &&
+ layer->HasPotentiallyRunningOpacityAnimation())
+ return false;
+
+ // If layer has a background filter, don't skip the layer, even it the
+ // opacity is 0.
+ if (!layer->background_filters().IsEmpty())
return false;
// The opacity of a layer always applies to its children (either implicitly
@@ -501,46 +599,8 @@ static inline bool SubtreeShouldBeSkipped(LayerImpl* layer,
return !layer->opacity();
}
-static inline bool SubtreeShouldBeSkipped(Layer* layer, bool layer_is_drawn) {
- // If the layer transform is not invertible, it should not be drawn.
- if (!layer->transform_is_invertible() && !layer->TransformIsAnimating())
- return true;
-
- // When we need to do a readback/copy of a layer's output, we can not skip
- // it or any of its ancestors.
- if (layer->draw_properties().layer_or_descendant_has_copy_request)
- return false;
-
- // We cannot skip the the subtree if a descendant has a wheel or touch handler
- // or the hit testing code will break (it requires fresh transforms, etc).
- if (layer->draw_properties().layer_or_descendant_has_input_handler)
- return false;
-
- // If the layer is not drawn, then skip it and its subtree.
- if (!layer_is_drawn)
- return true;
-
- // If the opacity is being animated then the opacity on the main thread is
- // unreliable (since the impl thread may be using a different opacity), so it
- // should not be trusted.
- // In particular, it should not cause the subtree to be skipped.
- // Similarly, for layers that might animate opacity using an impl-only
- // animation, their subtree should also not be skipped.
- return !layer->opacity() && !layer->OpacityIsAnimating() &&
- !layer->OpacityCanAnimateOnImplThread();
-}
-
static inline void SavePaintPropertiesLayer(LayerImpl* layer) {}
-static inline void SavePaintPropertiesLayer(Layer* layer) {
- layer->SavePaintProperties();
-
- if (layer->mask_layer())
- layer->mask_layer()->SavePaintProperties();
- if (layer->replica_layer() && layer->replica_layer()->mask_layer())
- layer->replica_layer()->mask_layer()->SavePaintProperties();
-}
-
static bool SubtreeShouldRenderToSeparateSurface(
Layer* layer,
bool axis_aligned_with_respect_to_parent) {
@@ -576,7 +636,7 @@ static bool SubtreeShouldRenderToSeparateSurface(
// If the layer will use a CSS filter. In this case, the animation
// will start and add a filter to this layer, so it needs a surface.
- if (layer->FilterIsAnimating()) {
+ if (layer->HasPotentiallyRunningFilterAnimation()) {
DCHECK(!is_root);
return true;
}
@@ -679,10 +739,9 @@ static bool SubtreeShouldRenderToSeparateSurface(
// This function returns a translation matrix that can be applied on a vector
// that's in the layer's target surface coordinate, while the position offset is
// specified in some ancestor layer's coordinate.
-template <typename LayerType>
gfx::Transform ComputeSizeDeltaCompensation(
- LayerType* layer,
- LayerType* container,
+ LayerImpl* layer,
+ LayerImpl* container,
const gfx::Vector2dF& position_offset) {
gfx::Transform result_transform;
@@ -697,11 +756,11 @@ gfx::Transform ComputeSizeDeltaCompensation(
gfx::Transform target_surface_space_to_container_layer_space;
// Calculate step 1a
- LayerType* container_target_surface = container->render_target();
- for (LayerType* current_target_surface = NextTargetSurface(layer);
- current_target_surface &&
- current_target_surface != container_target_surface;
- current_target_surface = NextTargetSurface(current_target_surface)) {
+ LayerImpl* container_target_surface = container->render_target();
+ for (const LayerImpl* current_target_surface = NextTargetSurface(layer);
+ current_target_surface &&
+ current_target_surface != container_target_surface;
+ current_target_surface = NextTargetSurface(current_target_surface)) {
// Note: Concat is used here to convert the result coordinate space from
// current render surface to the next render surface.
target_surface_space_to_container_layer_space.ConcatTransform(
@@ -742,12 +801,10 @@ gfx::Transform ComputeSizeDeltaCompensation(
return result_transform;
}
-template <typename LayerType>
-void ApplyPositionAdjustment(
- LayerType* layer,
- LayerType* container,
- const gfx::Transform& scroll_compensation,
- gfx::Transform* combined_transform) {
+void ApplyPositionAdjustment(LayerImpl* layer,
+ LayerImpl* container,
+ const gfx::Transform& scroll_compensation,
+ gfx::Transform* combined_transform) {
if (!layer->position_constraint().is_fixed_position())
return;
@@ -776,9 +833,8 @@ void ApplyPositionAdjustment(
ComputeSizeDeltaCompensation(layer, container, position_offset));
}
-template <typename LayerType>
gfx::Transform ComputeScrollCompensationForThisLayer(
- LayerType* scrolling_layer,
+ LayerImpl* scrolling_layer,
const gfx::Transform& parent_matrix,
const gfx::Vector2dF& scroll_delta) {
// For every layer that has non-zero scroll_delta, we have to compute a
@@ -816,9 +872,8 @@ gfx::Transform ComputeScrollCompensationForThisLayer(
return scroll_compensation_for_this_layer;
}
-template <typename LayerType>
gfx::Transform ComputeScrollCompensationMatrixForChildren(
- LayerType* layer,
+ LayerImpl* layer,
const gfx::Transform& parent_matrix,
const gfx::Transform& current_scroll_compensation_matrix,
const gfx::Vector2dF& scroll_delta) {
@@ -903,9 +958,8 @@ gfx::Transform ComputeScrollCompensationMatrixForChildren(
return next_scroll_compensation_matrix;
}
-template <typename LayerType>
static inline void UpdateLayerScaleDrawProperties(
- LayerType* layer,
+ LayerImpl* layer,
float maximum_animation_contents_scale,
float starting_animation_contents_scale) {
layer->draw_properties().maximum_animation_contents_scale =
@@ -915,23 +969,10 @@ static inline void UpdateLayerScaleDrawProperties(
}
static inline void CalculateAnimationContentsScale(
- Layer* layer,
- bool ancestor_is_animating_scale,
- float ancestor_maximum_animation_contents_scale,
- const gfx::Transform& parent_transform,
- const gfx::Transform& combined_transform,
- bool* combined_is_animating_scale,
- float* combined_maximum_animation_contents_scale,
- float* combined_starting_animation_contents_scale) {
- *combined_is_animating_scale = false;
- *combined_maximum_animation_contents_scale = 0.f;
- *combined_starting_animation_contents_scale = 0.f;
-}
-
-static inline void CalculateAnimationContentsScale(
LayerImpl* layer,
bool ancestor_is_animating_scale,
float ancestor_maximum_animation_contents_scale,
+ float ancestor_starting_animation_contents_scale,
const gfx::Transform& ancestor_transform,
const gfx::Transform& combined_transform,
bool* combined_is_animating_scale,
@@ -987,11 +1028,12 @@ static inline void CalculateAnimationContentsScale(
if (!layer_is_animating_scale) {
gfx::Vector2dF layer_transform_scales =
MathUtil::ComputeTransform2dScaleComponents(layer->transform(), 0.f);
- *combined_maximum_animation_contents_scale =
- ancestor_maximum_animation_contents_scale *
+ float max_layer_scale =
std::max(layer_transform_scales.x(), layer_transform_scales.y());
+ *combined_maximum_animation_contents_scale =
+ ancestor_maximum_animation_contents_scale * max_layer_scale;
*combined_starting_animation_contents_scale =
- *combined_maximum_animation_contents_scale;
+ ancestor_starting_animation_contents_scale * max_layer_scale;
return;
}
@@ -1016,9 +1058,8 @@ static inline void CalculateAnimationContentsScale(
layer_start_animated_scale * max_scale_xy;
}
-template <typename LayerTypePtr>
static inline void MarkLayerWithRenderSurfaceLayerListId(
- LayerTypePtr layer,
+ LayerImpl* layer,
int current_render_surface_layer_list_id) {
layer->draw_properties().last_drawn_render_surface_layer_list_id =
current_render_surface_layer_list_id;
@@ -1026,9 +1067,8 @@ static inline void MarkLayerWithRenderSurfaceLayerListId(
!!current_render_surface_layer_list_id);
}
-template <typename LayerTypePtr>
static inline void MarkMasksWithRenderSurfaceLayerListId(
- LayerTypePtr layer,
+ LayerImpl* layer,
int current_render_surface_layer_list_id) {
if (layer->mask_layer()) {
MarkLayerWithRenderSurfaceLayerListId(layer->mask_layer(),
@@ -1040,13 +1080,11 @@ static inline void MarkMasksWithRenderSurfaceLayerListId(
}
}
-template <typename LayerListType>
static inline void MarkLayerListWithRenderSurfaceLayerListId(
- LayerListType* layer_list,
+ LayerImplList* layer_list,
int current_render_surface_layer_list_id) {
- for (typename LayerListType::iterator it = layer_list->begin();
- it != layer_list->end();
- ++it) {
+ for (LayerImplList::iterator it = layer_list->begin();
+ it != layer_list->end(); ++it) {
MarkLayerWithRenderSurfaceLayerListId(*it,
current_render_surface_layer_list_id);
MarkMasksWithRenderSurfaceLayerListId(*it,
@@ -1054,10 +1092,9 @@ static inline void MarkLayerListWithRenderSurfaceLayerListId(
}
}
-template <typename LayerType>
static inline void RemoveSurfaceForEarlyExit(
- LayerType* layer_to_remove,
- typename LayerType::RenderSurfaceListType* render_surface_layer_list) {
+ LayerImpl* layer_to_remove,
+ LayerImplList* render_surface_layer_list) {
DCHECK(layer_to_remove->render_surface());
// Technically, we know that the layer we want to remove should be
// at the back of the render_surface_layer_list. However, we have had
@@ -1136,8 +1173,12 @@ static void PreCalculateMetaInformationInternal(
PreCalculateMetaInformationRecursiveData* recursive_data) {
ValidateRenderSurface(layer);
+ if (!IsMetaInformationRecomputationNeeded(layer)) {
+ DCHECK(IsRootLayer(layer));
+ return;
+ }
+
layer->set_sorted_for_recursion(false);
- layer->draw_properties().has_child_with_a_scroll_parent = false;
layer->set_layer_or_descendant_is_drawn(false);
layer->set_visited(false);
@@ -1147,26 +1188,14 @@ static void PreCalculateMetaInformationInternal(
return;
}
- if (!IsMetaInformationRecomputationNeeded(layer)) {
- DCHECK(IsRootLayer(layer));
- return;
- }
-
if (layer->clip_parent())
recursive_data->num_unclipped_descendants++;
- layer->set_num_children_with_scroll_parent(0);
for (size_t i = 0; i < layer->children().size(); ++i) {
Layer* child_layer = layer->child_at(i);
PreCalculateMetaInformationRecursiveData data_for_child;
PreCalculateMetaInformationInternal(child_layer, &data_for_child);
-
- if (child_layer->scroll_parent()) {
- layer->draw_properties().has_child_with_a_scroll_parent = true;
- layer->set_num_children_with_scroll_parent(
- layer->num_children_with_scroll_parent() + 1);
- }
recursive_data->Merge(data_for_child);
}
@@ -1183,16 +1212,10 @@ static void PreCalculateMetaInformationInternal(
layer->have_wheel_event_handlers())
recursive_data->num_layer_or_descendants_with_input_handler++;
- layer->draw_properties().num_unclipped_descendants =
- recursive_data->num_unclipped_descendants;
- layer->draw_properties().layer_or_descendant_has_copy_request =
- (recursive_data->num_layer_or_descendants_with_copy_request != 0);
- layer->draw_properties().layer_or_descendant_has_input_handler =
- (recursive_data->num_layer_or_descendants_with_input_handler != 0);
- layer->set_num_layer_or_descandant_with_copy_request(
+ layer->set_num_unclipped_descendants(
+ recursive_data->num_unclipped_descendants);
+ layer->set_num_layer_or_descendant_with_copy_request(
recursive_data->num_layer_or_descendants_with_copy_request);
- layer->set_num_layer_or_descandant_with_input_handler(
- recursive_data->num_layer_or_descendants_with_input_handler);
if (IsRootLayer(layer))
layer->layer_tree_host()->SetNeedsMetaInfoRecomputation(false);
@@ -1243,10 +1266,12 @@ static void PreCalculateMetaInformationInternal(
layer->draw_properties().num_unclipped_descendants =
recursive_data->num_unclipped_descendants;
- layer->draw_properties().layer_or_descendant_has_copy_request =
- (recursive_data->num_layer_or_descendants_with_copy_request != 0);
- layer->draw_properties().layer_or_descendant_has_input_handler =
- (recursive_data->num_layer_or_descendants_with_input_handler != 0);
+ layer->set_layer_or_descendant_has_input_handler(
+ (recursive_data->num_layer_or_descendants_with_input_handler != 0));
+ // TODO(enne): this should be synced from the main thread, so is only
+ // for tests constructing layers on the compositor thread.
+ layer->set_num_layer_or_descendant_with_copy_request(
+ recursive_data->num_layer_or_descendants_with_copy_request);
}
void LayerTreeHostCommon::PreCalculateMetaInformation(Layer* root_layer) {
@@ -1267,20 +1292,18 @@ void LayerTreeHostCommon::PreCalculateMetaInformationForTesting(
PreCalculateMetaInformationInternal(root_layer, &recursive_data);
}
-template <typename LayerType>
struct SubtreeGlobals {
int max_texture_size;
float device_scale_factor;
float page_scale_factor;
- const LayerType* page_scale_layer;
+ const LayerImpl* page_scale_layer;
gfx::Vector2dF elastic_overscroll;
- const LayerType* elastic_overscroll_application_layer;
+ const LayerImpl* elastic_overscroll_application_layer;
bool can_adjust_raster_scales;
bool can_render_to_separate_surface;
bool layers_always_allowed_lcd_text;
};
-template<typename LayerType>
struct DataForRecursion {
// The accumulated sequence of transforms a layer will use to determine its
// own draw transform.
@@ -1297,7 +1320,7 @@ struct DataForRecursion {
// The ancestor that would be the container for any fixed-position / sticky
// layers.
- LayerType* fixed_container;
+ LayerImpl* fixed_container;
// This is the normal clip rect that is propagated from parent to child.
gfx::Rect clip_rect_in_target_space;
@@ -1313,22 +1336,25 @@ struct DataForRecursion {
gfx::Rect clip_rect_of_target_surface_in_target_space;
// The maximum amount by which this layer will be scaled during the lifetime
- // of currently running animations.
+ // of currently running animations, considering only scales at keyframes not
+ // including the starting keyframe of each animation.
float maximum_animation_contents_scale;
+ // The maximum amout by which this layer will be scaled during the lifetime of
+ // currently running animations, consdering only the starting scale of each
+ // animation.
+ float starting_animation_contents_scale;
+
bool ancestor_is_animating_scale;
bool ancestor_clips_subtree;
- typename LayerType::RenderSurfaceType*
- nearest_occlusion_immune_ancestor_surface;
bool in_subtree_of_page_scale_layer;
bool subtree_can_use_lcd_text;
bool subtree_is_visible_from_ancestor;
};
-template <typename LayerType>
-static LayerType* GetChildContainingLayer(const LayerType& parent,
- LayerType* layer) {
- for (LayerType* ancestor = layer; ancestor; ancestor = ancestor->parent()) {
+static LayerImpl* GetChildContainingLayer(const LayerImpl& parent,
+ LayerImpl* layer) {
+ for (LayerImpl* ancestor = layer; ancestor; ancestor = ancestor->parent()) {
if (ancestor->parent() == &parent)
return ancestor;
}
@@ -1336,10 +1362,9 @@ static LayerType* GetChildContainingLayer(const LayerType& parent,
return 0;
}
-template <typename LayerType>
-static void AddScrollParentChain(std::vector<LayerType*>* out,
- const LayerType& parent,
- LayerType* layer) {
+static void AddScrollParentChain(std::vector<LayerImpl*>* out,
+ const LayerImpl& parent,
+ LayerImpl* layer) {
// At a high level, this function walks up the chain of scroll parents
// recursively, and once we reach the end of the chain, we add the child
// of |parent| containing each scroll ancestor as we unwind. The result is
@@ -1367,11 +1392,11 @@ static void AddScrollParentChain(std::vector<LayerType*>* out,
// So our first task at this step of the recursion is to determine the layer
// that we will potentionally add to the list. That is, the child of parent
// containing |layer|.
- LayerType* child = GetChildContainingLayer(parent, layer);
+ LayerImpl* child = GetChildContainingLayer(parent, layer);
if (child->sorted_for_recursion())
return;
- if (LayerType* scroll_parent = child->scroll_parent())
+ if (LayerImpl* scroll_parent = child->scroll_parent())
AddScrollParentChain(out, parent, scroll_parent);
out->push_back(child);
@@ -1379,13 +1404,12 @@ static void AddScrollParentChain(std::vector<LayerType*>* out,
child->set_sorted_for_recursion(sorted_for_recursion);
}
-template <typename LayerType>
-static bool SortChildrenForRecursion(std::vector<LayerType*>* out,
- const LayerType& parent) {
+static bool SortChildrenForRecursion(std::vector<LayerImpl*>* out,
+ const LayerImpl& parent) {
out->reserve(parent.children().size());
bool order_changed = false;
for (size_t i = 0; i < parent.children().size(); ++i) {
- LayerType* current =
+ LayerImpl* current =
LayerTreeHostCommon::get_layer_as_raw_ptr(parent.children(), i);
if (current->sorted_for_recursion()) {
@@ -1400,69 +1424,13 @@ static bool SortChildrenForRecursion(std::vector<LayerType*>* out,
return order_changed;
}
-template <typename LayerType>
-static void GetNewDescendantsStartIndexAndCount(LayerType* layer,
- size_t* start_index,
- size_t* count) {
- *start_index = layer->draw_properties().index_of_first_descendants_addition;
- *count = layer->draw_properties().num_descendants_added;
-}
-
-template <typename LayerType>
-static void GetNewRenderSurfacesStartIndexAndCount(LayerType* layer,
- size_t* start_index,
- size_t* count) {
- *start_index = layer->draw_properties()
- .index_of_first_render_surface_layer_list_addition;
- *count = layer->draw_properties().num_render_surfaces_added;
-}
-
-// We need to extract a list from the the two flavors of RenderSurfaceListType
-// for use in the sorting function below.
-static LayerList* GetLayerListForSorting(RenderSurfaceLayerList* rsll) {
- return &rsll->AsLayerList();
-}
-
-static LayerImplList* GetLayerListForSorting(LayerImplList* layer_list) {
- return layer_list;
-}
-
-template <typename LayerType, typename GetIndexAndCountType>
-static void SortLayerListContributions(
- const LayerType& parent,
- typename LayerType::LayerListType* unsorted,
- size_t start_index_for_all_contributions,
- GetIndexAndCountType get_index_and_count) {
- typename LayerType::LayerListType buffer;
- for (size_t i = 0; i < parent.children().size(); ++i) {
- LayerType* child =
- LayerTreeHostCommon::get_layer_as_raw_ptr(parent.children(), i);
-
- size_t start_index = 0;
- size_t count = 0;
- get_index_and_count(child, &start_index, &count);
- for (size_t j = start_index; j < start_index + count; ++j)
- buffer.push_back(unsorted->at(j));
- }
-
- DCHECK_EQ(buffer.size(),
- unsorted->size() - start_index_for_all_contributions);
-
- for (size_t i = 0; i < buffer.size(); ++i)
- (*unsorted)[i + start_index_for_all_contributions] = buffer[i];
-}
-
// Recursively walks the layer tree starting at the given node and computes all
// the necessary transformations, clip rects, render surfaces, etc.
-template <typename LayerType>
static void CalculateDrawPropertiesInternal(
- LayerType* layer,
- const SubtreeGlobals<LayerType>& globals,
- const DataForRecursion<LayerType>& data_from_ancestor,
- typename LayerType::RenderSurfaceListType* render_surface_layer_list,
- typename LayerType::LayerListType* layer_list,
- std::vector<AccumulatedSurfaceState<LayerType>>* accumulated_surface_state,
- int current_render_surface_layer_list_id) {
+ LayerImpl* layer,
+ const SubtreeGlobals& globals,
+ const DataForRecursion& data_from_ancestor,
+ std::vector<AccumulatedSurfaceState>* accumulated_surface_state) {
// This function computes the new matrix transformations recursively for this
// layer and all its descendants. It also computes the appropriate render
// surfaces.
@@ -1586,10 +1554,7 @@ static void CalculateDrawPropertiesInternal(
bool visited = true;
layer->set_visited(visited);
- DataForRecursion<LayerType> data_for_children;
- typename LayerType::RenderSurfaceType*
- nearest_occlusion_immune_ancestor_surface =
- data_from_ancestor.nearest_occlusion_immune_ancestor_surface;
+ DataForRecursion data_for_children;
data_for_children.in_subtree_of_page_scale_layer =
data_from_ancestor.in_subtree_of_page_scale_layer;
data_for_children.subtree_can_use_lcd_text =
@@ -1606,9 +1571,6 @@ static void CalculateDrawPropertiesInternal(
// The root layer cannot skip CalcDrawProperties.
if (!IsRootLayer(layer) && SubtreeShouldBeSkipped(layer, layer_is_drawn)) {
- if (layer->render_surface())
- layer->ClearRenderSurfaceLayerList();
- layer->draw_properties().render_target = nullptr;
return;
}
@@ -1623,14 +1585,14 @@ static void CalculateDrawPropertiesInternal(
// Update our clipping state. If we have a clip parent we will need to pull
// from the clip state cache rather than using the clip state passed from our
// immediate ancestor.
- UpdateClipRectsForClipChild<LayerType>(
- layer, &ancestor_clip_rect_in_target_space, &ancestor_clips_subtree);
+ UpdateClipRectsForClipChild(layer, &ancestor_clip_rect_in_target_space,
+ &ancestor_clips_subtree);
// As this function proceeds, these are the properties for the current
// layer that actually get computed. To avoid unnecessary copies
// (particularly for matrices), we do computations directly on these values
// when possible.
- DrawProperties<LayerType>& layer_draw_properties = layer->draw_properties();
+ DrawProperties& layer_draw_properties = layer->draw_properties();
gfx::Rect clip_rect_in_target_space;
bool layer_or_ancestor_clips_descendants = false;
@@ -1643,20 +1605,12 @@ static void CalculateDrawPropertiesInternal(
gfx::Rect clip_rect_of_target_surface_in_target_space;
float accumulated_draw_opacity = layer->opacity();
- bool animating_opacity_to_target = layer->OpacityIsAnimating();
- bool animating_opacity_to_screen = animating_opacity_to_target;
- if (layer->parent()) {
+ if (layer->parent())
accumulated_draw_opacity *= layer->parent()->draw_opacity();
- animating_opacity_to_target |= layer->parent()->draw_opacity_is_animating();
- animating_opacity_to_screen |=
- layer->parent()->screen_space_opacity_is_animating();
- }
- bool animating_transform_to_target = layer->TransformIsAnimating();
- bool animating_transform_to_screen = animating_transform_to_target;
+ bool animating_transform_to_screen =
+ layer->HasPotentiallyRunningTransformAnimation();
if (layer->parent()) {
- animating_transform_to_target |=
- layer->parent()->draw_transform_is_animating();
animating_transform_to_screen |=
layer->parent()->screen_space_transform_is_animating();
}
@@ -1681,7 +1635,7 @@ static void CalculateDrawPropertiesInternal(
}
gfx::Vector2dF effective_scroll_delta = GetEffectiveScrollDelta(layer);
- if (!animating_transform_to_target && layer->scrollable() &&
+ if (!animating_transform_to_screen && layer->scrollable() &&
combined_transform.IsScaleOrTranslation()) {
// Align the scrollable layer's position to screen space pixels to avoid
// blurriness. To avoid side-effects, do this only if the transform is
@@ -1715,6 +1669,7 @@ static void CalculateDrawPropertiesInternal(
CalculateAnimationContentsScale(
layer, data_from_ancestor.ancestor_is_animating_scale,
data_from_ancestor.maximum_animation_contents_scale,
+ data_from_ancestor.starting_animation_contents_scale,
data_from_ancestor.parent_matrix, combined_transform,
&combined_is_animating_scale,
&combined_maximum_animation_contents_scale,
@@ -1723,6 +1678,8 @@ static void CalculateDrawPropertiesInternal(
data_for_children.ancestor_is_animating_scale = combined_is_animating_scale;
data_for_children.maximum_animation_contents_scale =
combined_maximum_animation_contents_scale;
+ data_for_children.starting_animation_contents_scale =
+ combined_starting_animation_contents_scale;
// Compute the 2d scale components of the transform hierarchy up to the target
// surface. From there, we can decide on a contents scale for the layer.
@@ -1738,14 +1695,14 @@ static void CalculateDrawPropertiesInternal(
combined_maximum_animation_contents_scale,
combined_starting_animation_contents_scale);
- LayerType* mask_layer = layer->mask_layer();
+ LayerImpl* mask_layer = layer->mask_layer();
if (mask_layer) {
UpdateLayerScaleDrawProperties(mask_layer,
combined_maximum_animation_contents_scale,
combined_starting_animation_contents_scale);
}
- LayerType* replica_mask_layer =
+ LayerImpl* replica_mask_layer =
layer->replica_layer() ? layer->replica_layer()->mask_layer() : NULL;
if (replica_mask_layer) {
UpdateLayerScaleDrawProperties(replica_mask_layer,
@@ -1800,27 +1757,18 @@ static void CalculateDrawPropertiesInternal(
DCHECK(layer->render_surface());
// Check back-face visibility before continuing with this surface and its
// subtree
- if (!layer->double_sided() && TransformToParentIsKnown(layer) &&
+ if (!layer->double_sided() &&
IsSurfaceBackFaceVisible(layer, combined_transform)) {
- layer->ClearRenderSurfaceLayerList();
- layer->draw_properties().render_target = nullptr;
return;
}
- typename LayerType::RenderSurfaceType* render_surface =
- layer->render_surface();
- layer->ClearRenderSurfaceLayerList();
+ RenderSurfaceImpl* render_surface = layer->render_surface();
- layer_draw_properties.render_target = layer;
if (IsRootLayer(layer)) {
// The root layer's render surface size is predetermined and so the root
// layer can't directly support non-identity transforms. It should just
// forward top-level transforms to the rest of the tree.
data_for_children.parent_matrix = combined_transform;
-
- // The root surface does not contribute to any other surface, it has no
- // target.
- layer->render_surface()->set_contributes_to_drawn_surface(false);
} else {
// The owning layer's draw transform has a scale from content to layer
// space which we do not want; so here we use the combined_transform
@@ -1848,31 +1796,14 @@ static void CalculateDrawPropertiesInternal(
DCHECK(data_for_children.parent_matrix.IsIdentity());
data_for_children.parent_matrix.Scale(combined_transform_scales.x(),
combined_transform_scales.y());
-
- // Even if the |layer_is_drawn|, it only contributes to a drawn surface
- // when the |layer_is_visible|.
- layer->render_surface()->set_contributes_to_drawn_surface(
- layer_is_visible);
}
// The opacity value is moved from the layer to its surface, so that the
// entire subtree properly inherits opacity.
render_surface->SetDrawOpacity(accumulated_draw_opacity);
- render_surface->SetDrawOpacityIsAnimating(animating_opacity_to_target);
- animating_opacity_to_target = false;
layer_draw_properties.opacity = 1.f;
- layer_draw_properties.blend_mode = SkXfermode::kSrcOver_Mode;
- layer_draw_properties.opacity_is_animating = animating_opacity_to_target;
- layer_draw_properties.screen_space_opacity_is_animating =
- animating_opacity_to_screen;
-
- render_surface->SetTargetSurfaceTransformsAreAnimating(
- animating_transform_to_target);
- render_surface->SetScreenSpaceTransformsAreAnimating(
- animating_transform_to_screen);
- animating_transform_to_target = false;
- layer_draw_properties.target_space_transform_is_animating =
- animating_transform_to_target;
+ DCHECK_EQ(layer->draw_blend_mode(), SkXfermode::kSrcOver_Mode);
+
layer_draw_properties.screen_space_transform_is_animating =
animating_transform_to_screen;
@@ -1886,9 +1817,8 @@ static void CalculateDrawPropertiesInternal(
data_for_children.full_hierarchy_matrix.FlattenTo2d();
if (layer->mask_layer()) {
- DrawProperties<LayerType>& mask_layer_draw_properties =
+ DrawProperties& mask_layer_draw_properties =
layer->mask_layer()->draw_properties();
- mask_layer_draw_properties.render_target = layer;
mask_layer_draw_properties.visible_layer_rect =
gfx::Rect(layer->bounds());
// Temporarily copy the draw transform of the mask's owning layer into the
@@ -1901,51 +1831,37 @@ static void CalculateDrawPropertiesInternal(
}
if (layer->replica_layer() && layer->replica_layer()->mask_layer()) {
- DrawProperties<LayerType>& replica_mask_draw_properties =
+ DrawProperties& replica_mask_draw_properties =
layer->replica_layer()->mask_layer()->draw_properties();
- replica_mask_draw_properties.render_target = layer;
replica_mask_draw_properties.visible_layer_rect =
gfx::Rect(layer->bounds());
replica_mask_draw_properties.target_space_transform =
layer_draw_properties.target_space_transform;
}
- // Ignore occlusion from outside the surface when surface contents need to
- // be fully drawn. Layers with copy-request need to be complete.
- // We could be smarter about layers with replica and exclude regions
- // where both layer and the replica are occluded, but this seems like an
- // overkill. The same is true for layers with filters that move pixels.
- // TODO(senorblanco): make this smarter for the SkImageFilter case (check
- // for pixel-moving filters)
- if (layer->HasCopyRequest() ||
- layer->has_replica() ||
- layer->filters().HasReferenceFilter() ||
- layer->filters().HasFilterThatMovesPixels()) {
- nearest_occlusion_immune_ancestor_surface = render_surface;
- }
- render_surface->SetNearestOcclusionImmuneAncestor(
- nearest_occlusion_immune_ancestor_surface);
-
layer_or_ancestor_clips_descendants = false;
bool subtree_is_clipped_by_surface_bounds = false;
- if (ancestor_clips_subtree) {
- // It may be the layer or the surface doing the clipping of the subtree,
- // but in either case, we'll be clipping to the projected clip rect of our
- // ancestor.
- gfx::Transform inverse_surface_draw_transform(
- gfx::Transform::kSkipInitialization);
- if (!render_surface->draw_transform().GetInverse(
- &inverse_surface_draw_transform)) {
- // TODO(shawnsingh): Either we need to handle uninvertible transforms
- // here, or DCHECK that the transform is invertible.
- }
+ // It may be the layer or the surface doing the clipping of the subtree,
+ // but in either case, we'll be clipping to the projected clip rect of our
+ // ancestor.
+ gfx::Transform inverse_surface_draw_transform(
+ gfx::Transform::kSkipInitialization);
+ if (!render_surface->draw_transform().GetInverse(
+ &inverse_surface_draw_transform)) {
+ // TODO(shawnsingh): Either we need to handle uninvertible transforms
+ // here, or DCHECK that the transform is invertible.
+ }
- gfx::Rect surface_clip_rect_in_target_space = gfx::IntersectRects(
- data_from_ancestor.clip_rect_of_target_surface_in_target_space,
+ gfx::Rect surface_clip_rect_in_target_space =
+ data_from_ancestor.clip_rect_of_target_surface_in_target_space;
+ if (ancestor_clips_subtree)
+ surface_clip_rect_in_target_space.Intersect(
ancestor_clip_rect_in_target_space);
- gfx::Rect projected_surface_rect = MathUtil::ProjectEnclosingClippedRect(
- inverse_surface_draw_transform, surface_clip_rect_in_target_space);
+ gfx::Rect projected_surface_rect = MathUtil::ProjectEnclosingClippedRect(
+ inverse_surface_draw_transform, surface_clip_rect_in_target_space);
+ clip_rect_of_target_surface_in_target_space = projected_surface_rect;
+ if (ancestor_clips_subtree) {
if (layer_draw_properties.num_unclipped_descendants > 0u) {
// If we have unclipped descendants, we cannot count on the render
// surface's bounds clipping our subtree: the unclipped descendants
@@ -1964,7 +1880,6 @@ static void CalculateDrawPropertiesInternal(
// expressed in the space where this surface draws, i.e. the same space
// as clip_rect_from_ancestor_in_ancestor_target_space.
render_surface->SetClipRect(ancestor_clip_rect_in_target_space);
- clip_rect_of_target_surface_in_target_space = projected_surface_rect;
subtree_is_clipped_by_surface_bounds = true;
}
}
@@ -1973,14 +1888,11 @@ static void CalculateDrawPropertiesInternal(
DCHECK(!layer->parent() || layer->parent()->render_target() ==
accumulated_surface_state->back().render_target);
- accumulated_surface_state->push_back(
- AccumulatedSurfaceState<LayerType>(layer));
+ accumulated_surface_state->push_back(AccumulatedSurfaceState(layer));
render_surface->SetIsClipped(subtree_is_clipped_by_surface_bounds);
if (!subtree_is_clipped_by_surface_bounds) {
render_surface->SetClipRect(gfx::Rect());
- clip_rect_of_target_surface_in_target_space =
- data_from_ancestor.clip_rect_of_target_surface_in_target_space;
}
// If the new render surface is drawn translucent or with a non-integral
@@ -1988,21 +1900,15 @@ static void CalculateDrawPropertiesInternal(
// cannot use LCD text.
data_for_children.subtree_can_use_lcd_text = subtree_can_use_lcd_text;
- render_surface_layer_list->push_back(layer);
} else {
DCHECK(layer->parent());
// Note: layer_draw_properties.target_space_transform is computed above,
// before this if-else statement.
- layer_draw_properties.target_space_transform_is_animating =
- animating_transform_to_target;
layer_draw_properties.screen_space_transform_is_animating =
animating_transform_to_screen;
layer_draw_properties.opacity = accumulated_draw_opacity;
- layer_draw_properties.blend_mode = layer->blend_mode();
- layer_draw_properties.opacity_is_animating = animating_opacity_to_target;
- layer_draw_properties.screen_space_opacity_is_animating =
- animating_opacity_to_screen;
+ DCHECK_EQ(layer->draw_blend_mode(), layer->blend_mode());
data_for_children.parent_matrix = combined_transform;
// Layers without render_surfaces directly inherit the ancestor's clip
@@ -2017,10 +1923,6 @@ static void CalculateDrawPropertiesInternal(
// clipping goes on between layers here.
clip_rect_of_target_surface_in_target_space =
data_from_ancestor.clip_rect_of_target_surface_in_target_space;
-
- // Layers that are not their own render_target will render into the target
- // of their nearest ancestor.
- layer_draw_properties.render_target = layer->parent()->render_target();
}
layer_draw_properties.can_use_lcd_text = layer_can_use_lcd_text;
@@ -2056,26 +1958,6 @@ static void CalculateDrawPropertiesInternal(
layer_draw_properties.clip_rect = rect_in_target_space;
}
- typename LayerType::LayerListType& descendants =
- (render_to_separate_surface ? layer->render_surface()->layer_list()
- : *layer_list);
-
- // Any layers that are appended after this point are in the layer's subtree
- // and should be included in the sorting process.
- size_t sorting_start_index = descendants.size();
-
- if (!LayerShouldBeSkipped(layer, layer_is_drawn)) {
- MarkLayerWithRenderSurfaceLayerListId(layer,
- current_render_surface_layer_list_id);
- descendants.push_back(layer);
- }
-
- // Any layers that are appended after this point may need to be sorted if we
- // visit the children out of order.
- size_t render_surface_layer_list_child_sorting_start_index =
- render_surface_layer_list->size();
- size_t layer_list_child_sorting_start_index = descendants.size();
-
if (!layer->children().empty()) {
if (layer == globals.elastic_overscroll_application_layer) {
data_for_children.parent_matrix.Translate(
@@ -2101,58 +1983,26 @@ static void CalculateDrawPropertiesInternal(
clip_rect_of_target_surface_in_target_space;
data_for_children.ancestor_clips_subtree =
layer_or_ancestor_clips_descendants;
- data_for_children.nearest_occlusion_immune_ancestor_surface =
- nearest_occlusion_immune_ancestor_surface;
data_for_children.subtree_is_visible_from_ancestor = layer_is_drawn;
}
- std::vector<LayerType*> sorted_children;
- bool child_order_changed = false;
+ std::vector<LayerImpl*> sorted_children;
if (layer_draw_properties.has_child_with_a_scroll_parent)
- child_order_changed = SortChildrenForRecursion(&sorted_children, *layer);
+ SortChildrenForRecursion(&sorted_children, *layer);
for (size_t i = 0; i < layer->children().size(); ++i) {
// If one of layer's children has a scroll parent, then we may have to
// visit the children out of order. The new order is stored in
// sorted_children. Otherwise, we'll grab the child directly from the
// layer's list of children.
- LayerType* child =
+
+ LayerImpl* child =
layer_draw_properties.has_child_with_a_scroll_parent
? sorted_children[i]
: LayerTreeHostCommon::get_layer_as_raw_ptr(layer->children(), i);
- child->draw_properties().index_of_first_descendants_addition =
- descendants.size();
- child->draw_properties().index_of_first_render_surface_layer_list_addition =
- render_surface_layer_list->size();
-
- CalculateDrawPropertiesInternal<LayerType>(
- child,
- globals,
- data_for_children,
- render_surface_layer_list,
- &descendants,
- accumulated_surface_state,
- current_render_surface_layer_list_id);
- // If the child is its own render target, then it has a render surface.
- if (child->render_target() == child &&
- !child->render_surface()->layer_list().empty() &&
- !child->render_surface()->content_rect().IsEmpty()) {
- // This child will contribute its render surface, which means
- // we need to mark just the mask layer (and replica mask layer)
- // with the id.
- MarkMasksWithRenderSurfaceLayerListId(
- child, current_render_surface_layer_list_id);
- descendants.push_back(child);
- }
-
- child->draw_properties().num_descendants_added =
- descendants.size() -
- child->draw_properties().index_of_first_descendants_addition;
- child->draw_properties().num_render_surfaces_added =
- render_surface_layer_list->size() -
- child->draw_properties()
- .index_of_first_render_surface_layer_list_addition;
+ CalculateDrawPropertiesInternal(child, globals, data_for_children,
+ accumulated_surface_state);
if (child->layer_or_descendant_is_drawn()) {
bool layer_or_descendant_is_drawn = true;
@@ -2160,21 +2010,6 @@ static void CalculateDrawPropertiesInternal(
}
}
- // Add the unsorted layer list contributions, if necessary.
- if (child_order_changed) {
- SortLayerListContributions(
- *layer,
- GetLayerListForSorting(render_surface_layer_list),
- render_surface_layer_list_child_sorting_start_index,
- &GetNewRenderSurfacesStartIndexAndCount<LayerType>);
-
- SortLayerListContributions(
- *layer,
- &descendants,
- layer_list_child_sorting_start_index,
- &GetNewDescendantsStartIndexAndCount<LayerType>);
- }
-
// Compute the total drawable_content_rect for this subtree (the rect is in
// target surface space).
gfx::Rect local_drawable_content_rect_of_subtree =
@@ -2184,12 +2019,6 @@ static void CalculateDrawPropertiesInternal(
accumulated_surface_state->pop_back();
}
- if (render_to_separate_surface && !IsRootLayer(layer) &&
- layer->render_surface()->layer_list().empty()) {
- RemoveSurfaceForEarlyExit(layer, render_surface_layer_list);
- return;
- }
-
// Compute the layer's drawable content rect (the rect is in target surface
// space).
layer_draw_properties.drawable_content_rect = rect_in_target_space;
@@ -2214,15 +2043,12 @@ static void CalculateDrawPropertiesInternal(
layer->render_surface()->SetContentRect(
ancestor_clip_rect_in_target_space);
} else if (render_to_separate_surface) {
- typename LayerType::RenderSurfaceType* render_surface =
- layer->render_surface();
+ RenderSurfaceImpl* render_surface = layer->render_surface();
gfx::Rect clipped_content_rect = local_drawable_content_rect_of_subtree;
// Don't clip if the layer is reflected as the reflection shouldn't be
- // clipped. If the layer is animating, then the surface's transform to
- // its target is not known on the main thread, and we should not use it
- // to clip.
- if (!layer->replica_layer() && TransformToParentIsKnown(layer)) {
+ // clipped.
+ if (!layer->replica_layer()) {
// Note, it is correct to use data_from_ancestor.ancestor_clips_subtree
// here, because we are looking at this layer's render_surface, not the
// layer itself.
@@ -2242,11 +2068,6 @@ static void CalculateDrawPropertiesInternal(
clipped_content_rect.set_height(
std::min(clipped_content_rect.height(), globals.max_texture_size));
- if (clipped_content_rect.IsEmpty()) {
- RemoveSurfaceForEarlyExit(layer, render_surface_layer_list);
- return;
- }
-
// Layers having a non-default blend mode will blend with the content
// inside its parent's render target. This render target should be
// either root_for_isolated_group, or the root of the layer tree.
@@ -2259,6 +2080,10 @@ static void CalculateDrawPropertiesInternal(
render_surface->SetContentRect(clipped_content_rect);
+ if (clipped_content_rect.IsEmpty()) {
+ return;
+ }
+
// The owning layer's screen_space_transform has a scale from content to
// layer space which we need to undo and replace with a scale from the
// surface's subtree into layer space.
@@ -2304,28 +2129,14 @@ static void CalculateDrawPropertiesInternal(
SavePaintPropertiesLayer(layer);
- // If neither this layer nor any of its children were added, early out.
- if (sorting_start_index == descendants.size()) {
- DCHECK(!render_to_separate_surface || IsRootLayer(layer));
- return;
- }
-
- UpdateAccumulatedSurfaceState<LayerType>(
- layer, local_drawable_content_rect_of_subtree, accumulated_surface_state);
-
- if (layer->HasContributingDelegatedRenderPasses()) {
- layer->render_target()->render_surface()->
- AddContributingDelegatedRenderPassLayer(layer);
- }
+ UpdateAccumulatedSurfaceState(layer, local_drawable_content_rect_of_subtree,
+ accumulated_surface_state);
} // NOLINT(readability/fn_size)
-template <typename LayerType, typename RenderSurfaceLayerListType>
static void ProcessCalcDrawPropsInputs(
- const LayerTreeHostCommon::CalcDrawPropsInputs<LayerType,
- RenderSurfaceLayerListType>&
- inputs,
- SubtreeGlobals<LayerType>* globals,
- DataForRecursion<LayerType>* data_for_recursion) {
+ const LayerTreeHostCommon::CalcDrawPropsImplInputs& inputs,
+ SubtreeGlobals* globals,
+ DataForRecursion* data_for_recursion) {
DCHECK(inputs.root_layer);
DCHECK(IsRootLayer(inputs.root_layer));
DCHECK(inputs.render_surface_layer_list);
@@ -2369,9 +2180,9 @@ static void ProcessCalcDrawPropsInputs(
data_for_recursion->clip_rect_of_target_surface_in_target_space =
device_viewport_rect;
data_for_recursion->maximum_animation_contents_scale = 0.f;
+ data_for_recursion->starting_animation_contents_scale = 0.f;
data_for_recursion->ancestor_is_animating_scale = false;
data_for_recursion->ancestor_clips_subtree = true;
- data_for_recursion->nearest_occlusion_immune_ancestor_surface = NULL;
data_for_recursion->in_subtree_of_page_scale_layer = false;
data_for_recursion->subtree_can_use_lcd_text = inputs.can_use_lcd_text;
data_for_recursion->subtree_is_visible_from_ancestor = true;
@@ -2391,15 +2202,10 @@ void LayerTreeHostCommon::UpdateRenderSurface(
// will now be relative to this RenderSurface.
transform->MakeIdentity();
*draw_transform_is_axis_aligned = true;
- if (!layer->render_surface()) {
- layer->CreateRenderSurface();
- }
layer->SetHasRenderSurface(true);
return;
}
layer->SetHasRenderSurface(false);
- if (layer->render_surface())
- layer->ClearRenderSurface();
}
void LayerTreeHostCommon::UpdateRenderSurfaces(
@@ -2422,13 +2228,7 @@ void LayerTreeHostCommon::UpdateRenderSurfaces(
static bool ApproximatelyEqual(const gfx::Rect& r1, const gfx::Rect& r2) {
// TODO(vollick): This tolerance should be lower: crbug.com/471786
- static const int tolerance = 3;
-
- if (r1.IsEmpty())
- return std::min(r2.width(), r2.height()) < tolerance;
-
- if (r2.IsEmpty())
- return std::min(r1.width(), r1.height()) < tolerance;
+ static const int tolerance = 1;
return std::abs(r1.x() - r2.x()) <= tolerance &&
std::abs(r1.y() - r2.y()) <= tolerance &&
@@ -2458,44 +2258,108 @@ static bool ApproximatelyEqual(const gfx::Transform& a,
return true;
}
+void VerifyPropertyTreeValuesForSurface(RenderSurfaceImpl* render_surface,
+ PropertyTrees* property_trees) {
+ RenderSurfaceDrawProperties draw_properties;
+ ComputeSurfaceDrawPropertiesUsingPropertyTrees(render_surface, property_trees,
+ &draw_properties);
+
+ // content_rect has to be computed recursively, so is computed separately from
+ // other draw properties.
+ draw_properties.content_rect =
+ render_surface->content_rect_from_property_trees();
+
+ const bool render_surface_draw_transforms_match = ApproximatelyEqual(
+ render_surface->draw_transform(), draw_properties.draw_transform);
+ CHECK(render_surface_draw_transforms_match)
+ << "expected: " << render_surface->draw_transform().ToString()
+ << " actual: " << draw_properties.draw_transform.ToString();
+
+ const bool render_surface_screen_space_transform_match =
+ ApproximatelyEqual(render_surface->screen_space_transform(),
+ draw_properties.screen_space_transform);
+ CHECK(render_surface_screen_space_transform_match)
+ << "expected: " << render_surface->screen_space_transform().ToString()
+ << " actual: " << draw_properties.screen_space_transform.ToString();
+
+ const bool render_surface_replica_draw_transforms_match =
+ ApproximatelyEqual(render_surface->replica_draw_transform(),
+ draw_properties.replica_draw_transform);
+ CHECK(render_surface_replica_draw_transforms_match)
+ << "expected: " << render_surface->replica_draw_transform().ToString()
+ << " actual: " << draw_properties.replica_draw_transform.ToString();
+
+ const bool render_surface_replica_screen_space_transforms_match =
+ ApproximatelyEqual(render_surface->replica_screen_space_transform(),
+ draw_properties.replica_screen_space_transform);
+ CHECK(render_surface_replica_screen_space_transforms_match)
+ << "expected: "
+ << render_surface->replica_screen_space_transform().ToString()
+ << " actual: "
+ << draw_properties.replica_screen_space_transform.ToString();
+
+ CHECK_EQ(render_surface->is_clipped(), draw_properties.is_clipped);
+
+ const bool render_surface_clip_rects_match = ApproximatelyEqual(
+ render_surface->clip_rect(), draw_properties.clip_rect);
+ CHECK(render_surface_clip_rects_match)
+ << "expected: " << render_surface->clip_rect().ToString()
+ << " actual: " << draw_properties.clip_rect.ToString();
+
+ CHECK_EQ(render_surface->draw_opacity(), draw_properties.draw_opacity);
+
+ const bool render_surface_content_rects_match = ApproximatelyEqual(
+ render_surface->content_rect(), draw_properties.content_rect);
+ CHECK(render_surface_content_rects_match)
+ << "expected: " << render_surface->content_rect().ToString()
+ << " actual: " << draw_properties.content_rect.ToString();
+}
+
void VerifyPropertyTreeValuesForLayer(LayerImpl* current_layer,
PropertyTrees* property_trees,
bool layers_always_allowed_lcd_text,
bool can_use_lcd_text) {
- const bool visible_rects_match =
- ApproximatelyEqual(current_layer->visible_layer_rect(),
- current_layer->visible_rect_from_property_trees());
+ DrawProperties draw_properties;
+ ComputeLayerDrawPropertiesUsingPropertyTrees(
+ current_layer, property_trees, layers_always_allowed_lcd_text,
+ can_use_lcd_text, &draw_properties);
+
+ const bool visible_rects_match = ApproximatelyEqual(
+ current_layer->visible_layer_rect(), draw_properties.visible_layer_rect);
CHECK(visible_rects_match)
<< "expected: " << current_layer->visible_layer_rect().ToString()
- << " actual: "
- << current_layer->visible_rect_from_property_trees().ToString();
+ << " actual: " << draw_properties.visible_layer_rect.ToString();
- const bool draw_transforms_match =
- ApproximatelyEqual(current_layer->draw_transform(),
- DrawTransformFromPropertyTrees(
- current_layer, property_trees->transform_tree));
+ const bool draw_transforms_match = ApproximatelyEqual(
+ current_layer->draw_transform(), draw_properties.target_space_transform);
CHECK(draw_transforms_match)
<< "expected: " << current_layer->draw_transform().ToString()
- << " actual: "
- << DrawTransformFromPropertyTrees(
- current_layer, property_trees->transform_tree).ToString();
-
- const bool draw_opacities_match =
- current_layer->draw_opacity() ==
- DrawOpacityFromPropertyTrees(current_layer, property_trees->opacity_tree);
- CHECK(draw_opacities_match)
- << "expected: " << current_layer->draw_opacity()
- << " actual: " << DrawOpacityFromPropertyTrees(
- current_layer, property_trees->opacity_tree);
- const bool can_use_lcd_text_match =
- CanUseLcdTextFromPropertyTrees(
- current_layer, layers_always_allowed_lcd_text, can_use_lcd_text,
- property_trees) == current_layer->can_use_lcd_text();
- CHECK(can_use_lcd_text_match);
-}
-
-void VerifyPropertyTreeValues(
- LayerTreeHostCommon::CalcDrawPropsMainInputs* inputs) {
+ << " actual: " << draw_properties.target_space_transform.ToString();
+
+ CHECK_EQ(current_layer->draw_opacity(), draw_properties.opacity);
+ CHECK_EQ(current_layer->can_use_lcd_text(), draw_properties.can_use_lcd_text);
+ CHECK_EQ(current_layer->is_clipped(), draw_properties.is_clipped);
+ CHECK_EQ(current_layer->screen_space_transform_is_animating(),
+ draw_properties.screen_space_transform_is_animating);
+
+ const bool drawable_content_rects_match =
+ ApproximatelyEqual(current_layer->drawable_content_rect(),
+ draw_properties.drawable_content_rect);
+ CHECK(drawable_content_rects_match)
+ << "expected: " << current_layer->drawable_content_rect().ToString()
+ << " actual: " << draw_properties.drawable_content_rect.ToString();
+
+ const bool clip_rects_match =
+ ApproximatelyEqual(current_layer->clip_rect(), draw_properties.clip_rect);
+ CHECK(clip_rects_match) << "expected: "
+ << current_layer->clip_rect().ToString()
+ << " actual: "
+ << draw_properties.clip_rect.ToString();
+
+ CHECK_EQ(current_layer->draw_properties().maximum_animation_contents_scale,
+ draw_properties.maximum_animation_contents_scale);
+ CHECK_EQ(current_layer->draw_properties().starting_animation_contents_scale,
+ draw_properties.starting_animation_contents_scale);
}
void VerifyPropertyTreeValues(
@@ -2505,6 +2369,9 @@ void VerifyPropertyTreeValues(
end = LayerIterator::End(inputs->render_surface_layer_list);
it != end; ++it) {
LayerImpl* current_layer = *it;
+ if (it.represents_target_render_surface())
+ VerifyPropertyTreeValuesForSurface(current_layer->render_surface(),
+ inputs->property_trees);
if (!it.represents_itself() || !current_layer->DrawsContent())
continue;
VerifyPropertyTreeValuesForLayer(current_layer, inputs->property_trees,
@@ -2518,14 +2385,286 @@ enum PropertyTreeOption {
DONT_BUILD_PROPERTY_TREES
};
-template <typename LayerType, typename RenderSurfaceLayerListType>
-void CalculateDrawPropertiesAndVerify(LayerTreeHostCommon::CalcDrawPropsInputs<
- LayerType,
- RenderSurfaceLayerListType>* inputs,
- PropertyTreeOption property_tree_option) {
- typename LayerType::LayerListType dummy_layer_list;
- SubtreeGlobals<LayerType> globals;
- DataForRecursion<LayerType> data_for_recursion;
+void CalculateRenderTargetInternal(LayerImpl* layer,
+ bool subtree_visible_from_ancestor,
+ bool can_render_to_separate_surface) {
+ const bool layer_is_visible =
+ subtree_visible_from_ancestor && !layer->hide_layer_and_subtree();
+ const bool layer_is_drawn = layer_is_visible || layer->HasCopyRequest();
+
+ // The root layer cannot be skipped.
+ if (!IsRootLayer(layer) && SubtreeShouldBeSkipped(layer, layer_is_drawn)) {
+ layer->draw_properties().render_target = nullptr;
+ return;
+ }
+
+ bool render_to_separate_surface =
+ IsRootLayer(layer) ||
+ (can_render_to_separate_surface && layer->render_surface());
+
+ if (render_to_separate_surface) {
+ DCHECK(layer->render_surface());
+ layer->draw_properties().render_target = layer;
+
+ if (layer->mask_layer())
+ layer->mask_layer()->draw_properties().render_target = layer;
+
+ if (layer->replica_layer() && layer->replica_layer()->mask_layer())
+ layer->replica_layer()->mask_layer()->draw_properties().render_target =
+ layer;
+
+ } else {
+ DCHECK(layer->parent());
+ layer->draw_properties().render_target = layer->parent()->render_target();
+ }
+
+ for (size_t i = 0; i < layer->children().size(); ++i) {
+ CalculateRenderTargetInternal(
+ LayerTreeHostCommon::get_layer_as_raw_ptr(layer->children(), i),
+ layer_is_drawn, can_render_to_separate_surface);
+ }
+}
+
+void CalculateRenderSurfaceLayerListInternal(
+ LayerImpl* layer,
+ PropertyTrees* property_trees,
+ LayerImplList* render_surface_layer_list,
+ LayerImplList* descendants,
+ RenderSurfaceImpl* nearest_occlusion_immune_ancestor,
+ bool subtree_visible_from_ancestor,
+ const bool can_render_to_separate_surface,
+ const int current_render_surface_layer_list_id,
+ const bool verify_property_trees) {
+ // This calculates top level Render Surface Layer List, and Layer List for all
+ // Render Surfaces.
+
+ // |layer| is current layer.
+
+ // |render_surface_layer_list| is the top level RenderSurfaceLayerList.
+
+ // |descendants| is used to determine what's in current layer's render
+ // surface's layer list.
+
+ // |subtree_visible_from_ancestor| is set during recursion to affect current
+ // layer's subtree.
+
+ // |can_render_to_separate_surface| and |current_render_surface_layer_list_id|
+ // are settings that should stay the same during recursion.
+
+ // Layers that are marked as hidden will hide themselves and their subtree.
+ // Exception: Layers with copy requests, whether hidden or not, must be drawn
+ // anyway. In this case, we will inform their subtree they are visible to get
+ // the right results.
+ const bool layer_is_visible =
+ subtree_visible_from_ancestor && !layer->hide_layer_and_subtree();
+ const bool layer_is_drawn = layer_is_visible || layer->HasCopyRequest();
+
+ // The root layer cannot be skipped.
+ if (!IsRootLayer(layer) && SubtreeShouldBeSkipped(layer, layer_is_drawn)) {
+ if (layer->render_surface())
+ layer->ClearRenderSurfaceLayerList();
+ layer->draw_properties().render_target = nullptr;
+ return;
+ }
+
+ bool render_to_separate_surface =
+ IsRootLayer(layer) ||
+ (can_render_to_separate_surface && layer->render_surface());
+
+ if (render_to_separate_surface) {
+ DCHECK(layer->render_surface());
+ if (!layer->double_sided() &&
+ IsSurfaceBackFaceVisible(layer, layer->draw_transform())) {
+ layer->ClearRenderSurfaceLayerList();
+ layer->draw_properties().render_target = nullptr;
+ return;
+ }
+ if (IsRootLayer(layer)) {
+ // The root surface does not contribute to any other surface, it has no
+ // target.
+ layer->render_surface()->set_contributes_to_drawn_surface(false);
+ } else {
+ // Even if the |layer_is_drawn|, it only contributes to a drawn surface
+ // when the |layer_is_visible|.
+ layer->render_surface()->set_contributes_to_drawn_surface(
+ layer_is_visible);
+ }
+
+ // Ignore occlusion from outside the surface when surface contents need to
+ // be fully drawn. Layers with copy-request need to be complete.
+ // We could be smarter about layers with replica and exclude regions
+ // where both layer and the replica are occluded, but this seems like an
+ // overkill. The same is true for layers with filters that move pixels.
+ // TODO(senorblanco): make this smarter for the SkImageFilter case (check
+ // for pixel-moving filters)
+ if (layer->HasCopyRequest() || layer->has_replica() ||
+ layer->filters().HasReferenceFilter() ||
+ layer->filters().HasFilterThatMovesPixels()) {
+ nearest_occlusion_immune_ancestor = layer->render_surface();
+ }
+ layer->render_surface()->SetNearestOcclusionImmuneAncestor(
+ nearest_occlusion_immune_ancestor);
+ layer->ClearRenderSurfaceLayerList();
+
+ render_surface_layer_list->push_back(layer);
+
+ descendants = &(layer->render_surface()->layer_list());
+ }
+
+ size_t descendants_size = descendants->size();
+
+ bool layer_should_be_skipped = LayerShouldBeSkipped(layer, layer_is_drawn);
+ if (!layer_should_be_skipped) {
+ MarkLayerWithRenderSurfaceLayerListId(layer,
+ current_render_surface_layer_list_id);
+ descendants->push_back(layer);
+ }
+
+ // The render surface's content rect is the union of drawable content rects
+ // of the layers that draw into the surface. If the render surface is clipped,
+ // it is also intersected with the render's surface clip rect.
+ if (verify_property_trees) {
+ if (render_to_separate_surface) {
+ if (IsRootLayer(layer)) {
+ // The root layer's surface content rect is always the entire viewport.
+ gfx::Rect viewport =
+ gfx::ToEnclosingRect(property_trees->clip_tree.ViewportClip());
+ layer->render_surface()->SetAccumulatedContentRect(viewport);
+ } else {
+ // If the owning layer of a render surface draws content, the content
+ // rect of the render surface is initialized to the drawable content
+ // rect of the layer.
+ gfx::Rect content_rect = layer->DrawsContent()
+ ? layer->drawable_content_rect()
+ : gfx::Rect();
+ layer->render_surface()->SetAccumulatedContentRect(content_rect);
+ }
+ } else if (!layer_should_be_skipped &&
+ !IsRootLayer(layer->render_target())) {
+ // In this case, the layer's drawable content rect can expand the
+ // content rect of the render surface it is drawing into.
+ gfx::Rect surface_content_rect =
+ layer->render_target()->render_surface()->accumulated_content_rect();
+ surface_content_rect.Union(layer->drawable_content_rect());
+ layer->render_target()->render_surface()->SetAccumulatedContentRect(
+ surface_content_rect);
+ }
+ }
+
+ for (auto& child_layer : layer->children()) {
+ CalculateRenderSurfaceLayerListInternal(
+ child_layer, property_trees, render_surface_layer_list, descendants,
+ nearest_occlusion_immune_ancestor, layer_is_drawn,
+ can_render_to_separate_surface, current_render_surface_layer_list_id,
+ verify_property_trees);
+
+ // If the child is its own render target, then it has a render surface.
+ if (child_layer->render_target() == child_layer &&
+ !child_layer->render_surface()->layer_list().empty() &&
+ !child_layer->render_surface()->content_rect().IsEmpty()) {
+ // This child will contribute its render surface, which means
+ // we need to mark just the mask layer (and replica mask layer)
+ // with the id.
+ MarkMasksWithRenderSurfaceLayerListId(
+ child_layer, current_render_surface_layer_list_id);
+ descendants->push_back(child_layer);
+ }
+
+ if (child_layer->layer_or_descendant_is_drawn()) {
+ bool layer_or_descendant_is_drawn = true;
+ layer->set_layer_or_descendant_is_drawn(layer_or_descendant_is_drawn);
+ }
+ }
+
+ if (render_to_separate_surface && !IsRootLayer(layer) &&
+ layer->render_surface()->layer_list().empty()) {
+ RemoveSurfaceForEarlyExit(layer, render_surface_layer_list);
+ return;
+ }
+
+ if (verify_property_trees && render_to_separate_surface &&
+ !IsRootLayer(layer)) {
+ if (!layer->replica_layer() && layer->render_surface()->is_clipped()) {
+ // Here, we clip the render surface's content rect with its clip rect.
+ // As the clip rect of render surface is in the surface's target space,
+ // we first map the content rect into the target space, intersect it with
+ // clip rect and project back the result to the surface space.
+ gfx::Rect surface_content_rect =
+ layer->render_surface()->accumulated_content_rect();
+
+ if (!surface_content_rect.IsEmpty()) {
+ gfx::Rect surface_clip_rect = LayerTreeHostCommon::CalculateVisibleRect(
+ layer->render_surface()->clip_rect(), surface_content_rect,
+ layer->render_surface()->draw_transform());
+ surface_content_rect.Intersect(surface_clip_rect);
+ layer->render_surface()->SetAccumulatedContentRect(
+ surface_content_rect);
+ }
+ }
+ layer->render_surface()->SetContentRectFromPropertyTrees(
+ layer->render_surface()->accumulated_content_rect());
+ if (!IsRootLayer(layer->parent()->render_target())) {
+ // The surface's drawable content rect may expand the content rect
+ // of its target's surface(surface's target's surface).
+ gfx::Rect surface_target_rect = layer->parent()
+ ->render_target()
+ ->render_surface()
+ ->accumulated_content_rect();
+ surface_target_rect.Union(
+ gfx::ToEnclosedRect(layer->render_surface()->DrawableContentRect()));
+ layer->parent()
+ ->render_target()
+ ->render_surface()
+ ->SetAccumulatedContentRect(surface_target_rect);
+ }
+ }
+
+ if (verify_property_trees && IsRootLayer(layer))
+ layer->render_surface()->SetContentRectFromPropertyTrees(
+ layer->render_surface()->accumulated_content_rect());
+
+ if (render_to_separate_surface && !IsRootLayer(layer) &&
+ layer->render_surface()->content_rect().IsEmpty()) {
+ RemoveSurfaceForEarlyExit(layer, render_surface_layer_list);
+ return;
+ }
+
+ // If neither this layer nor any of its children were added, early out.
+ if (descendants_size == descendants->size()) {
+ DCHECK(!render_to_separate_surface || IsRootLayer(layer));
+ return;
+ }
+
+ if (layer->HasContributingDelegatedRenderPasses()) {
+ layer->render_target()
+ ->render_surface()
+ ->AddContributingDelegatedRenderPassLayer(layer);
+ }
+}
+
+void CalculateRenderTarget(
+ LayerTreeHostCommon::CalcDrawPropsImplInputs* inputs) {
+ CalculateRenderTargetInternal(inputs->root_layer, true,
+ inputs->can_render_to_separate_surface);
+}
+
+void CalculateRenderSurfaceLayerList(
+ LayerTreeHostCommon::CalcDrawPropsImplInputs* inputs) {
+ const bool subtree_visible_from_ancestor = true;
+ CalculateRenderSurfaceLayerListInternal(
+ inputs->root_layer, inputs->property_trees,
+ inputs->render_surface_layer_list, nullptr, nullptr,
+ subtree_visible_from_ancestor, inputs->can_render_to_separate_surface,
+ inputs->current_render_surface_layer_list_id,
+ inputs->verify_property_trees);
+}
+
+void CalculateDrawPropertiesAndVerify(
+ LayerTreeHostCommon::CalcDrawPropsImplInputs* inputs,
+ PropertyTreeOption property_tree_option) {
+ SubtreeGlobals globals;
+ DataForRecursion data_for_recursion;
+ inputs->render_surface_layer_list->clear();
ProcessCalcDrawPropsInputs(*inputs, &globals, &data_for_recursion);
UpdateMetaInformationSequenceNumber(inputs->root_layer);
@@ -2536,28 +2675,9 @@ void CalculateDrawPropertiesAndVerify(LayerTreeHostCommon::CalcDrawPropsInputs<
inputs->verify_property_trees &&
(property_tree_option == BUILD_PROPERTY_TREES_IF_NEEDED);
- if (should_measure_property_tree_performance) {
- TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("cc.debug.cdp-perf"),
- "LayerTreeHostCommon::CalculateDrawProperties");
- }
-
- std::vector<AccumulatedSurfaceState<LayerType>> accumulated_surface_state;
- CalculateDrawPropertiesInternal<LayerType>(
- inputs->root_layer, globals, data_for_recursion,
- inputs->render_surface_layer_list, &dummy_layer_list,
- &accumulated_surface_state, inputs->current_render_surface_layer_list_id);
-
- if (should_measure_property_tree_performance) {
- TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("cc.debug.cdp-perf"),
- "LayerTreeHostCommon::CalculateDrawProperties");
- }
-
if (inputs->verify_property_trees) {
- typename LayerType::LayerListType update_layer_list;
+ LayerImplList update_layer_list;
- // For testing purposes, sometimes property trees need to be built on the
- // compositor thread, so this can't just switch on Layer vs LayerImpl,
- // even though in practice only the main thread builds property trees.
switch (property_tree_option) {
case BUILD_PROPERTY_TREES_IF_NEEDED: {
// The translation from layer to property trees is an intermediate
@@ -2594,12 +2714,28 @@ void CalculateDrawPropertiesAndVerify(LayerTreeHostCommon::CalcDrawPropsInputs<
break;
}
}
+ }
- VerifyPropertyTreeValues(inputs);
+ if (should_measure_property_tree_performance) {
+ TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("cc.debug.cdp-perf"),
+ "LayerTreeHostCommon::CalculateDrawProperties");
}
- // The dummy layer list should not have been used.
- DCHECK_EQ(0u, dummy_layer_list.size());
+ std::vector<AccumulatedSurfaceState> accumulated_surface_state;
+ CalculateRenderTarget(inputs);
+ CalculateDrawPropertiesInternal(inputs->root_layer, globals,
+ data_for_recursion,
+ &accumulated_surface_state);
+ CalculateRenderSurfaceLayerList(inputs);
+
+ if (should_measure_property_tree_performance) {
+ TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("cc.debug.cdp-perf"),
+ "LayerTreeHostCommon::CalculateDrawProperties");
+ }
+
+ if (inputs->verify_property_trees)
+ VerifyPropertyTreeValues(inputs);
+
// A root layer render_surface should always exist after
// CalculateDrawProperties.
DCHECK(inputs->root_layer->render_surface());
@@ -2607,10 +2743,18 @@ void CalculateDrawPropertiesAndVerify(LayerTreeHostCommon::CalcDrawPropsInputs<
void LayerTreeHostCommon::CalculateDrawProperties(
CalcDrawPropsMainInputs* inputs) {
- UpdateRenderSurfaces(inputs->root_layer,
- inputs->can_render_to_separate_surface, gfx::Transform(),
- false);
- CalculateDrawPropertiesAndVerify(inputs, BUILD_PROPERTY_TREES_IF_NEEDED);
+ LayerList update_layer_list;
+ bool can_render_to_separate_surface = true;
+ UpdateRenderSurfaces(inputs->root_layer, can_render_to_separate_surface,
+ gfx::Transform(), false);
+ PropertyTrees* property_trees =
+ inputs->root_layer->layer_tree_host()->property_trees();
+ BuildPropertyTreesAndComputeVisibleRects(
+ inputs->root_layer, inputs->page_scale_layer,
+ inputs->inner_viewport_scroll_layer, inputs->outer_viewport_scroll_layer,
+ inputs->page_scale_factor, inputs->device_scale_factor,
+ gfx::Rect(inputs->device_viewport_size), inputs->device_transform,
+ property_trees, &update_layer_list);
}
void LayerTreeHostCommon::CalculateDrawProperties(
diff --git a/chromium/cc/trees/layer_tree_host_common.h b/chromium/cc/trees/layer_tree_host_common.h
index bf62111acbe..814833db812 100644
--- a/chromium/cc/trees/layer_tree_host_common.h
+++ b/chromium/cc/trees/layer_tree_host_common.h
@@ -31,89 +31,86 @@ class CC_EXPORT LayerTreeHostCommon {
const gfx::Rect& layer_bound_rect,
const gfx::Transform& transform);
- template <typename LayerType, typename RenderSurfaceLayerListType>
- struct CalcDrawPropsInputs {
+ struct CC_EXPORT CalcDrawPropsMainInputs {
public:
- CalcDrawPropsInputs(LayerType* root_layer,
- const gfx::Size& device_viewport_size,
- const gfx::Transform& device_transform,
- float device_scale_factor,
- float page_scale_factor,
- const LayerType* page_scale_layer,
- const LayerType* inner_viewport_scroll_layer,
- const LayerType* outer_viewport_scroll_layer,
- const gfx::Vector2dF& elastic_overscroll,
- const LayerType* elastic_overscroll_application_layer,
- int max_texture_size,
- bool can_use_lcd_text,
- bool layers_always_allowed_lcd_text,
- bool can_render_to_separate_surface,
- bool can_adjust_raster_scales,
- bool verify_property_trees,
- RenderSurfaceLayerListType* render_surface_layer_list,
- int current_render_surface_layer_list_id,
- PropertyTrees* property_trees)
- : root_layer(root_layer),
- device_viewport_size(device_viewport_size),
- device_transform(device_transform),
- device_scale_factor(device_scale_factor),
- page_scale_factor(page_scale_factor),
- page_scale_layer(page_scale_layer),
- inner_viewport_scroll_layer(inner_viewport_scroll_layer),
- outer_viewport_scroll_layer(outer_viewport_scroll_layer),
- elastic_overscroll(elastic_overscroll),
- elastic_overscroll_application_layer(
- elastic_overscroll_application_layer),
- max_texture_size(max_texture_size),
- can_use_lcd_text(can_use_lcd_text),
- layers_always_allowed_lcd_text(layers_always_allowed_lcd_text),
- can_render_to_separate_surface(can_render_to_separate_surface),
- can_adjust_raster_scales(can_adjust_raster_scales),
- verify_property_trees(verify_property_trees),
- render_surface_layer_list(render_surface_layer_list),
- current_render_surface_layer_list_id(
- current_render_surface_layer_list_id),
- property_trees(property_trees) {}
-
- LayerType* root_layer;
+ CalcDrawPropsMainInputs(Layer* root_layer,
+ const gfx::Size& device_viewport_size,
+ const gfx::Transform& device_transform,
+ float device_scale_factor,
+ float page_scale_factor,
+ const Layer* page_scale_layer,
+ const Layer* inner_viewport_scroll_layer,
+ const Layer* outer_viewport_scroll_layer);
+ CalcDrawPropsMainInputs(Layer* root_layer,
+ const gfx::Size& device_viewport_size,
+ const gfx::Transform& device_transform);
+ CalcDrawPropsMainInputs(Layer* root_layer,
+ const gfx::Size& device_viewport_size);
+ Layer* root_layer;
gfx::Size device_viewport_size;
gfx::Transform device_transform;
float device_scale_factor;
float page_scale_factor;
- const LayerType* page_scale_layer;
- const LayerType* inner_viewport_scroll_layer;
- const LayerType* outer_viewport_scroll_layer;
+ const Layer* page_scale_layer;
+ const Layer* inner_viewport_scroll_layer;
+ const Layer* outer_viewport_scroll_layer;
+ };
+
+ struct CC_EXPORT CalcDrawPropsImplInputs {
+ public:
+ CalcDrawPropsImplInputs(
+ LayerImpl* root_layer,
+ const gfx::Size& device_viewport_size,
+ const gfx::Transform& device_transform,
+ float device_scale_factor,
+ float page_scale_factor,
+ const LayerImpl* page_scale_layer,
+ const LayerImpl* inner_viewport_scroll_layer,
+ const LayerImpl* outer_viewport_scroll_layer,
+ const gfx::Vector2dF& elastic_overscroll,
+ const LayerImpl* elastic_overscroll_application_layer,
+ int max_texture_size,
+ bool can_use_lcd_text,
+ bool layers_always_allowed_lcd_text,
+ bool can_render_to_separate_surface,
+ bool can_adjust_raster_scales,
+ bool verify_property_trees,
+ LayerImplList* render_surface_layer_list,
+ int current_render_surface_layer_list_id,
+ PropertyTrees* property_trees);
+
+ LayerImpl* root_layer;
+ gfx::Size device_viewport_size;
+ gfx::Transform device_transform;
+ float device_scale_factor;
+ float page_scale_factor;
+ const LayerImpl* page_scale_layer;
+ const LayerImpl* inner_viewport_scroll_layer;
+ const LayerImpl* outer_viewport_scroll_layer;
gfx::Vector2dF elastic_overscroll;
- const LayerType* elastic_overscroll_application_layer;
+ const LayerImpl* elastic_overscroll_application_layer;
int max_texture_size;
bool can_use_lcd_text;
bool layers_always_allowed_lcd_text;
bool can_render_to_separate_surface;
bool can_adjust_raster_scales;
bool verify_property_trees;
- RenderSurfaceLayerListType* render_surface_layer_list;
+ LayerImplList* render_surface_layer_list;
int current_render_surface_layer_list_id;
PropertyTrees* property_trees;
};
- template <typename LayerType, typename RenderSurfaceLayerListType>
- struct CalcDrawPropsInputsForTesting
- : public CalcDrawPropsInputs<LayerType, RenderSurfaceLayerListType> {
- CalcDrawPropsInputsForTesting(
- LayerType* root_layer,
- const gfx::Size& device_viewport_size,
- const gfx::Transform& device_transform,
- RenderSurfaceLayerListType* render_surface_layer_list);
- CalcDrawPropsInputsForTesting(
- LayerType* root_layer,
- const gfx::Size& device_viewport_size,
- RenderSurfaceLayerListType* render_surface_layer_list);
+ struct CC_EXPORT CalcDrawPropsImplInputsForTesting
+ : public CalcDrawPropsImplInputs {
+ CalcDrawPropsImplInputsForTesting(LayerImpl* root_layer,
+ const gfx::Size& device_viewport_size,
+ const gfx::Transform& device_transform,
+ LayerImplList* render_surface_layer_list);
+ CalcDrawPropsImplInputsForTesting(LayerImpl* root_layer,
+ const gfx::Size& device_viewport_size,
+ LayerImplList* render_surface_layer_list);
};
- typedef CalcDrawPropsInputs<Layer, RenderSurfaceLayerList>
- CalcDrawPropsMainInputs;
- typedef CalcDrawPropsInputsForTesting<Layer, RenderSurfaceLayerList>
- CalcDrawPropsMainInputsForTesting;
static void UpdateRenderSurfaces(Layer* root_layer,
bool can_render_to_separate_surface,
const gfx::Transform& transform,
@@ -127,9 +124,6 @@ class CC_EXPORT LayerTreeHostCommon {
static void PreCalculateMetaInformationForTesting(LayerImpl* root_layer);
static void PreCalculateMetaInformationForTesting(Layer* root_layer);
- typedef CalcDrawPropsInputs<LayerImpl, LayerImplList> CalcDrawPropsImplInputs;
- typedef CalcDrawPropsInputsForTesting<LayerImpl, LayerImplList>
- CalcDrawPropsImplInputsForTesting;
static void CalculateDrawProperties(CalcDrawPropsImplInputs* inputs);
static void CalculateDrawProperties(
CalcDrawPropsImplInputsForTesting* inputs);
@@ -243,69 +237,6 @@ void LayerTreeHostCommon::CallFunctionForSubtree(LayerType* layer,
CC_EXPORT PropertyTrees* GetPropertyTrees(Layer* layer);
CC_EXPORT PropertyTrees* GetPropertyTrees(LayerImpl* layer);
-template <typename LayerType, typename RenderSurfaceLayerListType>
-LayerTreeHostCommon::CalcDrawPropsInputsForTesting<LayerType,
- RenderSurfaceLayerListType>::
- CalcDrawPropsInputsForTesting(
- LayerType* root_layer,
- const gfx::Size& device_viewport_size,
- const gfx::Transform& device_transform,
- RenderSurfaceLayerListType* render_surface_layer_list)
- : CalcDrawPropsInputs<LayerType, RenderSurfaceLayerListType>(
- root_layer,
- device_viewport_size,
- device_transform,
- 1.f,
- 1.f,
- NULL,
- NULL,
- NULL,
- gfx::Vector2dF(),
- NULL,
- std::numeric_limits<int>::max() / 2,
- false,
- false,
- true,
- false,
- true,
- render_surface_layer_list,
- 0,
- GetPropertyTrees(root_layer)) {
- DCHECK(root_layer);
- DCHECK(render_surface_layer_list);
-}
-
-template <typename LayerType, typename RenderSurfaceLayerListType>
-LayerTreeHostCommon::CalcDrawPropsInputsForTesting<LayerType,
- RenderSurfaceLayerListType>::
- CalcDrawPropsInputsForTesting(
- LayerType* root_layer,
- const gfx::Size& device_viewport_size,
- RenderSurfaceLayerListType* render_surface_layer_list)
- : CalcDrawPropsInputs<LayerType, RenderSurfaceLayerListType>(
- root_layer,
- device_viewport_size,
- gfx::Transform(),
- 1.f,
- 1.f,
- NULL,
- NULL,
- NULL,
- gfx::Vector2dF(),
- NULL,
- std::numeric_limits<int>::max() / 2,
- false,
- false,
- true,
- false,
- true,
- render_surface_layer_list,
- 0,
- GetPropertyTrees(root_layer)) {
- DCHECK(root_layer);
- DCHECK(render_surface_layer_list);
-}
-
} // namespace cc
#endif // CC_TREES_LAYER_TREE_HOST_COMMON_H_
diff --git a/chromium/cc/trees/layer_tree_host_common_perftest.cc b/chromium/cc/trees/layer_tree_host_common_perftest.cc
index 49831328d1e..f326ec25dff 100644
--- a/chromium/cc/trees/layer_tree_host_common_perftest.cc
+++ b/chromium/cc/trees/layer_tree_host_common_perftest.cc
@@ -116,7 +116,7 @@ class CalcDrawPropsTest : public LayerTreeHostCommonPerfTest {
active_tree->InnerViewportScrollLayer(),
active_tree->OuterViewportScrollLayer(),
active_tree->elastic_overscroll()->Current(active_tree->IsActiveTree()),
- active_tree->overscroll_elasticity_layer(), max_texture_size,
+ active_tree->OverscrollElasticityLayer(), max_texture_size,
host_impl->settings().can_use_lcd_text,
host_impl->settings().layers_always_allowed_lcd_text,
can_render_to_separate_surface,
@@ -156,7 +156,7 @@ class BspTreePerfTest : public CalcDrawPropsTest {
for (LayerImplList::iterator it = base_list.begin(); it != base_list.end();
++it) {
DrawPolygon* draw_polygon =
- new DrawPolygon(NULL, gfx::RectF((*it)->bounds()),
+ new DrawPolygon(NULL, gfx::RectF(gfx::SizeF((*it)->bounds())),
(*it)->draw_transform(), polygon_counter++);
polygon_list.push_back(scoped_ptr<DrawPolygon>(draw_polygon));
}
diff --git a/chromium/cc/trees/layer_tree_host_common_unittest.cc b/chromium/cc/trees/layer_tree_host_common_unittest.cc
index 43e2bb02123..8af5a0650a9 100644
--- a/chromium/cc/trees/layer_tree_host_common_unittest.cc
+++ b/chromium/cc/trees/layer_tree_host_common_unittest.cc
@@ -7,6 +7,7 @@
#include <algorithm>
#include <set>
+#include "cc/animation/keyframed_animation_curve.h"
#include "cc/animation/layer_animation_controller.h"
#include "cc/animation/transform_operations.h"
#include "cc/base/math_util.h"
@@ -15,7 +16,6 @@
#include "cc/layers/layer_client.h"
#include "cc/layers/layer_impl.h"
#include "cc/layers/layer_iterator.h"
-#include "cc/layers/render_surface.h"
#include "cc/layers/render_surface_impl.h"
#include "cc/output/copy_output_request.h"
#include "cc/output/copy_output_result.h"
@@ -24,11 +24,13 @@
#include "cc/test/fake_impl_proxy.h"
#include "cc/test/fake_layer_tree_host.h"
#include "cc/test/fake_layer_tree_host_impl.h"
+#include "cc/test/fake_output_surface.h"
#include "cc/test/fake_picture_layer.h"
#include "cc/test/fake_picture_layer_impl.h"
#include "cc/test/geometry_test_utils.h"
#include "cc/test/layer_tree_host_common_test.h"
#include "cc/test/test_task_graph_runner.h"
+#include "cc/trees/draw_property_utils.h"
#include "cc/trees/layer_tree_impl.h"
#include "cc/trees/proxy.h"
#include "cc/trees/single_thread_proxy.h"
@@ -68,17 +70,9 @@ class MockContentLayerClient : public ContentLayerClient {
return nullptr;
}
bool FillsBoundsCompletely() const override { return false; }
+ size_t GetApproximateUnsharedMemoryUsage() const override { return 0; }
};
-scoped_refptr<FakePictureLayer> CreateDrawablePictureLayer(
- const LayerSettings& settings,
- ContentLayerClient* delegate) {
- scoped_refptr<FakePictureLayer> to_return =
- FakePictureLayer::Create(settings, delegate);
- to_return->SetIsDrawable(true);
- return to_return;
-}
-
#define EXPECT_CONTENTS_SCALE_EQ(expected, layer) \
do { \
EXPECT_FLOAT_EQ(expected, layer->contents_scale_x()); \
@@ -152,43 +146,27 @@ TEST_F(LayerTreeHostCommonTest, TransformsForNoOpLayer) {
}
TEST_F(LayerTreeHostCommonTest, DoNotSkipLayersWithHandlers) {
- scoped_refptr<Layer> parent = Layer::Create(layer_settings());
- scoped_refptr<Layer> child = Layer::Create(layer_settings());
- scoped_refptr<Layer> grand_child = Layer::Create(layer_settings());
- parent->AddChild(child);
- child->AddChild(grand_child);
-
- host()->SetRootLayer(parent);
+ LayerImpl* parent = root_layer();
+ LayerImpl* child = AddChild<LayerImpl>(parent);
+ LayerImpl* grand_child = AddChild<LayerImpl>(child);
gfx::Transform identity_matrix;
- SetLayerPropertiesForTesting(parent.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(100, 100),
- true,
- false);
- SetLayerPropertiesForTesting(child.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(10, 10),
- gfx::Size(100, 100),
- true,
- false);
+ SetLayerPropertiesForTesting(parent, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(100, 100), true, false,
+ true);
+ SetLayerPropertiesForTesting(child, identity_matrix, gfx::Point3F(),
+ gfx::PointF(10, 10), gfx::Size(100, 100), true,
+ false, false);
// This would have previously caused us to skip our subtree, but this would be
// wrong; we need up-to-date draw properties to do hit testing on the layers
// with handlers.
child->SetOpacity(0.f);
- SetLayerPropertiesForTesting(grand_child.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(10, 10),
- gfx::Size(100, 100),
- true,
- false);
+ SetLayerPropertiesForTesting(grand_child, identity_matrix, gfx::Point3F(),
+ gfx::PointF(10, 10), gfx::Size(100, 100), true,
+ false, false);
grand_child->SetTouchEventHandlerRegion(gfx::Rect(0, 0, 100, 100));
- ExecuteCalculateDrawProperties(parent.get());
+ ExecuteCalculateDrawProperties(parent);
// Check that we've computed draw properties for the subtree rooted at
// |child|.
@@ -201,113 +179,96 @@ TEST_F(LayerTreeHostCommonTest, TransformsForSingleLayer) {
scoped_refptr<Layer> layer = Layer::Create(layer_settings());
scoped_refptr<Layer> root = Layer::Create(layer_settings());
- SetLayerPropertiesForTesting(root.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(1, 2),
- true,
- false);
+ SetLayerPropertiesForTesting(root.get(), identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(1, 2), true, false);
root->AddChild(layer);
host()->SetRootLayer(root);
+ TransformTree& tree = host()->property_trees()->transform_tree;
+
// Case 2: Setting the bounds of the layer should not affect either the draw
// transform or the screenspace transform.
gfx::Transform translation_to_center;
translation_to_center.Translate(5.0, 6.0);
- SetLayerPropertiesForTesting(layer.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(10, 12),
- true,
- false);
+ SetLayerPropertiesForTesting(layer.get(), identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(10, 12), true, false);
ExecuteCalculateDrawProperties(root.get());
- EXPECT_TRANSFORMATION_MATRIX_EQ(identity_matrix, layer->draw_transform());
- EXPECT_TRANSFORMATION_MATRIX_EQ(identity_matrix,
- layer->screen_space_transform());
+ EXPECT_TRANSFORMATION_MATRIX_EQ(
+ identity_matrix, DrawTransformFromPropertyTrees(layer.get(), tree));
+ EXPECT_TRANSFORMATION_MATRIX_EQ(
+ identity_matrix,
+ ScreenSpaceTransformFromPropertyTrees(layer.get(), tree));
// Case 3: The anchor point by itself (without a layer transform) should have
// no effect on the transforms.
- SetLayerPropertiesForTesting(layer.get(),
- identity_matrix,
- gfx::Point3F(2.5f, 3.0f, 0.f),
- gfx::PointF(),
- gfx::Size(10, 12),
- true,
- false);
+ SetLayerPropertiesForTesting(layer.get(), identity_matrix,
+ gfx::Point3F(2.5f, 3.0f, 0.f), gfx::PointF(),
+ gfx::Size(10, 12), true, false);
ExecuteCalculateDrawProperties(root.get());
- EXPECT_TRANSFORMATION_MATRIX_EQ(identity_matrix, layer->draw_transform());
- EXPECT_TRANSFORMATION_MATRIX_EQ(identity_matrix,
- layer->screen_space_transform());
+ EXPECT_TRANSFORMATION_MATRIX_EQ(
+ identity_matrix, DrawTransformFromPropertyTrees(layer.get(), tree));
+ EXPECT_TRANSFORMATION_MATRIX_EQ(
+ identity_matrix,
+ ScreenSpaceTransformFromPropertyTrees(layer.get(), tree));
// Case 4: A change in actual position affects both the draw transform and
// screen space transform.
gfx::Transform position_transform;
position_transform.Translate(0.f, 1.2f);
- SetLayerPropertiesForTesting(layer.get(),
- identity_matrix,
- gfx::Point3F(2.5f, 3.0f, 0.f),
- gfx::PointF(0.f, 1.2f),
- gfx::Size(10, 12),
- true,
- false);
+ SetLayerPropertiesForTesting(
+ layer.get(), identity_matrix, gfx::Point3F(2.5f, 3.0f, 0.f),
+ gfx::PointF(0.f, 1.2f), gfx::Size(10, 12), true, false);
ExecuteCalculateDrawProperties(root.get());
- EXPECT_TRANSFORMATION_MATRIX_EQ(position_transform, layer->draw_transform());
- EXPECT_TRANSFORMATION_MATRIX_EQ(position_transform,
- layer->screen_space_transform());
+ EXPECT_TRANSFORMATION_MATRIX_EQ(
+ position_transform, DrawTransformFromPropertyTrees(layer.get(), tree));
+ EXPECT_TRANSFORMATION_MATRIX_EQ(
+ position_transform,
+ ScreenSpaceTransformFromPropertyTrees(layer.get(), tree));
// Case 5: In the correct sequence of transforms, the layer transform should
// pre-multiply the translation_to_center. This is easily tested by using a
// scale transform, because scale and translation are not commutative.
gfx::Transform layer_transform;
layer_transform.Scale3d(2.0, 2.0, 1.0);
- SetLayerPropertiesForTesting(layer.get(),
- layer_transform,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(10, 12),
- true,
- false);
+ SetLayerPropertiesForTesting(layer.get(), layer_transform, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(10, 12), true, false);
ExecuteCalculateDrawProperties(root.get());
- EXPECT_TRANSFORMATION_MATRIX_EQ(layer_transform, layer->draw_transform());
- EXPECT_TRANSFORMATION_MATRIX_EQ(layer_transform,
- layer->screen_space_transform());
+ EXPECT_TRANSFORMATION_MATRIX_EQ(
+ layer_transform, DrawTransformFromPropertyTrees(layer.get(), tree));
+ EXPECT_TRANSFORMATION_MATRIX_EQ(
+ layer_transform,
+ ScreenSpaceTransformFromPropertyTrees(layer.get(), tree));
// Case 6: The layer transform should occur with respect to the anchor point.
gfx::Transform translation_to_anchor;
translation_to_anchor.Translate(5.0, 0.0);
gfx::Transform expected_result =
translation_to_anchor * layer_transform * Inverse(translation_to_anchor);
- SetLayerPropertiesForTesting(layer.get(),
- layer_transform,
- gfx::Point3F(5.0f, 0.f, 0.f),
- gfx::PointF(),
- gfx::Size(10, 12),
- true,
- false);
+ SetLayerPropertiesForTesting(layer.get(), layer_transform,
+ gfx::Point3F(5.0f, 0.f, 0.f), gfx::PointF(),
+ gfx::Size(10, 12), true, false);
ExecuteCalculateDrawProperties(root.get());
- EXPECT_TRANSFORMATION_MATRIX_EQ(expected_result, layer->draw_transform());
- EXPECT_TRANSFORMATION_MATRIX_EQ(expected_result,
- layer->screen_space_transform());
+ EXPECT_TRANSFORMATION_MATRIX_EQ(
+ expected_result, DrawTransformFromPropertyTrees(layer.get(), tree));
+ EXPECT_TRANSFORMATION_MATRIX_EQ(
+ expected_result,
+ ScreenSpaceTransformFromPropertyTrees(layer.get(), tree));
// Case 7: Verify that position pre-multiplies the layer transform. The
// current implementation of CalculateDrawProperties does this implicitly, but
// it is still worth testing to detect accidental regressions.
expected_result = position_transform * translation_to_anchor *
layer_transform * Inverse(translation_to_anchor);
- SetLayerPropertiesForTesting(layer.get(),
- layer_transform,
- gfx::Point3F(5.0f, 0.f, 0.f),
- gfx::PointF(0.f, 1.2f),
- gfx::Size(10, 12),
- true,
- false);
+ SetLayerPropertiesForTesting(
+ layer.get(), layer_transform, gfx::Point3F(5.0f, 0.f, 0.f),
+ gfx::PointF(0.f, 1.2f), gfx::Size(10, 12), true, false);
ExecuteCalculateDrawProperties(root.get());
- EXPECT_TRANSFORMATION_MATRIX_EQ(expected_result, layer->draw_transform());
- EXPECT_TRANSFORMATION_MATRIX_EQ(expected_result,
- layer->screen_space_transform());
+ EXPECT_TRANSFORMATION_MATRIX_EQ(
+ expected_result, DrawTransformFromPropertyTrees(layer.get(), tree));
+ EXPECT_TRANSFORMATION_MATRIX_EQ(
+ expected_result,
+ ScreenSpaceTransformFromPropertyTrees(layer.get(), tree));
}
TEST_F(LayerTreeHostCommonTest, TransformsAboutScrollOffset) {
@@ -413,78 +374,57 @@ TEST_F(LayerTreeHostCommonTest, TransformsForSimpleHierarchy) {
host()->SetRootLayer(root);
// One-time setup of root layer
- SetLayerPropertiesForTesting(root.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(1, 2),
- true,
- false);
+ SetLayerPropertiesForTesting(root.get(), identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(1, 2), true, false);
+
+ TransformTree& tree = host()->property_trees()->transform_tree;
// Case 1: parent's anchor point should not affect child or grand_child.
- SetLayerPropertiesForTesting(parent.get(),
- identity_matrix,
- gfx::Point3F(2.5f, 3.0f, 0.f),
- gfx::PointF(),
- gfx::Size(10, 12),
- true,
- false);
- SetLayerPropertiesForTesting(child.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(16, 18),
- true,
- false);
- SetLayerPropertiesForTesting(grand_child.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(76, 78),
- true,
- false);
+ SetLayerPropertiesForTesting(parent.get(), identity_matrix,
+ gfx::Point3F(2.5f, 3.0f, 0.f), gfx::PointF(),
+ gfx::Size(10, 12), true, false);
+ SetLayerPropertiesForTesting(child.get(), identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(16, 18), true, false);
+ SetLayerPropertiesForTesting(grand_child.get(), identity_matrix,
+ gfx::Point3F(), gfx::PointF(), gfx::Size(76, 78),
+ true, false);
ExecuteCalculateDrawProperties(root.get());
- EXPECT_TRANSFORMATION_MATRIX_EQ(identity_matrix, child->draw_transform());
- EXPECT_TRANSFORMATION_MATRIX_EQ(identity_matrix,
- child->screen_space_transform());
- EXPECT_TRANSFORMATION_MATRIX_EQ(identity_matrix,
- grand_child->draw_transform());
- EXPECT_TRANSFORMATION_MATRIX_EQ(identity_matrix,
- grand_child->screen_space_transform());
+
+ EXPECT_TRANSFORMATION_MATRIX_EQ(
+ identity_matrix, DrawTransformFromPropertyTrees(child.get(), tree));
+ EXPECT_TRANSFORMATION_MATRIX_EQ(
+ identity_matrix,
+ ScreenSpaceTransformFromPropertyTrees(child.get(), tree));
+ EXPECT_TRANSFORMATION_MATRIX_EQ(
+ identity_matrix, DrawTransformFromPropertyTrees(grand_child.get(), tree));
+ EXPECT_TRANSFORMATION_MATRIX_EQ(
+ identity_matrix,
+ ScreenSpaceTransformFromPropertyTrees(grand_child.get(), tree));
// Case 2: parent's position affects child and grand_child.
gfx::Transform parent_position_transform;
parent_position_transform.Translate(0.f, 1.2f);
- SetLayerPropertiesForTesting(parent.get(),
- identity_matrix,
- gfx::Point3F(2.5f, 3.0f, 0.f),
- gfx::PointF(0.f, 1.2f),
- gfx::Size(10, 12),
- true,
- false);
- SetLayerPropertiesForTesting(child.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(16, 18),
- true,
- false);
- SetLayerPropertiesForTesting(grand_child.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(76, 78),
- true,
- false);
+ SetLayerPropertiesForTesting(
+ parent.get(), identity_matrix, gfx::Point3F(2.5f, 3.0f, 0.f),
+ gfx::PointF(0.f, 1.2f), gfx::Size(10, 12), true, false);
+ SetLayerPropertiesForTesting(child.get(), identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(16, 18), true, false);
+ SetLayerPropertiesForTesting(grand_child.get(), identity_matrix,
+ gfx::Point3F(), gfx::PointF(), gfx::Size(76, 78),
+ true, false);
ExecuteCalculateDrawProperties(root.get());
- EXPECT_TRANSFORMATION_MATRIX_EQ(parent_position_transform,
- child->draw_transform());
- EXPECT_TRANSFORMATION_MATRIX_EQ(parent_position_transform,
- child->screen_space_transform());
- EXPECT_TRANSFORMATION_MATRIX_EQ(parent_position_transform,
- grand_child->draw_transform());
- EXPECT_TRANSFORMATION_MATRIX_EQ(parent_position_transform,
- grand_child->screen_space_transform());
+ EXPECT_TRANSFORMATION_MATRIX_EQ(
+ parent_position_transform,
+ DrawTransformFromPropertyTrees(child.get(), tree));
+ EXPECT_TRANSFORMATION_MATRIX_EQ(
+ parent_position_transform,
+ ScreenSpaceTransformFromPropertyTrees(child.get(), tree));
+ EXPECT_TRANSFORMATION_MATRIX_EQ(
+ parent_position_transform,
+ DrawTransformFromPropertyTrees(grand_child.get(), tree));
+ EXPECT_TRANSFORMATION_MATRIX_EQ(
+ parent_position_transform,
+ ScreenSpaceTransformFromPropertyTrees(grand_child.get(), tree));
// Case 3: parent's local transform affects child and grandchild
gfx::Transform parent_layer_transform;
@@ -494,63 +434,43 @@ TEST_F(LayerTreeHostCommonTest, TransformsForSimpleHierarchy) {
gfx::Transform parent_composite_transform =
parent_translation_to_anchor * parent_layer_transform *
Inverse(parent_translation_to_anchor);
- SetLayerPropertiesForTesting(parent.get(),
- parent_layer_transform,
- gfx::Point3F(2.5f, 3.0f, 0.f),
- gfx::PointF(),
- gfx::Size(10, 12),
- true,
- false);
- SetLayerPropertiesForTesting(child.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(16, 18),
- true,
- false);
- SetLayerPropertiesForTesting(grand_child.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(76, 78),
- true,
- false);
+ SetLayerPropertiesForTesting(parent.get(), parent_layer_transform,
+ gfx::Point3F(2.5f, 3.0f, 0.f), gfx::PointF(),
+ gfx::Size(10, 12), true, false);
+ SetLayerPropertiesForTesting(child.get(), identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(16, 18), true, false);
+ SetLayerPropertiesForTesting(grand_child.get(), identity_matrix,
+ gfx::Point3F(), gfx::PointF(), gfx::Size(76, 78),
+ true, false);
ExecuteCalculateDrawProperties(root.get());
- EXPECT_TRANSFORMATION_MATRIX_EQ(parent_composite_transform,
- child->draw_transform());
- EXPECT_TRANSFORMATION_MATRIX_EQ(parent_composite_transform,
- child->screen_space_transform());
- EXPECT_TRANSFORMATION_MATRIX_EQ(parent_composite_transform,
- grand_child->draw_transform());
- EXPECT_TRANSFORMATION_MATRIX_EQ(parent_composite_transform,
- grand_child->screen_space_transform());
+ EXPECT_TRANSFORMATION_MATRIX_EQ(
+ parent_composite_transform,
+ DrawTransformFromPropertyTrees(child.get(), tree));
+ EXPECT_TRANSFORMATION_MATRIX_EQ(
+ parent_composite_transform,
+ ScreenSpaceTransformFromPropertyTrees(child.get(), tree));
+ EXPECT_TRANSFORMATION_MATRIX_EQ(
+ parent_composite_transform,
+ DrawTransformFromPropertyTrees(grand_child.get(), tree));
+ EXPECT_TRANSFORMATION_MATRIX_EQ(
+ parent_composite_transform,
+ ScreenSpaceTransformFromPropertyTrees(grand_child.get(), tree));
}
TEST_F(LayerTreeHostCommonTest, TransformsForSingleRenderSurface) {
- scoped_refptr<Layer> root = Layer::Create(layer_settings());
- scoped_refptr<Layer> parent = Layer::Create(layer_settings());
- scoped_refptr<Layer> child = Layer::Create(layer_settings());
- scoped_refptr<LayerWithForcedDrawsContent> grand_child =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
- root->AddChild(parent);
- parent->AddChild(child);
- child->AddChild(grand_child);
-
- host()->SetRootLayer(root);
+ LayerImpl* root = root_layer();
+ LayerImpl* parent = AddChildToRoot<LayerImpl>();
+ LayerImpl* child = AddChild<LayerImpl>(parent);
+ LayerImpl* grand_child = AddChild<LayerImpl>(child);
+ grand_child->SetDrawsContent(true);
- // One-time setup of root layer
gfx::Transform identity_matrix;
- SetLayerPropertiesForTesting(root.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(1, 2),
- true,
- false);
+ SetLayerPropertiesForTesting(root, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(1, 2), true, false,
+ true);
// Child is set up so that a new render surface should be created.
child->SetOpacity(0.5f);
- child->SetForceRenderSurface(true);
gfx::Transform parent_layer_transform;
parent_layer_transform.Scale3d(1.f, 0.9f, 1.f);
@@ -569,35 +489,20 @@ TEST_F(LayerTreeHostCommonTest, TransformsForSingleRenderSurface) {
gfx::Transform surface_sublayer_composite_transform =
parent_composite_transform * Inverse(surface_sublayer_transform);
- // Child's render surface should not exist yet.
- ASSERT_FALSE(child->render_surface());
-
- SetLayerPropertiesForTesting(parent.get(),
- parent_layer_transform,
- gfx::Point3F(25.0f, 30.0f, 0.f),
- gfx::PointF(),
- gfx::Size(100, 120),
- true,
- false);
- SetLayerPropertiesForTesting(child.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(16, 18),
- true,
- false);
- SetLayerPropertiesForTesting(grand_child.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(8, 10),
- true,
+ SetLayerPropertiesForTesting(parent, parent_layer_transform,
+ gfx::Point3F(25.0f, 30.0f, 0.f), gfx::PointF(),
+ gfx::Size(100, 120), true, false, false);
+ SetLayerPropertiesForTesting(child, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(16, 18), true, false,
+ true);
+ SetLayerPropertiesForTesting(grand_child, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(8, 10), true, false,
false);
- ExecuteCalculateDrawProperties(root.get());
+ ExecuteCalculateDrawProperties(root);
// Render surface should have been created now.
ASSERT_TRUE(child->render_surface());
- ASSERT_EQ(child.get(), child->render_target());
+ ASSERT_EQ(child, child->render_target());
// The child layer's draw transform should refer to its new render surface.
// The screen-space transform, however, should still refer to the root.
@@ -621,28 +526,19 @@ TEST_F(LayerTreeHostCommonTest, TransformsForSingleRenderSurface) {
}
TEST_F(LayerTreeHostCommonTest, TransformsForReplica) {
- scoped_refptr<Layer> root = Layer::Create(layer_settings());
- scoped_refptr<Layer> parent = Layer::Create(layer_settings());
- scoped_refptr<Layer> child = Layer::Create(layer_settings());
- scoped_refptr<Layer> child_replica = Layer::Create(layer_settings());
- scoped_refptr<LayerWithForcedDrawsContent> grand_child =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
- root->AddChild(parent);
- parent->AddChild(child);
- child->AddChild(grand_child);
- child->SetReplicaLayer(child_replica.get());
-
- host()->SetRootLayer(root);
+ LayerImpl* root = root_layer();
+ LayerImpl* parent = AddChildToRoot<LayerImpl>();
+ LayerImpl* child = AddChild<LayerImpl>(parent);
+ LayerImpl* grand_child = AddChild<LayerImpl>(child);
+ grand_child->SetDrawsContent(true);
+ scoped_ptr<LayerImpl> child_replica =
+ LayerImpl::Create(host_impl()->active_tree(), 100);
// One-time setup of root layer
gfx::Transform identity_matrix;
- SetLayerPropertiesForTesting(root.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(1, 2),
- true,
- false);
+ SetLayerPropertiesForTesting(root, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(1, 2), true, false,
+ true);
// Child is set up so that a new render surface should be created.
child->SetOpacity(0.5f);
@@ -665,43 +561,29 @@ TEST_F(LayerTreeHostCommonTest, TransformsForReplica) {
gfx::Transform replica_composite_transform =
parent_composite_transform * replica_layer_transform *
Inverse(surface_sublayer_transform);
- child_replica->SetIsDrawable(true);
+ child_replica->SetDrawsContent(true);
// Child's render surface should not exist yet.
ASSERT_FALSE(child->render_surface());
- SetLayerPropertiesForTesting(parent.get(),
- parent_layer_transform,
- gfx::Point3F(2.5f, 3.0f, 0.f),
- gfx::PointF(),
- gfx::Size(10, 12),
- true,
- false);
- SetLayerPropertiesForTesting(child.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(16, 18),
- true,
- false);
- SetLayerPropertiesForTesting(grand_child.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(-0.5f, -0.5f),
- gfx::Size(1, 1),
- true,
- false);
- SetLayerPropertiesForTesting(child_replica.get(),
- replica_layer_transform,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(),
- true,
- false);
- ExecuteCalculateDrawProperties(root.get());
+ SetLayerPropertiesForTesting(parent, parent_layer_transform,
+ gfx::Point3F(2.5f, 3.0f, 0.f), gfx::PointF(),
+ gfx::Size(10, 12), true, false, false);
+ SetLayerPropertiesForTesting(child, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(16, 18), true, false,
+ true);
+ SetLayerPropertiesForTesting(grand_child, identity_matrix, gfx::Point3F(),
+ gfx::PointF(-0.5f, -0.5f), gfx::Size(1, 1), true,
+ false, false);
+ SetLayerPropertiesForTesting(child_replica.get(), replica_layer_transform,
+ gfx::Point3F(), gfx::PointF(), gfx::Size(), true,
+ false, false);
+ child->SetReplicaLayer(child_replica.Pass());
+
+ ExecuteCalculateDrawProperties(root);
// Render surface should have been created now.
ASSERT_TRUE(child->render_surface());
- ASSERT_EQ(child.get(), child->render_target());
+ ASSERT_EQ(child, child->render_target());
EXPECT_TRANSFORMATION_MATRIX_EQ(
replica_composite_transform,
@@ -726,33 +608,23 @@ TEST_F(LayerTreeHostCommonTest, TransformsForRenderSurfaceHierarchy) {
// - verifying that each layer has a reference to the correct render surface
// and render target values.
- scoped_refptr<Layer> root = Layer::Create(layer_settings());
- scoped_refptr<Layer> parent = Layer::Create(layer_settings());
- scoped_refptr<Layer> render_surface1 = Layer::Create(layer_settings());
- scoped_refptr<Layer> render_surface2 = Layer::Create(layer_settings());
- scoped_refptr<Layer> child_of_root = Layer::Create(layer_settings());
- scoped_refptr<Layer> child_of_rs1 = Layer::Create(layer_settings());
- scoped_refptr<Layer> child_of_rs2 = Layer::Create(layer_settings());
- scoped_refptr<Layer> replica_of_rs1 = Layer::Create(layer_settings());
- scoped_refptr<Layer> replica_of_rs2 = Layer::Create(layer_settings());
- scoped_refptr<Layer> grand_child_of_root = Layer::Create(layer_settings());
- scoped_refptr<LayerWithForcedDrawsContent> grand_child_of_rs1 =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
- scoped_refptr<LayerWithForcedDrawsContent> grand_child_of_rs2 =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
- root->AddChild(parent);
- parent->AddChild(render_surface1);
- parent->AddChild(child_of_root);
- render_surface1->AddChild(child_of_rs1);
- render_surface1->AddChild(render_surface2);
- render_surface2->AddChild(child_of_rs2);
- child_of_root->AddChild(grand_child_of_root);
- child_of_rs1->AddChild(grand_child_of_rs1);
- child_of_rs2->AddChild(grand_child_of_rs2);
- render_surface1->SetReplicaLayer(replica_of_rs1.get());
- render_surface2->SetReplicaLayer(replica_of_rs2.get());
+ LayerImpl* root = root_layer();
+ LayerImpl* parent = AddChildToRoot<LayerImpl>();
+ LayerImpl* render_surface1 = AddChild<LayerImpl>(parent);
+ LayerImpl* render_surface2 = AddChild<LayerImpl>(render_surface1);
+ LayerImpl* child_of_root = AddChild<LayerImpl>(parent);
+ LayerImpl* child_of_rs1 = AddChild<LayerImpl>(render_surface1);
+ LayerImpl* child_of_rs2 = AddChild<LayerImpl>(render_surface2);
+ LayerImpl* grand_child_of_root = AddChild<LayerImpl>(child_of_root);
+ LayerImpl* grand_child_of_rs1 = AddChild<LayerImpl>(child_of_rs1);
+ grand_child_of_rs1->SetDrawsContent(true);
+ LayerImpl* grand_child_of_rs2 = AddChild<LayerImpl>(child_of_rs2);
+ grand_child_of_rs2->SetDrawsContent(true);
- host()->SetRootLayer(root);
+ scoped_ptr<LayerImpl> replica_of_rs1 =
+ LayerImpl::Create(host_impl()->active_tree(), 101);
+ scoped_ptr<LayerImpl> replica_of_rs2 =
+ LayerImpl::Create(host_impl()->active_tree(), 102);
// In combination with descendant draws content, opacity != 1 forces the layer
// to have a new render surface.
@@ -761,13 +633,9 @@ TEST_F(LayerTreeHostCommonTest, TransformsForRenderSurfaceHierarchy) {
// One-time setup of root layer
gfx::Transform identity_matrix;
- SetLayerPropertiesForTesting(root.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(1, 2),
- true,
- false);
+ SetLayerPropertiesForTesting(root, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(1, 2), true, false,
+ true);
// All layers in the tree are initialized with an anchor at .25 and a size of
// (10,10). matrix "A" is the composite layer transform used in all layers,
@@ -808,85 +676,43 @@ TEST_F(LayerTreeHostCommonTest, TransformsForRenderSurfaceHierarchy) {
// the owning layer
gfx::Transform S2 = Inverse(surface2_sublayer_transform);
- SetLayerPropertiesForTesting(parent.get(),
- layer_transform,
- gfx::Point3F(2.5f, 0.f, 0.f),
- gfx::PointF(),
- gfx::Size(10, 10),
- true,
- false);
- SetLayerPropertiesForTesting(render_surface1.get(),
- layer_transform,
- gfx::Point3F(2.5f, 0.f, 0.f),
- gfx::PointF(),
- gfx::Size(10, 10),
- true,
- false);
- SetLayerPropertiesForTesting(render_surface2.get(),
- layer_transform,
- gfx::Point3F(2.5f, 0.f, 0.f),
- gfx::PointF(),
- gfx::Size(10, 10),
- true,
- false);
- SetLayerPropertiesForTesting(child_of_root.get(),
- layer_transform,
- gfx::Point3F(2.5f, 0.f, 0.f),
- gfx::PointF(),
- gfx::Size(10, 10),
- true,
- false);
- SetLayerPropertiesForTesting(child_of_rs1.get(),
- layer_transform,
- gfx::Point3F(2.5f, 0.f, 0.f),
- gfx::PointF(),
- gfx::Size(10, 10),
- true,
- false);
- SetLayerPropertiesForTesting(child_of_rs2.get(),
- layer_transform,
- gfx::Point3F(2.5f, 0.f, 0.f),
- gfx::PointF(),
- gfx::Size(10, 10),
- true,
- false);
- SetLayerPropertiesForTesting(grand_child_of_root.get(),
- layer_transform,
- gfx::Point3F(2.5f, 0.f, 0.f),
- gfx::PointF(),
- gfx::Size(10, 10),
- true,
- false);
- SetLayerPropertiesForTesting(grand_child_of_rs1.get(),
- layer_transform,
- gfx::Point3F(2.5f, 0.f, 0.f),
- gfx::PointF(),
- gfx::Size(10, 10),
- true,
- false);
- SetLayerPropertiesForTesting(grand_child_of_rs2.get(),
- layer_transform,
- gfx::Point3F(2.5f, 0.f, 0.f),
- gfx::PointF(),
- gfx::Size(10, 10),
- true,
- false);
- SetLayerPropertiesForTesting(replica_of_rs1.get(),
- replica_layer_transform,
- gfx::Point3F(2.5f, 0.f, 0.f),
- gfx::PointF(),
- gfx::Size(),
- true,
- false);
- SetLayerPropertiesForTesting(replica_of_rs2.get(),
- replica_layer_transform,
- gfx::Point3F(2.5f, 0.f, 0.f),
- gfx::PointF(),
- gfx::Size(),
- true,
- false);
-
- ExecuteCalculateDrawProperties(root.get());
+ SetLayerPropertiesForTesting(parent, layer_transform,
+ gfx::Point3F(2.5f, 0.f, 0.f), gfx::PointF(),
+ gfx::Size(10, 10), true, false, false);
+ SetLayerPropertiesForTesting(render_surface1, layer_transform,
+ gfx::Point3F(2.5f, 0.f, 0.f), gfx::PointF(),
+ gfx::Size(10, 10), true, false, true);
+ SetLayerPropertiesForTesting(render_surface2, layer_transform,
+ gfx::Point3F(2.5f, 0.f, 0.f), gfx::PointF(),
+ gfx::Size(10, 10), true, false, true);
+ SetLayerPropertiesForTesting(child_of_root, layer_transform,
+ gfx::Point3F(2.5f, 0.f, 0.f), gfx::PointF(),
+ gfx::Size(10, 10), true, false, false);
+ SetLayerPropertiesForTesting(child_of_rs1, layer_transform,
+ gfx::Point3F(2.5f, 0.f, 0.f), gfx::PointF(),
+ gfx::Size(10, 10), true, false, false);
+ SetLayerPropertiesForTesting(child_of_rs2, layer_transform,
+ gfx::Point3F(2.5f, 0.f, 0.f), gfx::PointF(),
+ gfx::Size(10, 10), true, false, false);
+ SetLayerPropertiesForTesting(grand_child_of_root, layer_transform,
+ gfx::Point3F(2.5f, 0.f, 0.f), gfx::PointF(),
+ gfx::Size(10, 10), true, false, false);
+ SetLayerPropertiesForTesting(grand_child_of_rs1, layer_transform,
+ gfx::Point3F(2.5f, 0.f, 0.f), gfx::PointF(),
+ gfx::Size(10, 10), true, false, false);
+ SetLayerPropertiesForTesting(grand_child_of_rs2, layer_transform,
+ gfx::Point3F(2.5f, 0.f, 0.f), gfx::PointF(),
+ gfx::Size(10, 10), true, false, false);
+ SetLayerPropertiesForTesting(replica_of_rs1.get(), replica_layer_transform,
+ gfx::Point3F(2.5f, 0.f, 0.f), gfx::PointF(),
+ gfx::Size(), true, false, false);
+ SetLayerPropertiesForTesting(replica_of_rs2.get(), replica_layer_transform,
+ gfx::Point3F(2.5f, 0.f, 0.f), gfx::PointF(),
+ gfx::Size(), true, false, false);
+
+ render_surface1->SetReplicaLayer(replica_of_rs1.Pass());
+ render_surface2->SetReplicaLayer(replica_of_rs2.Pass());
+ ExecuteCalculateDrawProperties(root);
// Only layers that are associated with render surfaces should have an actual
// RenderSurface() value.
@@ -903,17 +729,17 @@ TEST_F(LayerTreeHostCommonTest, TransformsForRenderSurfaceHierarchy) {
ASSERT_FALSE(grand_child_of_rs2->render_surface());
// Verify all render target accessors
- EXPECT_EQ(root.get(), parent->render_target());
- EXPECT_EQ(root.get(), child_of_root->render_target());
- EXPECT_EQ(root.get(), grand_child_of_root->render_target());
+ EXPECT_EQ(root, parent->render_target());
+ EXPECT_EQ(root, child_of_root->render_target());
+ EXPECT_EQ(root, grand_child_of_root->render_target());
- EXPECT_EQ(render_surface1.get(), render_surface1->render_target());
- EXPECT_EQ(render_surface1.get(), child_of_rs1->render_target());
- EXPECT_EQ(render_surface1.get(), grand_child_of_rs1->render_target());
+ EXPECT_EQ(render_surface1, render_surface1->render_target());
+ EXPECT_EQ(render_surface1, child_of_rs1->render_target());
+ EXPECT_EQ(render_surface1, grand_child_of_rs1->render_target());
- EXPECT_EQ(render_surface2.get(), render_surface2->render_target());
- EXPECT_EQ(render_surface2.get(), child_of_rs2->render_target());
- EXPECT_EQ(render_surface2.get(), grand_child_of_rs2->render_target());
+ EXPECT_EQ(render_surface2, render_surface2->render_target());
+ EXPECT_EQ(render_surface2, child_of_rs2->render_target());
+ EXPECT_EQ(render_surface2, grand_child_of_rs2->render_target());
// Verify layer draw transforms note that draw transforms are described with
// respect to the nearest ancestor render surface but screen space transforms
@@ -1011,48 +837,29 @@ TEST_F(LayerTreeHostCommonTest, TransformsForFlatteningLayer) {
// Note that the way the code is currently implemented, it is not expected to
// use a canonical orthographic projection.
- scoped_refptr<Layer> root = Layer::Create(layer_settings());
- scoped_refptr<Layer> child = Layer::Create(layer_settings());
- scoped_refptr<LayerWithForcedDrawsContent> grand_child =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
- scoped_refptr<LayerWithForcedDrawsContent> great_grand_child =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
+ LayerImpl* root = root_layer();
+ LayerImpl* child = AddChildToRoot<LayerImpl>();
+ LayerImpl* grand_child = AddChild<LayerImpl>(child);
+ grand_child->SetDrawsContent(true);
+ LayerImpl* great_grand_child = AddChild<LayerImpl>(grand_child);
+ great_grand_child->SetDrawsContent(true);
gfx::Transform rotation_about_y_axis;
rotation_about_y_axis.RotateAboutYAxis(30.0);
const gfx::Transform identity_matrix;
- SetLayerPropertiesForTesting(root.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(100, 100),
- true,
- false);
- SetLayerPropertiesForTesting(child.get(),
- rotation_about_y_axis,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(10, 10),
- true,
- false);
- SetLayerPropertiesForTesting(grand_child.get(),
- rotation_about_y_axis,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(10, 10),
- true,
- false);
- SetLayerPropertiesForTesting(great_grand_child.get(), identity_matrix,
+ SetLayerPropertiesForTesting(root, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(100, 100), true, false,
+ true);
+ SetLayerPropertiesForTesting(child, rotation_about_y_axis, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(10, 10), true, false,
+ true);
+ SetLayerPropertiesForTesting(grand_child, rotation_about_y_axis,
gfx::Point3F(), gfx::PointF(), gfx::Size(10, 10),
- true, false);
-
- root->AddChild(child);
- child->AddChild(grand_child);
- grand_child->AddChild(great_grand_child);
- child->SetForceRenderSurface(true);
-
- host()->SetRootLayer(root);
+ true, false, false);
+ SetLayerPropertiesForTesting(great_grand_child, identity_matrix,
+ gfx::Point3F(), gfx::PointF(), gfx::Size(10, 10),
+ true, false, false);
// No layers in this test should preserve 3d.
ASSERT_TRUE(root->should_flatten_transform());
@@ -1073,7 +880,7 @@ TEST_F(LayerTreeHostCommonTest, TransformsForFlatteningLayer) {
gfx::Transform expected_great_grand_child_screen_space_transform =
flattened_rotation_about_y * flattened_rotation_about_y;
- ExecuteCalculateDrawProperties(root.get());
+ ExecuteCalculateDrawProperties(root);
// The child's draw transform should have been taken by its surface.
ASSERT_TRUE(child->render_surface());
@@ -1096,6 +903,43 @@ TEST_F(LayerTreeHostCommonTest, TransformsForFlatteningLayer) {
great_grand_child->screen_space_transform());
}
+TEST_F(LayerTreeHostCommonTest, LayerFullyContainedWithinClipInTargetSpace) {
+ scoped_refptr<Layer> root = Layer::Create(layer_settings());
+ scoped_refptr<Layer> child = Layer::Create(layer_settings());
+ scoped_refptr<LayerWithForcedDrawsContent> grand_child =
+ make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
+
+ gfx::Transform child_transform;
+ child_transform.Translate(50.0, 50.0);
+ child_transform.RotateAboutZAxis(30.0);
+
+ gfx::Transform grand_child_transform;
+ grand_child_transform.RotateAboutYAxis(90.0);
+
+ const gfx::Transform identity_matrix;
+ SetLayerPropertiesForTesting(root.get(), identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(200, 200), true, false);
+ SetLayerPropertiesForTesting(child.get(), child_transform, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(10, 10), true, false);
+ SetLayerPropertiesForTesting(grand_child.get(), grand_child_transform,
+ gfx::Point3F(), gfx::PointF(),
+ gfx::Size(100, 100), true, false);
+
+ root->AddChild(child);
+ child->AddChild(grand_child);
+ grand_child->SetShouldFlattenTransform(false);
+
+ host()->SetRootLayer(root);
+
+ ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get());
+
+ // Mapping grand_child's bounds to target space produces a non-empty rect
+ // that is fully contained within the target's bounds, so grand_child should
+ // be considered fully visible.
+ EXPECT_EQ(gfx::Rect(grand_child->bounds()),
+ grand_child->visible_rect_from_property_trees());
+}
+
TEST_F(LayerTreeHostCommonTest, TransformsForDegenerateIntermediateLayer) {
// A layer that is empty in one axis, but not the other, was accidentally
// skipping a necessary translation. Without that translation, the coordinate
@@ -1106,45 +950,27 @@ TEST_F(LayerTreeHostCommonTest, TransformsForDegenerateIntermediateLayer) {
// implicitly inherited by the rest of the subtree, which then is positioned
// incorrectly as a result.
- scoped_refptr<Layer> root = Layer::Create(layer_settings());
- scoped_refptr<Layer> child = Layer::Create(layer_settings());
- scoped_refptr<LayerWithForcedDrawsContent> grand_child =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
+ LayerImpl* root = root_layer();
+ LayerImpl* child = AddChild<LayerImpl>(root);
+ LayerImpl* grand_child = AddChild<LayerImpl>(child);
+ grand_child->SetDrawsContent(true);
// The child height is zero, but has non-zero width that should be accounted
// for while computing draw transforms.
const gfx::Transform identity_matrix;
- SetLayerPropertiesForTesting(root.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(100, 100),
- true,
- false);
- SetLayerPropertiesForTesting(child.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(10, 0),
- true,
- false);
- SetLayerPropertiesForTesting(grand_child.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(10, 10),
- true,
+ SetLayerPropertiesForTesting(root, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(100, 100), true, false,
+ true);
+ SetLayerPropertiesForTesting(child, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(10, 0), true, false,
+ true);
+ SetLayerPropertiesForTesting(grand_child, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(10, 10), true, false,
false);
- root->AddChild(child);
- child->AddChild(grand_child);
- child->SetForceRenderSurface(true);
-
- host()->SetRootLayer(root);
-
- ExecuteCalculateDrawProperties(root.get());
+ ExecuteCalculateDrawProperties(root);
- ASSERT_TRUE(child->render_surface());
+ ASSERT_TRUE(child->has_render_surface());
// This is the real test, the rest are sanity checks.
EXPECT_TRANSFORMATION_MATRIX_EQ(identity_matrix,
child->render_surface()->draw_transform());
@@ -1157,37 +983,26 @@ TEST_F(LayerTreeHostCommonTest, TransformAboveRootLayer) {
// Transformations applied at the root of the tree should be forwarded
// to child layers instead of applied to the root RenderSurface.
const gfx::Transform identity_matrix;
- scoped_refptr<LayerWithForcedDrawsContent> root =
- new LayerWithForcedDrawsContent(layer_settings());
- scoped_refptr<LayerWithForcedDrawsContent> child =
- new LayerWithForcedDrawsContent(layer_settings());
- child->SetScrollClipLayerId(root->id());
- root->AddChild(child);
+ LayerImpl* root = root_layer();
+ root->SetDrawsContent(true);
+ LayerImpl* child = AddChild<LayerImpl>(root);
+ child->SetDrawsContent(true);
- host()->SetRootLayer(root);
+ child->SetScrollClipLayer(root->id());
- SetLayerPropertiesForTesting(root.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(20, 20),
- true,
- false);
- SetLayerPropertiesForTesting(child.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(20, 20),
- true,
+ SetLayerPropertiesForTesting(root, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(20, 20), true, false,
+ true);
+ SetLayerPropertiesForTesting(child, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(20, 20), true, false,
false);
gfx::Transform translate;
translate.Translate(50, 50);
{
- RenderSurfaceLayerList render_surface_layer_list;
- LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
- root.get(), root->bounds(), translate, &render_surface_layer_list);
- inputs.can_adjust_raster_scales = true;
+ LayerImplList render_surface_layer_list_impl;
+ LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs(
+ root, root->bounds(), translate, &render_surface_layer_list_impl);
inputs.property_trees->needs_rebuild = true;
LayerTreeHostCommon::CalculateDrawProperties(&inputs);
EXPECT_EQ(translate, root->draw_properties().target_space_transform);
@@ -1198,10 +1013,9 @@ TEST_F(LayerTreeHostCommonTest, TransformAboveRootLayer) {
gfx::Transform scale;
scale.Scale(2, 2);
{
- RenderSurfaceLayerList render_surface_layer_list;
- LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
- root.get(), root->bounds(), scale, &render_surface_layer_list);
- inputs.can_adjust_raster_scales = true;
+ LayerImplList render_surface_layer_list_impl;
+ LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs(
+ root, root->bounds(), scale, &render_surface_layer_list_impl);
inputs.property_trees->needs_rebuild = true;
LayerTreeHostCommon::CalculateDrawProperties(&inputs);
EXPECT_EQ(scale, root->draw_properties().target_space_transform);
@@ -1212,10 +1026,9 @@ TEST_F(LayerTreeHostCommonTest, TransformAboveRootLayer) {
gfx::Transform rotate;
rotate.Rotate(2);
{
- RenderSurfaceLayerList render_surface_layer_list;
- LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
- root.get(), root->bounds(), rotate, &render_surface_layer_list);
- inputs.can_adjust_raster_scales = true;
+ LayerImplList render_surface_layer_list_impl;
+ LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs(
+ root, root->bounds(), rotate, &render_surface_layer_list_impl);
inputs.property_trees->needs_rebuild = true;
LayerTreeHostCommon::CalculateDrawProperties(&inputs);
EXPECT_EQ(rotate, root->draw_properties().target_space_transform);
@@ -1228,10 +1041,9 @@ TEST_F(LayerTreeHostCommonTest, TransformAboveRootLayer) {
composite.ConcatTransform(scale);
composite.ConcatTransform(rotate);
{
- RenderSurfaceLayerList render_surface_layer_list;
- LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
- root.get(), root->bounds(), composite, &render_surface_layer_list);
- inputs.can_adjust_raster_scales = true;
+ LayerImplList render_surface_layer_list_impl;
+ LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs(
+ root, root->bounds(), composite, &render_surface_layer_list_impl);
inputs.property_trees->needs_rebuild = true;
LayerTreeHostCommon::CalculateDrawProperties(&inputs);
EXPECT_EQ(composite, root->draw_properties().target_space_transform);
@@ -1243,11 +1055,10 @@ TEST_F(LayerTreeHostCommonTest, TransformAboveRootLayer) {
float device_scale_factor = 1.5f;
{
- RenderSurfaceLayerList render_surface_layer_list;
- LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
- root.get(), root->bounds(), translate, &render_surface_layer_list);
+ LayerImplList render_surface_layer_list_impl;
+ LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs(
+ root, root->bounds(), translate, &render_surface_layer_list_impl);
inputs.device_scale_factor = device_scale_factor;
- inputs.can_adjust_raster_scales = true;
inputs.property_trees->needs_rebuild = true;
LayerTreeHostCommon::CalculateDrawProperties(&inputs);
gfx::Transform device_scaled_translate = translate;
@@ -1263,12 +1074,11 @@ TEST_F(LayerTreeHostCommonTest, TransformAboveRootLayer) {
float page_scale_factor = 2.f;
{
- RenderSurfaceLayerList render_surface_layer_list;
- LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
- root.get(), root->bounds(), translate, &render_surface_layer_list);
+ LayerImplList render_surface_layer_list_impl;
+ LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs(
+ root, root->bounds(), translate, &render_surface_layer_list_impl);
inputs.page_scale_factor = page_scale_factor;
- inputs.page_scale_layer = root.get();
- inputs.can_adjust_raster_scales = true;
+ inputs.page_scale_layer = root;
inputs.property_trees->needs_rebuild = true;
LayerTreeHostCommon::CalculateDrawProperties(&inputs);
gfx::Transform page_scaled_translate = translate;
@@ -1284,10 +1094,10 @@ TEST_F(LayerTreeHostCommonTest, TransformAboveRootLayer) {
root->SetTransform(composite);
{
- RenderSurfaceLayerList render_surface_layer_list;
- LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
- root.get(), root->bounds(), composite, &render_surface_layer_list);
- inputs.can_adjust_raster_scales = true;
+ LayerImplList render_surface_layer_list_impl;
+ LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs(
+ root, root->bounds(), composite, &render_surface_layer_list_impl);
+ inputs.property_trees->needs_rebuild = true;
LayerTreeHostCommon::CalculateDrawProperties(&inputs);
gfx::Transform compositeSquared = composite;
compositeSquared.ConcatTransform(composite);
@@ -1301,48 +1111,24 @@ TEST_F(LayerTreeHostCommonTest, TransformAboveRootLayer) {
TEST_F(LayerTreeHostCommonTest,
RenderSurfaceListForRenderSurfaceWithClippedLayer) {
- scoped_refptr<Layer> parent = Layer::Create(layer_settings());
- scoped_refptr<Layer> render_surface1 = Layer::Create(layer_settings());
- scoped_refptr<LayerWithForcedDrawsContent> child =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
-
- host()->SetRootLayer(parent);
+ LayerImpl* parent = root_layer();
+ parent->SetMasksToBounds(true);
+ LayerImpl* render_surface1 = AddChildToRoot<LayerImpl>();
+ LayerImpl* child = AddChild<LayerImpl>(render_surface1);
+ child->SetDrawsContent(true);
const gfx::Transform identity_matrix;
- SetLayerPropertiesForTesting(parent.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(10, 10),
- true,
- false);
- SetLayerPropertiesForTesting(render_surface1.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(10, 10),
- true,
- false);
- SetLayerPropertiesForTesting(child.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(30.f, 30.f),
- gfx::Size(10, 10),
- true,
- false);
-
- parent->AddChild(render_surface1);
- parent->SetMasksToBounds(true);
- render_surface1->AddChild(child);
- render_surface1->SetForceRenderSurface(true);
+ SetLayerPropertiesForTesting(parent, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(10, 10), true, false,
+ true);
+ SetLayerPropertiesForTesting(render_surface1, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(10, 10), true, false,
+ true);
+ SetLayerPropertiesForTesting(child, identity_matrix, gfx::Point3F(),
+ gfx::PointF(30.f, 30.f), gfx::Size(10, 10), true,
+ false, false);
- RenderSurfaceLayerList render_surface_layer_list;
- LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
- parent.get(),
- parent->bounds(),
- gfx::Transform(),
- &render_surface_layer_list);
- LayerTreeHostCommon::CalculateDrawProperties(&inputs);
+ ExecuteCalculateDrawProperties(parent);
// The child layer's content is entirely outside the parent's clip rect, so
// the intermediate render surface should not be listed here, even if it was
@@ -1350,7 +1136,7 @@ TEST_F(LayerTreeHostCommonTest,
// are unexpected at draw time (e.g. we might try to create a content texture
// of size 0).
ASSERT_TRUE(parent->render_surface());
- EXPECT_EQ(1U, render_surface_layer_list.size());
+ EXPECT_EQ(1U, render_surface_layer_list_impl()->size());
}
TEST_F(LayerTreeHostCommonTest, RenderSurfaceListForTransparentChild) {
@@ -1384,33 +1170,69 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceListForTransparentChild) {
EXPECT_EQ(gfx::Rect(), parent->drawable_content_rect());
}
-TEST_F(LayerTreeHostCommonTest, RenderSurfaceForBlendMode) {
- scoped_refptr<Layer> parent = Layer::Create(layer_settings());
- scoped_refptr<LayerWithForcedDrawsContent> child =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
+TEST_F(LayerTreeHostCommonTest,
+ RenderSurfaceListForTransparentChildWithBackgroundFilter) {
+ LayerImpl* parent = root_layer();
+ LayerImpl* render_surface1 = AddChild<LayerImpl>(parent);
+ LayerImpl* child = AddChild<LayerImpl>(render_surface1);
+ child->SetDrawsContent(true);
- host()->SetRootLayer(parent);
+ const gfx::Transform identity_matrix;
+ SetLayerPropertiesForTesting(parent, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(10, 10), true, false,
+ true);
+ SetLayerPropertiesForTesting(render_surface1, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(10, 10), true, false,
+ true);
+ SetLayerPropertiesForTesting(child, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(10, 10), true, false,
+ false);
+ render_surface1->SetOpacity(0.f);
+ FilterOperations filters;
+ filters.Append(FilterOperation::CreateBlurFilter(1.5f));
+ render_surface1->SetBackgroundFilters(filters);
+
+ LayerImplList render_surface_layer_list;
+ LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs(
+ parent, parent->bounds(), &render_surface_layer_list);
+ inputs.can_adjust_raster_scales = true;
+ LayerTreeHostCommon::CalculateDrawProperties(&inputs);
+
+ // The layer is fully transparent, but has a background filter, so it
+ // shouldn't be skipped.
+ ASSERT_TRUE(parent->render_surface());
+ EXPECT_EQ(1U, parent->render_surface()->layer_list().size());
+ EXPECT_EQ(2U, render_surface_layer_list.size());
+ EXPECT_EQ(gfx::Rect(0, 0, 10, 10), parent->drawable_content_rect());
+}
+
+TEST_F(LayerTreeHostCommonTest, RenderSurfaceForBlendMode) {
+ LayerImpl* parent = root_layer();
+ LayerImpl* child = AddChild<LayerImpl>(parent);
+ child->SetDrawsContent(true);
const gfx::Transform identity_matrix;
const SkXfermode::Mode blend_mode = SkXfermode::kMultiply_Mode;
- SetLayerPropertiesForTesting(child.get(), identity_matrix, gfx::Point3F(),
- gfx::PointF(), gfx::Size(10, 10), true, false);
+ SetLayerPropertiesForTesting(parent, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(10, 10), true, false,
+ true);
+ SetLayerPropertiesForTesting(child, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(10, 10), true, false,
+ true);
- parent->AddChild(child);
child->SetBlendMode(blend_mode);
+ child->SetOpacity(0.5f);
- RenderSurfaceLayerList render_surface_layer_list;
- LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
- parent.get(), parent->bounds(), &render_surface_layer_list);
- LayerTreeHostCommon::CalculateDrawProperties(&inputs);
+ ExecuteCalculateDrawProperties(parent);
// Since the child layer has a blend mode other than normal, it should get
// its own render surface. Also, layer's draw_properties should contain the
// default blend mode, since the render surface becomes responsible for
// applying the blend mode.
ASSERT_TRUE(child->render_surface());
- EXPECT_EQ(1U, child->render_surface()->layer_list().size());
- EXPECT_EQ(SkXfermode::kSrcOver_Mode, child->draw_properties().blend_mode);
+ EXPECT_EQ(1.0f, child->draw_opacity());
+ EXPECT_EQ(0.5f, child->render_surface()->draw_opacity());
+ EXPECT_EQ(SkXfermode::kSrcOver_Mode, child->draw_blend_mode());
}
TEST_F(LayerTreeHostCommonTest, ForceRenderSurface) {
@@ -1449,32 +1271,26 @@ TEST_F(LayerTreeHostCommonTest, ForceRenderSurface) {
render_surface1->AddChild(child);
// Sanity check before the actual test
- EXPECT_FALSE(parent->render_surface());
- EXPECT_FALSE(render_surface1->render_surface());
+ EXPECT_FALSE(parent->has_render_surface());
+ EXPECT_FALSE(render_surface1->has_render_surface());
{
- RenderSurfaceLayerList render_surface_layer_list;
- LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
- parent.get(), parent->bounds(), &render_surface_layer_list);
- inputs.can_adjust_raster_scales = true;
+ LayerTreeHostCommon::CalcDrawPropsMainInputs inputs(parent.get(),
+ parent->bounds());
LayerTreeHostCommon::CalculateDrawProperties(&inputs);
// The root layer always creates a render surface
- EXPECT_TRUE(parent->render_surface());
- EXPECT_TRUE(render_surface1->render_surface());
- EXPECT_EQ(2U, render_surface_layer_list.size());
+ EXPECT_TRUE(parent->has_render_surface());
+ EXPECT_TRUE(render_surface1->has_render_surface());
}
{
- RenderSurfaceLayerList render_surface_layer_list;
render_surface1->SetForceRenderSurface(false);
- LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
- parent.get(), parent->bounds(), &render_surface_layer_list);
- inputs.can_adjust_raster_scales = true;
+ LayerTreeHostCommon::CalcDrawPropsMainInputs inputs(parent.get(),
+ parent->bounds());
LayerTreeHostCommon::CalculateDrawProperties(&inputs);
- EXPECT_TRUE(parent->render_surface());
- EXPECT_FALSE(render_surface1->render_surface());
- EXPECT_EQ(1U, render_surface_layer_list.size());
+ EXPECT_TRUE(parent->has_render_surface());
+ EXPECT_FALSE(render_surface1->has_render_surface());
}
}
@@ -1482,12 +1298,13 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfacesFlattenScreenSpaceTransform) {
// Render surfaces act as a flattening point for their subtree, so should
// always flatten the target-to-screen space transform seen by descendants.
- scoped_refptr<Layer> root = Layer::Create(layer_settings());
- scoped_refptr<Layer> parent = Layer::Create(layer_settings());
- scoped_refptr<LayerWithForcedDrawsContent> child =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
- scoped_refptr<LayerWithForcedDrawsContent> grand_child =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
+ LayerImpl* root = root_layer();
+ LayerImpl* parent = AddChild<LayerImpl>(root);
+ LayerImpl* child = AddChild<LayerImpl>(parent);
+ LayerImpl* grand_child = AddChild<LayerImpl>(child);
+
+ child->SetDrawsContent(true);
+ grand_child->SetDrawsContent(true);
gfx::Transform rotation_about_y_axis;
rotation_about_y_axis.RotateAboutYAxis(30.0);
@@ -1495,25 +1312,21 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfacesFlattenScreenSpaceTransform) {
parent->SetOpacity(0.9f);
const gfx::Transform identity_matrix;
- SetLayerPropertiesForTesting(root.get(), identity_matrix, gfx::Point3F(),
- gfx::PointF(), gfx::Size(100, 100), true, false);
- SetLayerPropertiesForTesting(parent.get(), rotation_about_y_axis,
- gfx::Point3F(), gfx::PointF(), gfx::Size(10, 10),
- true, false);
- SetLayerPropertiesForTesting(child.get(), identity_matrix, gfx::Point3F(),
- gfx::PointF(), gfx::Size(10, 10), true, false);
- SetLayerPropertiesForTesting(grand_child.get(), identity_matrix,
- gfx::Point3F(), gfx::PointF(), gfx::Size(10, 10),
- true, false);
-
- root->AddChild(parent);
- parent->AddChild(child);
- child->AddChild(grand_child);
+ SetLayerPropertiesForTesting(root, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(100, 100), true, false,
+ true);
+ SetLayerPropertiesForTesting(parent, rotation_about_y_axis, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(10, 10), true, false,
+ true);
+ SetLayerPropertiesForTesting(child, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(10, 10), true, false,
+ false);
+ SetLayerPropertiesForTesting(grand_child, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(10, 10), true, false,
+ false);
grand_child->SetShouldFlattenTransform(false);
- host()->SetRootLayer(root);
-
// Only grand_child should preserve 3d.
EXPECT_TRUE(root->should_flatten_transform());
EXPECT_TRUE(parent->should_flatten_transform());
@@ -1526,7 +1339,7 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfacesFlattenScreenSpaceTransform) {
gfx::Transform flattened_rotation_about_y = rotation_about_y_axis;
flattened_rotation_about_y.FlattenTo2d();
- ExecuteCalculateDrawProperties(root.get());
+ ExecuteCalculateDrawProperties(root);
EXPECT_TRUE(parent->render_surface());
EXPECT_FALSE(child->render_surface());
@@ -1560,94 +1373,56 @@ TEST_F(LayerTreeHostCommonTest, ClipRectCullsRenderSurfaces) {
// In this configuration, grand_child and great_grand_child are completely
// outside the clip rect, and they should never get scheduled on the list of
// render surfaces.
- //
-
- const gfx::Transform identity_matrix;
- scoped_refptr<Layer> parent = Layer::Create(layer_settings());
- scoped_refptr<Layer> child = Layer::Create(layer_settings());
- scoped_refptr<Layer> grand_child = Layer::Create(layer_settings());
- scoped_refptr<Layer> great_grand_child = Layer::Create(layer_settings());
- scoped_refptr<LayerWithForcedDrawsContent> leaf_node1 =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
- scoped_refptr<LayerWithForcedDrawsContent> leaf_node2 =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
- parent->AddChild(child);
- child->AddChild(grand_child);
- grand_child->AddChild(great_grand_child);
- host()->SetRootLayer(parent);
+ LayerImpl* parent = root_layer();
+ LayerImpl* child = AddChildToRoot<LayerImpl>();
+ LayerImpl* grand_child = AddChild<LayerImpl>(child);
+ LayerImpl* great_grand_child = AddChild<LayerImpl>(grand_child);
// leaf_node1 ensures that parent and child are kept on the
// render_surface_layer_list, even though grand_child and great_grand_child
// should be clipped.
- child->AddChild(leaf_node1);
- great_grand_child->AddChild(leaf_node2);
+ LayerImpl* leaf_node1 = AddChild<LayerImpl>(child);
+ leaf_node1->SetDrawsContent(true);
+ LayerImpl* leaf_node2 = AddChild<LayerImpl>(great_grand_child);
+ leaf_node2->SetDrawsContent(true);
- SetLayerPropertiesForTesting(parent.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(500, 500),
- true,
- false);
- SetLayerPropertiesForTesting(child.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(20, 20),
- true,
- false);
- SetLayerPropertiesForTesting(grand_child.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(45.f, 45.f),
- gfx::Size(10, 10),
- true,
- false);
- SetLayerPropertiesForTesting(great_grand_child.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(10, 10),
- true,
- false);
- SetLayerPropertiesForTesting(leaf_node1.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(500, 500),
- true,
+ const gfx::Transform identity_matrix;
+
+ SetLayerPropertiesForTesting(parent, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(500, 500), true, false,
+ true);
+ SetLayerPropertiesForTesting(child, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(20, 20), true, false,
+ true);
+ SetLayerPropertiesForTesting(grand_child, identity_matrix, gfx::Point3F(),
+ gfx::PointF(45.f, 45.f), gfx::Size(10, 10), true,
+ false, false);
+ SetLayerPropertiesForTesting(great_grand_child, identity_matrix,
+ gfx::Point3F(), gfx::PointF(), gfx::Size(10, 10),
+ true, false, false);
+ SetLayerPropertiesForTesting(leaf_node1, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(500, 500), true, false,
false);
- SetLayerPropertiesForTesting(leaf_node2.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(20, 20),
- true,
+ SetLayerPropertiesForTesting(leaf_node2, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(20, 20), true, false,
false);
child->SetMasksToBounds(true);
child->SetOpacity(0.4f);
- child->SetForceRenderSurface(true);
grand_child->SetOpacity(0.5f);
great_grand_child->SetOpacity(0.4f);
- RenderSurfaceLayerList render_surface_layer_list;
- LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
- parent.get(), parent->bounds(), &render_surface_layer_list);
- inputs.can_adjust_raster_scales = true;
- LayerTreeHostCommon::CalculateDrawProperties(&inputs);
+ ExecuteCalculateDrawProperties(parent);
- ASSERT_EQ(2U, render_surface_layer_list.size());
- EXPECT_EQ(parent->id(), render_surface_layer_list.at(0)->id());
- EXPECT_EQ(child->id(), render_surface_layer_list.at(1)->id());
+ ASSERT_EQ(2U, render_surface_layer_list_impl()->size());
+ EXPECT_EQ(parent->id(), render_surface_layer_list_impl()->at(0)->id());
+ EXPECT_EQ(child->id(), render_surface_layer_list_impl()->at(1)->id());
}
TEST_F(LayerTreeHostCommonTest, ClipRectCullsSurfaceWithoutVisibleContent) {
// When a render surface has a clip rect, it is used to clip the content rect
- // of the surface. When the render surface is animating its transforms, then
- // the content rect's position in the clip rect is not defined on the main
- // thread, and its content rect should not be clipped.
+ // of the surface.
// The test tree is set up as follows:
// - parent is a container layer that masksToBounds=true to cause clipping.
@@ -1658,92 +1433,43 @@ TEST_F(LayerTreeHostCommonTest, ClipRectCullsSurfaceWithoutVisibleContent) {
// In this configuration, grand_child should be outside the clipped
// content rect of the child, making grand_child not appear in the
- // render_surface_layer_list. However, when we place an animation on the
- // child, this clipping should be avoided and we should keep the grand_child
- // in the render_surface_layer_list.
+ // render_surface_layer_list.
- const gfx::Transform identity_matrix;
- scoped_refptr<Layer> parent = Layer::Create(layer_settings());
- scoped_refptr<Layer> child = Layer::Create(layer_settings());
- scoped_refptr<Layer> grand_child = Layer::Create(layer_settings());
- scoped_refptr<LayerWithForcedDrawsContent> leaf_node =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
- parent->AddChild(child);
- child->AddChild(grand_child);
- grand_child->AddChild(leaf_node);
+ LayerImpl* parent = root_layer();
+ LayerImpl* child = AddChildToRoot<LayerImpl>();
+ LayerImpl* grand_child = AddChild<LayerImpl>(child);
+ LayerImpl* leaf_node = AddChild<LayerImpl>(grand_child);
+ leaf_node->SetDrawsContent(true);
- host()->SetRootLayer(parent);
+ const gfx::Transform identity_matrix;
- SetLayerPropertiesForTesting(parent.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(100, 100),
- true,
- false);
- SetLayerPropertiesForTesting(child.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(20, 20),
- true,
- false);
- SetLayerPropertiesForTesting(grand_child.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(200.f, 200.f),
- gfx::Size(10, 10),
- true,
- false);
- SetLayerPropertiesForTesting(leaf_node.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(10, 10),
- true,
+ SetLayerPropertiesForTesting(parent, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(100, 100), true, false,
+ true);
+ SetLayerPropertiesForTesting(child, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(20, 20), true, false,
+ true);
+ SetLayerPropertiesForTesting(grand_child, identity_matrix, gfx::Point3F(),
+ gfx::PointF(200.f, 200.f), gfx::Size(10, 10),
+ true, false, true);
+ SetLayerPropertiesForTesting(leaf_node, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(10, 10), true, false,
false);
parent->SetMasksToBounds(true);
child->SetOpacity(0.4f);
- child->SetForceRenderSurface(true);
grand_child->SetOpacity(0.4f);
- grand_child->SetForceRenderSurface(true);
- {
- RenderSurfaceLayerList render_surface_layer_list;
- LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
- parent.get(), parent->bounds(), &render_surface_layer_list);
- inputs.can_adjust_raster_scales = true;
- LayerTreeHostCommon::CalculateDrawProperties(&inputs);
-
- // Without an animation, we should cull child and grand_child from the
- // render_surface_layer_list.
- ASSERT_EQ(1U, render_surface_layer_list.size());
- EXPECT_EQ(parent->id(), render_surface_layer_list.at(0)->id());
- }
-
- // Now put an animating transform on child.
- AddAnimatedTransformToController(
- child->layer_animation_controller(), 10.0, 30, 0);
-
- {
- RenderSurfaceLayerList render_surface_layer_list;
- LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
- parent.get(), parent->bounds(), &render_surface_layer_list);
- inputs.can_adjust_raster_scales = true;
- LayerTreeHostCommon::CalculateDrawProperties(&inputs);
+ ExecuteCalculateDrawProperties(parent);
- // With an animating transform, we should keep child and grand_child in the
- // render_surface_layer_list.
- ASSERT_EQ(3U, render_surface_layer_list.size());
- EXPECT_EQ(parent->id(), render_surface_layer_list.at(0)->id());
- EXPECT_EQ(child->id(), render_surface_layer_list.at(1)->id());
- EXPECT_EQ(grand_child->id(), render_surface_layer_list.at(2)->id());
- }
+ // We should cull child and grand_child from the
+ // render_surface_layer_list.
+ ASSERT_EQ(1U, render_surface_layer_list_impl()->size());
+ EXPECT_EQ(parent->id(), render_surface_layer_list_impl()->at(0)->id());
}
-TEST_F(LayerTreeHostCommonTest, IsClippedIsSetCorrectly) {
- // Layer's IsClipped() property is set to true when:
+TEST_F(LayerTreeHostCommonTest, IsClippedIsSetCorrectlyLayerImpl) {
+ // Tests that LayerImpl's IsClipped() property is set to true when:
// - the layer clips its subtree, e.g. masks to bounds,
// - the layer is clipped by an ancestor that contributes to the same
// render target,
@@ -1757,83 +1483,41 @@ TEST_F(LayerTreeHostCommonTest, IsClippedIsSetCorrectly) {
// and propagates the clip to the subtree.
const gfx::Transform identity_matrix;
- scoped_refptr<Layer> root = Layer::Create(layer_settings());
- scoped_refptr<Layer> parent = Layer::Create(layer_settings());
- scoped_refptr<Layer> child1 = Layer::Create(layer_settings());
- scoped_refptr<Layer> child2 = Layer::Create(layer_settings());
- scoped_refptr<Layer> grand_child = Layer::Create(layer_settings());
- scoped_refptr<LayerWithForcedDrawsContent> leaf_node1 =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
- scoped_refptr<LayerWithForcedDrawsContent> leaf_node2 =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
- root->AddChild(parent);
- parent->AddChild(child1);
- parent->AddChild(child2);
- child1->AddChild(grand_child);
- child2->AddChild(leaf_node2);
- grand_child->AddChild(leaf_node1);
-
- host()->SetRootLayer(root);
-
- child2->SetForceRenderSurface(true);
+ LayerImpl* root = root_layer();
+ LayerImpl* parent = AddChild<LayerImpl>(root);
+ LayerImpl* child1 = AddChild<LayerImpl>(parent);
+ LayerImpl* child2 = AddChild<LayerImpl>(parent);
+ LayerImpl* grand_child = AddChild<LayerImpl>(child1);
+ LayerImpl* leaf_node1 = AddChild<LayerImpl>(grand_child);
+ leaf_node1->SetDrawsContent(true);
+ LayerImpl* leaf_node2 = AddChild<LayerImpl>(child2);
+ leaf_node2->SetDrawsContent(true);
- SetLayerPropertiesForTesting(root.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(100, 100),
- true,
- false);
- SetLayerPropertiesForTesting(parent.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(100, 100),
- true,
- false);
- SetLayerPropertiesForTesting(child1.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(100, 100),
- true,
+ SetLayerPropertiesForTesting(root, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(100, 100), true, false,
+ true);
+ SetLayerPropertiesForTesting(parent, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(100, 100), true, false,
false);
- SetLayerPropertiesForTesting(child2.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(100, 100),
- true,
+ SetLayerPropertiesForTesting(child1, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(100, 100), true, false,
false);
- SetLayerPropertiesForTesting(grand_child.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(100, 100),
- true,
+ SetLayerPropertiesForTesting(child2, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(100, 100), true, false,
+ true);
+ SetLayerPropertiesForTesting(grand_child, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(100, 100), true, false,
false);
- SetLayerPropertiesForTesting(leaf_node1.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(100, 100),
- true,
+ SetLayerPropertiesForTesting(leaf_node1, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(100, 100), true, false,
false);
- SetLayerPropertiesForTesting(leaf_node2.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(100, 100),
- true,
+ SetLayerPropertiesForTesting(leaf_node2, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(100, 100), true, false,
false);
// Case 1: nothing is clipped except the root render surface.
{
- RenderSurfaceLayerList render_surface_layer_list;
- LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
- root.get(), parent->bounds(), &render_surface_layer_list);
- inputs.can_adjust_raster_scales = true;
- LayerTreeHostCommon::CalculateDrawProperties(&inputs);
+ ExecuteCalculateDrawProperties(root);
ASSERT_TRUE(root->render_surface());
ASSERT_TRUE(child2->render_surface());
@@ -1854,12 +1538,10 @@ TEST_F(LayerTreeHostCommonTest, IsClippedIsSetCorrectly) {
// not clipped explicitly because child2's surface already accounts for
// that clip.
{
- RenderSurfaceLayerList render_surface_layer_list;
parent->SetMasksToBounds(true);
- LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
- root.get(), parent->bounds(), &render_surface_layer_list);
- inputs.can_adjust_raster_scales = true;
- LayerTreeHostCommon::CalculateDrawProperties(&inputs);
+ host_impl()->active_tree()->property_trees()->needs_rebuild = true;
+
+ ExecuteCalculateDrawProperties(root);
ASSERT_TRUE(root->render_surface());
ASSERT_TRUE(child2->render_surface());
@@ -1873,18 +1555,17 @@ TEST_F(LayerTreeHostCommonTest, IsClippedIsSetCorrectly) {
EXPECT_TRUE(grand_child->is_clipped());
EXPECT_TRUE(leaf_node1->is_clipped());
EXPECT_FALSE(leaf_node2->is_clipped());
+
+ parent->SetMasksToBounds(false);
}
// Case 3: child2 masksToBounds. The layer and subtree are clipped, and
// child2's render surface is not clipped.
{
- RenderSurfaceLayerList render_surface_layer_list;
- parent->SetMasksToBounds(false);
child2->SetMasksToBounds(true);
- LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
- root.get(), parent->bounds(), &render_surface_layer_list);
- inputs.can_adjust_raster_scales = true;
- LayerTreeHostCommon::CalculateDrawProperties(&inputs);
+ host_impl()->active_tree()->property_trees()->needs_rebuild = true;
+
+ ExecuteCalculateDrawProperties(root);
ASSERT_TRUE(root->render_surface());
ASSERT_TRUE(child2->render_surface());
@@ -1914,82 +1595,41 @@ TEST_F(LayerTreeHostCommonTest, DrawableContentRectForLayers) {
// the mask region.
// grand_child4 - outside parent's clip rect; the DrawableContentRect should
// be empty.
- //
const gfx::Transform identity_matrix;
- scoped_refptr<Layer> parent = Layer::Create(layer_settings());
- scoped_refptr<Layer> child = Layer::Create(layer_settings());
- scoped_refptr<Layer> grand_child1 = Layer::Create(layer_settings());
- scoped_refptr<Layer> grand_child2 = Layer::Create(layer_settings());
- scoped_refptr<Layer> grand_child3 = Layer::Create(layer_settings());
- scoped_refptr<Layer> grand_child4 = Layer::Create(layer_settings());
-
- parent->AddChild(child);
- child->AddChild(grand_child1);
- child->AddChild(grand_child2);
- child->AddChild(grand_child3);
- child->AddChild(grand_child4);
-
- host()->SetRootLayer(parent);
+ LayerImpl* parent = root_layer();
+ LayerImpl* child = AddChild<LayerImpl>(parent);
+ LayerImpl* grand_child1 = AddChild<LayerImpl>(child);
+ LayerImpl* grand_child2 = AddChild<LayerImpl>(child);
+ LayerImpl* grand_child3 = AddChild<LayerImpl>(child);
+ LayerImpl* grand_child4 = AddChild<LayerImpl>(child);
- SetLayerPropertiesForTesting(parent.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(500, 500),
- true,
- false);
- SetLayerPropertiesForTesting(child.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(20, 20),
- true,
- false);
- SetLayerPropertiesForTesting(grand_child1.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(5.f, 5.f),
- gfx::Size(10, 10),
- true,
- false);
- SetLayerPropertiesForTesting(grand_child2.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(15.f, 15.f),
- gfx::Size(10, 10),
- true,
- false);
- SetLayerPropertiesForTesting(grand_child3.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(15.f, 15.f),
- gfx::Size(10, 10),
- true,
- false);
- SetLayerPropertiesForTesting(grand_child4.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(45.f, 45.f),
- gfx::Size(10, 10),
- true,
- false);
+ SetLayerPropertiesForTesting(parent, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(500, 500), true, false,
+ true);
+ SetLayerPropertiesForTesting(child, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(20, 20), true, false,
+ true);
+ SetLayerPropertiesForTesting(grand_child1, identity_matrix, gfx::Point3F(),
+ gfx::PointF(5.f, 5.f), gfx::Size(10, 10), true,
+ false, false);
+ SetLayerPropertiesForTesting(grand_child2, identity_matrix, gfx::Point3F(),
+ gfx::PointF(15.f, 15.f), gfx::Size(10, 10), true,
+ false, false);
+ SetLayerPropertiesForTesting(grand_child3, identity_matrix, gfx::Point3F(),
+ gfx::PointF(15.f, 15.f), gfx::Size(10, 10), true,
+ false, false);
+ SetLayerPropertiesForTesting(grand_child4, identity_matrix, gfx::Point3F(),
+ gfx::PointF(45.f, 45.f), gfx::Size(10, 10), true,
+ false, false);
child->SetMasksToBounds(true);
grand_child3->SetMasksToBounds(true);
- // Force everyone to be a render surface.
+ // Force child to be a render surface.
child->SetOpacity(0.4f);
- grand_child1->SetOpacity(0.5f);
- grand_child2->SetOpacity(0.5f);
- grand_child3->SetOpacity(0.5f);
- grand_child4->SetOpacity(0.5f);
- RenderSurfaceLayerList render_surface_layer_list;
- LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
- parent.get(), parent->bounds(), &render_surface_layer_list);
- inputs.can_adjust_raster_scales = true;
- LayerTreeHostCommon::CalculateDrawProperties(&inputs);
+ ExecuteCalculateDrawProperties(parent);
EXPECT_EQ(gfx::Rect(5, 5, 10, 10), grand_child1->drawable_content_rect());
EXPECT_EQ(gfx::Rect(15, 15, 5, 5), grand_child3->drawable_content_rect());
@@ -2005,106 +1645,54 @@ TEST_F(LayerTreeHostCommonTest, ClipRectIsPropagatedCorrectlyToSurfaces) {
// clipping; instead the surface will enforce the clip for the entire subtree.
// They may still have a clip rect of their own layer bounds, however, if
// masksToBounds was true.
- const gfx::Transform identity_matrix;
- scoped_refptr<Layer> parent = Layer::Create(layer_settings());
- scoped_refptr<Layer> child = Layer::Create(layer_settings());
- scoped_refptr<Layer> grand_child1 = Layer::Create(layer_settings());
- scoped_refptr<Layer> grand_child2 = Layer::Create(layer_settings());
- scoped_refptr<Layer> grand_child3 = Layer::Create(layer_settings());
- scoped_refptr<Layer> grand_child4 = Layer::Create(layer_settings());
- scoped_refptr<LayerWithForcedDrawsContent> leaf_node1 =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
- scoped_refptr<LayerWithForcedDrawsContent> leaf_node2 =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
- scoped_refptr<LayerWithForcedDrawsContent> leaf_node3 =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
- scoped_refptr<LayerWithForcedDrawsContent> leaf_node4 =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
-
- parent->AddChild(child);
- child->AddChild(grand_child1);
- child->AddChild(grand_child2);
- child->AddChild(grand_child3);
- child->AddChild(grand_child4);
-
- host()->SetRootLayer(parent);
-
+ LayerImpl* parent = root_layer();
+ LayerImpl* child = AddChildToRoot<LayerImpl>();
+ LayerImpl* grand_child1 = AddChild<LayerImpl>(child);
+ LayerImpl* grand_child2 = AddChild<LayerImpl>(child);
+ LayerImpl* grand_child3 = AddChild<LayerImpl>(child);
+ LayerImpl* grand_child4 = AddChild<LayerImpl>(child);
// the leaf nodes ensure that these grand_children become render surfaces for
// this test.
- grand_child1->AddChild(leaf_node1);
- grand_child2->AddChild(leaf_node2);
- grand_child3->AddChild(leaf_node3);
- grand_child4->AddChild(leaf_node4);
+ LayerImpl* leaf_node1 = AddChild<LayerImpl>(grand_child1);
+ leaf_node1->SetDrawsContent(true);
+ LayerImpl* leaf_node2 = AddChild<LayerImpl>(grand_child2);
+ leaf_node2->SetDrawsContent(true);
+ LayerImpl* leaf_node3 = AddChild<LayerImpl>(grand_child3);
+ leaf_node3->SetDrawsContent(true);
+ LayerImpl* leaf_node4 = AddChild<LayerImpl>(grand_child4);
+ leaf_node4->SetDrawsContent(true);
- SetLayerPropertiesForTesting(parent.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(500, 500),
- true,
- false);
- SetLayerPropertiesForTesting(child.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(20, 20),
- true,
- false);
- SetLayerPropertiesForTesting(grand_child1.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(5.f, 5.f),
- gfx::Size(10, 10),
- true,
- false);
- SetLayerPropertiesForTesting(grand_child2.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(15.f, 15.f),
- gfx::Size(10, 10),
- true,
- false);
- SetLayerPropertiesForTesting(grand_child3.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(15.f, 15.f),
- gfx::Size(10, 10),
- true,
- false);
- SetLayerPropertiesForTesting(grand_child4.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(45.f, 45.f),
- gfx::Size(10, 10),
- true,
- false);
- SetLayerPropertiesForTesting(leaf_node1.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(10, 10),
- true,
+ const gfx::Transform identity_matrix;
+
+ SetLayerPropertiesForTesting(parent, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(500, 500), true, false,
+ true);
+ SetLayerPropertiesForTesting(child, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(20, 20), true, false,
+ true);
+ SetLayerPropertiesForTesting(grand_child1, identity_matrix, gfx::Point3F(),
+ gfx::PointF(5.f, 5.f), gfx::Size(10, 10), true,
+ false, true);
+ SetLayerPropertiesForTesting(grand_child2, identity_matrix, gfx::Point3F(),
+ gfx::PointF(15.f, 15.f), gfx::Size(10, 10), true,
+ false, true);
+ SetLayerPropertiesForTesting(grand_child3, identity_matrix, gfx::Point3F(),
+ gfx::PointF(15.f, 15.f), gfx::Size(10, 10), true,
+ false, true);
+ SetLayerPropertiesForTesting(grand_child4, identity_matrix, gfx::Point3F(),
+ gfx::PointF(45.f, 45.f), gfx::Size(10, 10), true,
+ false, true);
+ SetLayerPropertiesForTesting(leaf_node1, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(10, 10), true, false,
false);
- SetLayerPropertiesForTesting(leaf_node2.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(10, 10),
- true,
+ SetLayerPropertiesForTesting(leaf_node2, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(10, 10), true, false,
false);
- SetLayerPropertiesForTesting(leaf_node3.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(10, 10),
- true,
+ SetLayerPropertiesForTesting(leaf_node3, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(10, 10), true, false,
false);
- SetLayerPropertiesForTesting(leaf_node4.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(10, 10),
- true,
+ SetLayerPropertiesForTesting(leaf_node4, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(10, 10), true, false,
false);
child->SetMasksToBounds(true);
@@ -2113,21 +1701,13 @@ TEST_F(LayerTreeHostCommonTest, ClipRectIsPropagatedCorrectlyToSurfaces) {
// Force everyone to be a render surface.
child->SetOpacity(0.4f);
- child->SetForceRenderSurface(true);
grand_child1->SetOpacity(0.5f);
- grand_child1->SetForceRenderSurface(true);
grand_child2->SetOpacity(0.5f);
- grand_child2->SetForceRenderSurface(true);
grand_child3->SetOpacity(0.5f);
- grand_child3->SetForceRenderSurface(true);
grand_child4->SetOpacity(0.5f);
- grand_child4->SetForceRenderSurface(true);
- RenderSurfaceLayerList render_surface_layer_list;
- LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
- parent.get(), parent->bounds(), &render_surface_layer_list);
- inputs.can_adjust_raster_scales = true;
- LayerTreeHostCommon::CalculateDrawProperties(&inputs);
+ ExecuteCalculateDrawProperties(parent);
+
ASSERT_TRUE(grand_child1->render_surface());
ASSERT_TRUE(grand_child2->render_surface());
ASSERT_TRUE(grand_child3->render_surface());
@@ -2235,46 +1815,14 @@ TEST_F(LayerTreeHostCommonTest, AnimationsForRenderSurfaceHierarchy) {
EXPECT_EQ(render_surface2, child_of_rs2->render_target());
EXPECT_EQ(render_surface2, grand_child_of_rs2->render_target());
- // Verify draw_opacity_is_animating values
- EXPECT_FALSE(parent->draw_opacity_is_animating());
- EXPECT_FALSE(child_of_root->draw_opacity_is_animating());
- EXPECT_TRUE(grand_child_of_root->draw_opacity_is_animating());
- EXPECT_FALSE(render_surface1->draw_opacity_is_animating());
- EXPECT_TRUE(render_surface1->render_surface()->draw_opacity_is_animating());
- EXPECT_FALSE(child_of_rs1->draw_opacity_is_animating());
- EXPECT_FALSE(grand_child_of_rs1->draw_opacity_is_animating());
- EXPECT_FALSE(render_surface2->draw_opacity_is_animating());
- EXPECT_FALSE(render_surface2->render_surface()->draw_opacity_is_animating());
- EXPECT_FALSE(child_of_rs2->draw_opacity_is_animating());
- EXPECT_FALSE(grand_child_of_rs2->draw_opacity_is_animating());
-
- // Verify draw_transform_is_animating values
- EXPECT_FALSE(parent->draw_transform_is_animating());
- EXPECT_FALSE(child_of_root->draw_transform_is_animating());
- EXPECT_TRUE(grand_child_of_root->draw_transform_is_animating());
- EXPECT_FALSE(render_surface1->draw_transform_is_animating());
- EXPECT_FALSE(render_surface1->render_surface()
- ->target_surface_transforms_are_animating());
- EXPECT_FALSE(child_of_rs1->draw_transform_is_animating());
- EXPECT_FALSE(grand_child_of_rs1->draw_transform_is_animating());
- EXPECT_FALSE(render_surface2->draw_transform_is_animating());
- EXPECT_TRUE(render_surface2->render_surface()
- ->target_surface_transforms_are_animating());
- EXPECT_FALSE(child_of_rs2->draw_transform_is_animating());
- EXPECT_TRUE(grand_child_of_rs2->draw_transform_is_animating());
-
// Verify screen_space_transform_is_animating values
EXPECT_FALSE(parent->screen_space_transform_is_animating());
EXPECT_FALSE(child_of_root->screen_space_transform_is_animating());
EXPECT_TRUE(grand_child_of_root->screen_space_transform_is_animating());
EXPECT_FALSE(render_surface1->screen_space_transform_is_animating());
- EXPECT_FALSE(render_surface1->render_surface()
- ->screen_space_transforms_are_animating());
EXPECT_FALSE(child_of_rs1->screen_space_transform_is_animating());
EXPECT_FALSE(grand_child_of_rs1->screen_space_transform_is_animating());
EXPECT_TRUE(render_surface2->screen_space_transform_is_animating());
- EXPECT_TRUE(render_surface2->render_surface()
- ->screen_space_transforms_are_animating());
EXPECT_TRUE(child_of_rs2->screen_space_transform_is_animating());
EXPECT_TRUE(grand_child_of_rs2->screen_space_transform_is_animating());
@@ -2302,6 +1850,75 @@ TEST_F(LayerTreeHostCommonTest, AnimationsForRenderSurfaceHierarchy) {
5.0, grand_child_of_rs2->screen_space_transform().matrix().get(1, 3));
}
+TEST_F(LayerTreeHostCommonTest, LargeTransforms) {
+ LayerImpl* parent = root_layer();
+ LayerImpl* child = AddChildToRoot<LayerImpl>();
+ LayerImpl* grand_child = AddChild<LayerImpl>(child);
+
+ grand_child->SetDrawsContent(true);
+
+ gfx::Transform large_transform;
+ large_transform.Scale(SkDoubleToMScalar(1e37), SkDoubleToMScalar(1e37));
+
+ gfx::Transform identity;
+
+ SetLayerPropertiesForTesting(parent, identity, gfx::Point3F(), gfx::PointF(),
+ gfx::Size(10, 10), true, false, true);
+ SetLayerPropertiesForTesting(child, large_transform, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(10, 10), true, false,
+ false);
+ SetLayerPropertiesForTesting(grand_child, large_transform, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(10, 10), true, false,
+ false);
+ ExecuteCalculateDrawProperties(parent);
+
+ EXPECT_EQ(gfx::Rect(), grand_child->visible_layer_rect());
+}
+
+TEST_F(LayerTreeHostCommonTest,
+ ScreenSpaceTransformIsAnimatingWithDelayedAnimation) {
+ LayerImpl* parent = root_layer();
+ LayerImpl* child = AddChild<LayerImpl>(parent);
+ LayerImpl* grand_child = AddChild<LayerImpl>(child);
+ LayerImpl* great_grand_child = AddChild<LayerImpl>(grand_child);
+
+ parent->SetDrawsContent(true);
+ child->SetDrawsContent(true);
+ grand_child->SetDrawsContent(true);
+ great_grand_child->SetDrawsContent(true);
+
+ gfx::Transform identity;
+
+ SetLayerPropertiesForTesting(parent, identity, gfx::Point3F(), gfx::PointF(),
+ gfx::Size(10, 10), true, false, true);
+ SetLayerPropertiesForTesting(child, identity, gfx::Point3F(), gfx::PointF(),
+ gfx::Size(10, 10), true, false, false);
+ SetLayerPropertiesForTesting(grand_child, identity, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(10, 10), true, false,
+ false);
+ SetLayerPropertiesForTesting(great_grand_child, identity, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(10, 10), true, false,
+ false);
+
+ // Add a transform animation with a start delay to |grand_child|.
+ scoped_ptr<Animation> animation = Animation::Create(
+ scoped_ptr<AnimationCurve>(new FakeTransformTransition(1.0)).Pass(), 0, 1,
+ Animation::TRANSFORM);
+ animation->set_fill_mode(Animation::FILL_MODE_NONE);
+ animation->set_time_offset(base::TimeDelta::FromMilliseconds(-1000));
+ grand_child->layer_animation_controller()->AddAnimation(animation.Pass());
+
+ ExecuteCalculateDrawProperties(parent);
+
+ EXPECT_FALSE(parent->screen_space_transform_is_animating());
+ EXPECT_FALSE(child->screen_space_transform_is_animating());
+
+ EXPECT_FALSE(grand_child->TransformIsAnimating());
+ EXPECT_TRUE(grand_child->HasPotentiallyRunningTransformAnimation());
+ EXPECT_TRUE(grand_child->screen_space_transform_is_animating());
+ EXPECT_TRUE(great_grand_child->screen_space_transform_is_animating());
+}
+
TEST_F(LayerTreeHostCommonTest, VisibleRectForIdentityTransform) {
// Test the calculateVisibleRect() function works correctly for identity
// transforms.
@@ -2574,8 +2191,8 @@ TEST_F(LayerTreeHostCommonTest, VisibleRectForPerspectiveUnprojection) {
// Sanity check that un-projection does indeed cause w < 0, otherwise this
// code is not testing the intended scenario.
bool clipped;
- gfx::RectF clipped_rect =
- MathUtil::MapClippedRect(layer_to_surface_transform, layer_content_rect);
+ gfx::RectF clipped_rect = MathUtil::MapClippedRect(
+ layer_to_surface_transform, gfx::RectF(layer_content_rect));
MathUtil::ProjectQuad(
Inverse(layer_to_surface_transform), gfx::QuadF(clipped_rect), &clipped);
ASSERT_TRUE(clipped);
@@ -2591,153 +2208,103 @@ TEST_F(LayerTreeHostCommonTest, VisibleRectForPerspectiveUnprojection) {
TEST_F(LayerTreeHostCommonTest,
VisibleRectsForPositionedRootLayerClippedByViewport) {
- scoped_refptr<Layer> root =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
- host()->SetRootLayer(root);
+ LayerImpl* root = root_layer();
+ root->SetDrawsContent(true);
gfx::Transform identity_matrix;
// Root layer is positioned at (60, 70). The default device viewport size
// is (0, 0, 100x100) in target space. So the root layer's visible rect
// will be clipped by the viewport to be (0, 0, 40x30) in layer's space.
- SetLayerPropertiesForTesting(root.get(), identity_matrix, gfx::Point3F(),
+ SetLayerPropertiesForTesting(root, identity_matrix, gfx::Point3F(),
gfx::PointF(60, 70), gfx::Size(100, 100), true,
- false);
- ExecuteCalculateDrawProperties(root.get());
+ false, true);
+ ExecuteCalculateDrawProperties(root);
- EXPECT_EQ(gfx::Rect(0, 0, 100, 100),
+ EXPECT_EQ(gfx::RectF(100.f, 100.f),
root->render_surface()->DrawableContentRect());
// In target space, not clipped.
EXPECT_EQ(gfx::Rect(60, 70, 100, 100), root->drawable_content_rect());
// In layer space, clipped.
- EXPECT_EQ(gfx::Rect(0, 0, 40, 30), root->visible_layer_rect());
+ EXPECT_EQ(gfx::Rect(40, 30), root->visible_layer_rect());
}
TEST_F(LayerTreeHostCommonTest, DrawableAndVisibleContentRectsForSimpleLayers) {
- scoped_refptr<Layer> root = Layer::Create(layer_settings());
- scoped_refptr<LayerWithForcedDrawsContent> child1 =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
- scoped_refptr<LayerWithForcedDrawsContent> child2 =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
- scoped_refptr<LayerWithForcedDrawsContent> child3 =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
- root->AddChild(child1);
- root->AddChild(child2);
- root->AddChild(child3);
-
- host()->SetRootLayer(root);
+ LayerImpl* root = root_layer();
+ LayerImpl* child1_layer = AddChildToRoot<LayerImpl>();
+ child1_layer->SetDrawsContent(true);
+ LayerImpl* child2_layer = AddChildToRoot<LayerImpl>();
+ child2_layer->SetDrawsContent(true);
+ LayerImpl* child3_layer = AddChildToRoot<LayerImpl>();
+ child3_layer->SetDrawsContent(true);
gfx::Transform identity_matrix;
- SetLayerPropertiesForTesting(root.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(100, 100),
- true,
- false);
- SetLayerPropertiesForTesting(child1.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(50, 50),
- true,
- false);
- SetLayerPropertiesForTesting(child2.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(75.f, 75.f),
- gfx::Size(50, 50),
- true,
- false);
- SetLayerPropertiesForTesting(child3.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(125.f, 125.f),
- gfx::Size(50, 50),
- true,
+ SetLayerPropertiesForTesting(root, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(100, 100), true, false,
+ true);
+ SetLayerPropertiesForTesting(child1_layer, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(50, 50), true, false,
false);
+ SetLayerPropertiesForTesting(child2_layer, identity_matrix, gfx::Point3F(),
+ gfx::PointF(75.f, 75.f), gfx::Size(50, 50), true,
+ false, false);
+ SetLayerPropertiesForTesting(child3_layer, identity_matrix, gfx::Point3F(),
+ gfx::PointF(125.f, 125.f), gfx::Size(50, 50),
+ true, false, false);
- ExecuteCalculateDrawProperties(root.get());
+ ExecuteCalculateDrawProperties(root);
- EXPECT_EQ(gfx::Rect(0, 0, 100, 100),
+ EXPECT_EQ(gfx::RectF(100.f, 100.f),
root->render_surface()->DrawableContentRect());
- EXPECT_EQ(gfx::Rect(0, 0, 100, 100), root->drawable_content_rect());
+ EXPECT_EQ(gfx::Rect(100, 100), root->drawable_content_rect());
// Layers that do not draw content should have empty visible_layer_rects.
EXPECT_EQ(gfx::Rect(0, 0, 0, 0), root->visible_layer_rect());
// layer visible_layer_rects are clipped by their target surface.
- EXPECT_EQ(gfx::Rect(0, 0, 50, 50), child1->visible_layer_rect());
- EXPECT_EQ(gfx::Rect(0, 0, 25, 25), child2->visible_layer_rect());
- EXPECT_TRUE(child3->visible_layer_rect().IsEmpty());
+ EXPECT_EQ(gfx::Rect(0, 0, 50, 50), child1_layer->visible_layer_rect());
+ EXPECT_EQ(gfx::Rect(0, 0, 25, 25), child2_layer->visible_layer_rect());
+ EXPECT_TRUE(child3_layer->visible_layer_rect().IsEmpty());
// layer drawable_content_rects are not clipped.
- EXPECT_EQ(gfx::Rect(0, 0, 50, 50), child1->drawable_content_rect());
- EXPECT_EQ(gfx::Rect(75, 75, 50, 50), child2->drawable_content_rect());
- EXPECT_EQ(gfx::Rect(125, 125, 50, 50), child3->drawable_content_rect());
+ EXPECT_EQ(gfx::Rect(0, 0, 50, 50), child1_layer->drawable_content_rect());
+ EXPECT_EQ(gfx::Rect(75, 75, 50, 50), child2_layer->drawable_content_rect());
+ EXPECT_EQ(gfx::Rect(125, 125, 50, 50), child3_layer->drawable_content_rect());
}
TEST_F(LayerTreeHostCommonTest,
DrawableAndVisibleContentRectsForLayersClippedByLayer) {
- scoped_refptr<Layer> root = Layer::Create(layer_settings());
- scoped_refptr<Layer> child = Layer::Create(layer_settings());
- scoped_refptr<LayerWithForcedDrawsContent> grand_child1 =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
- scoped_refptr<LayerWithForcedDrawsContent> grand_child2 =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
- scoped_refptr<LayerWithForcedDrawsContent> grand_child3 =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
- root->AddChild(child);
- child->AddChild(grand_child1);
- child->AddChild(grand_child2);
- child->AddChild(grand_child3);
-
- host()->SetRootLayer(root);
+ LayerImpl* root = root_layer();
+ LayerImpl* child = AddChildToRoot<LayerImpl>();
+ LayerImpl* grand_child1 = AddChild<LayerImpl>(child);
+ grand_child1->SetDrawsContent(true);
+ LayerImpl* grand_child2 = AddChild<LayerImpl>(child);
+ grand_child2->SetDrawsContent(true);
+ LayerImpl* grand_child3 = AddChild<LayerImpl>(child);
+ grand_child3->SetDrawsContent(true);
gfx::Transform identity_matrix;
- SetLayerPropertiesForTesting(root.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(100, 100),
- true,
- false);
- SetLayerPropertiesForTesting(child.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(100, 100),
- true,
- false);
- SetLayerPropertiesForTesting(grand_child1.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(5.f, 5.f),
- gfx::Size(50, 50),
- true,
- false);
- SetLayerPropertiesForTesting(grand_child2.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(75.f, 75.f),
- gfx::Size(50, 50),
- true,
- false);
- SetLayerPropertiesForTesting(grand_child3.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(125.f, 125.f),
- gfx::Size(50, 50),
- true,
+ SetLayerPropertiesForTesting(root, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(100, 100), true, false,
+ true);
+ SetLayerPropertiesForTesting(child, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(100, 100), true, false,
false);
+ SetLayerPropertiesForTesting(grand_child1, identity_matrix, gfx::Point3F(),
+ gfx::PointF(5.f, 5.f), gfx::Size(50, 50), true,
+ false, false);
+ SetLayerPropertiesForTesting(grand_child2, identity_matrix, gfx::Point3F(),
+ gfx::PointF(75.f, 75.f), gfx::Size(50, 50), true,
+ false, false);
+ SetLayerPropertiesForTesting(grand_child3, identity_matrix, gfx::Point3F(),
+ gfx::PointF(125.f, 125.f), gfx::Size(50, 50),
+ true, false, false);
child->SetMasksToBounds(true);
- ExecuteCalculateDrawProperties(root.get());
-
- ASSERT_FALSE(child->render_surface());
+ ExecuteCalculateDrawProperties(root);
- EXPECT_EQ(gfx::Rect(0, 0, 100, 100),
+ EXPECT_EQ(gfx::RectF(100.f, 100.f),
root->render_surface()->DrawableContentRect());
- EXPECT_EQ(gfx::Rect(0, 0, 100, 100), root->drawable_content_rect());
+ EXPECT_EQ(gfx::Rect(100, 100), root->drawable_content_rect());
// Layers that do not draw content should have empty visible content rects.
EXPECT_EQ(gfx::Rect(0, 0, 0, 0), root->visible_layer_rect());
@@ -2788,75 +2355,48 @@ TEST_F(LayerTreeHostCommonTest, VisibleContentRectWithClippingAndScaling) {
TEST_F(LayerTreeHostCommonTest,
DrawableAndVisibleContentRectsForLayersInUnclippedRenderSurface) {
- scoped_refptr<Layer> root = Layer::Create(layer_settings());
- scoped_refptr<Layer> render_surface1 = Layer::Create(layer_settings());
- scoped_refptr<LayerWithForcedDrawsContent> child1 =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
- scoped_refptr<LayerWithForcedDrawsContent> child2 =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
- scoped_refptr<LayerWithForcedDrawsContent> child3 =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
- root->AddChild(render_surface1);
- render_surface1->AddChild(child1);
- render_surface1->AddChild(child2);
- render_surface1->AddChild(child3);
-
- host()->SetRootLayer(root);
+ LayerImpl* root = root_layer();
+ LayerImpl* render_surface = AddChildToRoot<LayerImpl>();
+ LayerImpl* child1 = AddChild<LayerImpl>(render_surface);
+ child1->SetDrawsContent(true);
+ LayerImpl* child2 = AddChild<LayerImpl>(render_surface);
+ child2->SetDrawsContent(true);
+ LayerImpl* child3 = AddChild<LayerImpl>(render_surface);
+ child3->SetDrawsContent(true);
gfx::Transform identity_matrix;
- SetLayerPropertiesForTesting(root.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(100, 100),
- true,
- false);
- SetLayerPropertiesForTesting(render_surface1.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(3, 4),
- true,
- false);
- SetLayerPropertiesForTesting(child1.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(5.f, 5.f),
- gfx::Size(50, 50),
- true,
- false);
- SetLayerPropertiesForTesting(child2.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(75.f, 75.f),
- gfx::Size(50, 50),
- true,
- false);
- SetLayerPropertiesForTesting(child3.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(125.f, 125.f),
- gfx::Size(50, 50),
- true,
- false);
+ SetLayerPropertiesForTesting(root, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(100, 100), true, false,
+ true);
+ SetLayerPropertiesForTesting(render_surface, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(3, 4), true, false,
+ true);
+ SetLayerPropertiesForTesting(child1, identity_matrix, gfx::Point3F(),
+ gfx::PointF(5.f, 5.f), gfx::Size(50, 50), true,
+ false, false);
+ SetLayerPropertiesForTesting(child2, identity_matrix, gfx::Point3F(),
+ gfx::PointF(75.f, 75.f), gfx::Size(50, 50), true,
+ false, false);
+ SetLayerPropertiesForTesting(child3, identity_matrix, gfx::Point3F(),
+ gfx::PointF(125.f, 125.f), gfx::Size(50, 50),
+ true, false, false);
- render_surface1->SetForceRenderSurface(true);
- ExecuteCalculateDrawProperties(root.get());
+ ExecuteCalculateDrawProperties(root);
- ASSERT_TRUE(render_surface1->render_surface());
+ ASSERT_TRUE(render_surface->render_surface());
- EXPECT_EQ(gfx::Rect(0, 0, 100, 100),
+ EXPECT_EQ(gfx::RectF(100.f, 100.f),
root->render_surface()->DrawableContentRect());
- EXPECT_EQ(gfx::Rect(0, 0, 100, 100), root->drawable_content_rect());
+ EXPECT_EQ(gfx::Rect(100, 100), root->drawable_content_rect());
// Layers that do not draw content should have empty visible content rects.
EXPECT_EQ(gfx::Rect(0, 0, 0, 0), root->visible_layer_rect());
- EXPECT_EQ(gfx::Rect(0, 0, 0, 0), render_surface1->visible_layer_rect());
+ EXPECT_EQ(gfx::Rect(0, 0, 0, 0), render_surface->visible_layer_rect());
// An unclipped surface grows its DrawableContentRect to include all drawable
// regions of the subtree.
- EXPECT_EQ(gfx::Rect(5, 5, 170, 170),
- render_surface1->render_surface()->DrawableContentRect());
+ EXPECT_EQ(gfx::RectF(5.f, 5.f, 170.f, 170.f),
+ render_surface->render_surface()->DrawableContentRect());
// All layers that draw content into the unclipped surface are also unclipped.
EXPECT_EQ(gfx::Rect(0, 0, 50, 50), child1->visible_layer_rect());
@@ -2870,36 +2410,32 @@ TEST_F(LayerTreeHostCommonTest,
TEST_F(LayerTreeHostCommonTest,
VisibleContentRectsForClippedSurfaceWithEmptyClip) {
- scoped_refptr<Layer> root = Layer::Create(layer_settings());
- scoped_refptr<LayerWithForcedDrawsContent> child1 =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
- scoped_refptr<LayerWithForcedDrawsContent> child2 =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
- scoped_refptr<LayerWithForcedDrawsContent> child3 =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
- root->AddChild(child1);
- root->AddChild(child2);
- root->AddChild(child3);
-
- host()->SetRootLayer(root);
+ LayerImpl* root = root_layer();
+ LayerImpl* child1 = AddChild<LayerImpl>(root);
+ LayerImpl* child2 = AddChild<LayerImpl>(root);
+ LayerImpl* child3 = AddChild<LayerImpl>(root);
+ child1->SetDrawsContent(true);
+ child2->SetDrawsContent(true);
+ child3->SetDrawsContent(true);
gfx::Transform identity_matrix;
- SetLayerPropertiesForTesting(root.get(), identity_matrix, gfx::Point3F(),
- gfx::PointF(), gfx::Size(100, 100), true, false);
- SetLayerPropertiesForTesting(child1.get(), identity_matrix, gfx::Point3F(),
+ SetLayerPropertiesForTesting(root, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(100, 100), true, false,
+ true);
+ SetLayerPropertiesForTesting(child1, identity_matrix, gfx::Point3F(),
gfx::PointF(5.f, 5.f), gfx::Size(50, 50), true,
- false);
- SetLayerPropertiesForTesting(child2.get(), identity_matrix, gfx::Point3F(),
+ false, false);
+ SetLayerPropertiesForTesting(child2, identity_matrix, gfx::Point3F(),
gfx::PointF(75.f, 75.f), gfx::Size(50, 50), true,
- false);
- SetLayerPropertiesForTesting(child3.get(), identity_matrix, gfx::Point3F(),
+ false, false);
+ SetLayerPropertiesForTesting(child3, identity_matrix, gfx::Point3F(),
gfx::PointF(125.f, 125.f), gfx::Size(50, 50),
- true, false);
+ true, false, false);
- RenderSurfaceLayerList render_surface_layer_list;
+ LayerImplList render_surface_layer_list_impl;
// Now set the root render surface an empty clip.
- LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
- root.get(), gfx::Size(), &render_surface_layer_list);
+ LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs(
+ root, gfx::Size(), &render_surface_layer_list_impl);
LayerTreeHostCommon::CalculateDrawProperties(&inputs);
ASSERT_TRUE(root->render_surface());
@@ -2919,34 +2455,23 @@ TEST_F(LayerTreeHostCommonTest,
TEST_F(LayerTreeHostCommonTest,
DrawableAndVisibleContentRectsForLayersWithUninvertibleTransform) {
- scoped_refptr<Layer> root = Layer::Create(layer_settings());
- scoped_refptr<LayerWithForcedDrawsContent> child =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
- root->AddChild(child);
-
- host()->SetRootLayer(root);
+ LayerImpl* root = root_layer();
+ LayerImpl* child = AddChildToRoot<LayerImpl>();
+ child->SetDrawsContent(true);
// Case 1: a truly degenerate matrix
gfx::Transform identity_matrix;
gfx::Transform uninvertible_matrix(0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
ASSERT_FALSE(uninvertible_matrix.IsInvertible());
- SetLayerPropertiesForTesting(root.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(100, 100),
- true,
- false);
- SetLayerPropertiesForTesting(child.get(),
- uninvertible_matrix,
- gfx::Point3F(),
- gfx::PointF(5.f, 5.f),
- gfx::Size(50, 50),
- true,
- false);
+ SetLayerPropertiesForTesting(root, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(100, 100), true, false,
+ true);
+ SetLayerPropertiesForTesting(child, uninvertible_matrix, gfx::Point3F(),
+ gfx::PointF(5.f, 5.f), gfx::Size(50, 50), true,
+ false, false);
- ExecuteCalculateDrawProperties(root.get());
+ ExecuteCalculateDrawProperties(root);
EXPECT_TRUE(child->visible_layer_rect().IsEmpty());
EXPECT_TRUE(child->drawable_content_rect().IsEmpty());
@@ -2957,15 +2482,11 @@ TEST_F(LayerTreeHostCommonTest,
uninvertible_matrix.matrix().set(2, 2, 0.0);
ASSERT_FALSE(uninvertible_matrix.IsInvertible());
- SetLayerPropertiesForTesting(child.get(),
- uninvertible_matrix,
- gfx::Point3F(),
- gfx::PointF(5.f, 5.f),
- gfx::Size(50, 50),
- true,
- false);
+ SetLayerPropertiesForTesting(child, uninvertible_matrix, gfx::Point3F(),
+ gfx::PointF(5.f, 5.f), gfx::Size(50, 50), true,
+ false, false);
- ExecuteCalculateDrawProperties(root.get());
+ ExecuteCalculateDrawProperties(root);
EXPECT_TRUE(child->visible_layer_rect().IsEmpty());
EXPECT_TRUE(child->drawable_content_rect().IsEmpty());
@@ -2976,21 +2497,125 @@ TEST_F(LayerTreeHostCommonTest,
uninvertible_matrix.matrix().set(2, 2, 0.0);
ASSERT_FALSE(uninvertible_matrix.IsInvertible());
- SetLayerPropertiesForTesting(child.get(),
- uninvertible_matrix,
- gfx::Point3F(),
- gfx::PointF(5.f, 5.f),
- gfx::Size(50, 50),
- true,
- false);
+ SetLayerPropertiesForTesting(child, uninvertible_matrix, gfx::Point3F(),
+ gfx::PointF(5.f, 5.f), gfx::Size(50, 50), true,
+ false, false);
- ExecuteCalculateDrawProperties(root.get());
+ ExecuteCalculateDrawProperties(root);
EXPECT_TRUE(child->visible_layer_rect().IsEmpty());
EXPECT_TRUE(child->drawable_content_rect().IsEmpty());
}
TEST_F(LayerTreeHostCommonTest,
+ VisibleContentRectForLayerWithUninvertibleDrawTransform) {
+ LayerImpl* root = root_layer();
+ LayerImpl* child = AddChildToRoot<LayerImpl>();
+ LayerImpl* grand_child = AddChild<LayerImpl>(child);
+ child->SetDrawsContent(true);
+ grand_child->SetDrawsContent(true);
+
+ gfx::Transform identity_matrix;
+
+ gfx::Transform perspective;
+ perspective.ApplyPerspectiveDepth(SkDoubleToMScalar(1e-12));
+
+ gfx::Transform rotation;
+ rotation.RotateAboutYAxis(45.0);
+
+ SetLayerPropertiesForTesting(root, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(100, 100), true, false,
+ true);
+ SetLayerPropertiesForTesting(child, perspective, gfx::Point3F(),
+ gfx::PointF(10.f, 10.f), gfx::Size(100, 100),
+ false, true, false);
+ SetLayerPropertiesForTesting(grand_child, rotation, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(100, 100), false, true,
+ false);
+
+ ExecuteCalculateDrawProperties(root);
+
+ // Though all layers have invertible transforms, matrix multiplication using
+ // floating-point math makes the draw transform uninvertible.
+ EXPECT_FALSE(grand_child->draw_transform().IsInvertible());
+
+ // CalcDrawProps only skips a subtree when a layer's own transform is
+ // uninvertible, not when its draw transform is invertible, since CDP makes
+ // skipping decisions before computing a layer's draw transform. Property
+ // trees make skipping decisions after computing draw transforms, so could be
+ // made to skip layers with an uninvertible draw transform (once CDP is
+ // deleted).
+ EXPECT_EQ(gfx::Rect(grand_child->bounds()),
+ grand_child->visible_layer_rect());
+}
+
+TEST_F(LayerTreeHostCommonTest,
+ OcclusionForLayerWithUninvertibleDrawTransform) {
+ FakeImplProxy proxy;
+ TestSharedBitmapManager shared_bitmap_manager;
+ TestTaskGraphRunner task_graph_runner;
+ scoped_ptr<OutputSurface> output_surface = FakeOutputSurface::Create3d();
+ FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager,
+ &task_graph_runner);
+ scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl.active_tree(), 1);
+ scoped_ptr<LayerImpl> child = LayerImpl::Create(host_impl.active_tree(), 2);
+ scoped_ptr<LayerImpl> grand_child =
+ LayerImpl::Create(host_impl.active_tree(), 3);
+ scoped_ptr<LayerImpl> occluding_child =
+ LayerImpl::Create(host_impl.active_tree(), 4);
+ child->SetDrawsContent(true);
+ grand_child->SetDrawsContent(true);
+ occluding_child->SetDrawsContent(true);
+ occluding_child->SetContentsOpaque(true);
+
+ gfx::Transform identity_matrix;
+ gfx::Transform perspective;
+ perspective.ApplyPerspectiveDepth(SkDoubleToMScalar(1e-12));
+
+ gfx::Transform rotation;
+ rotation.RotateAboutYAxis(45.0);
+
+ SetLayerPropertiesForTesting(root.get(), identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(1000, 1000), true,
+ false, true);
+ SetLayerPropertiesForTesting(child.get(), perspective, gfx::Point3F(),
+ gfx::PointF(10.f, 10.f), gfx::Size(300, 300),
+ false, true, false);
+ SetLayerPropertiesForTesting(grand_child.get(), rotation, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(200, 200), false, true,
+ false);
+ SetLayerPropertiesForTesting(occluding_child.get(), identity_matrix,
+ gfx::Point3F(), gfx::PointF(),
+ gfx::Size(200, 200), false, false, false);
+
+ host_impl.SetViewportSize(root->bounds());
+
+ child->AddChild(grand_child.Pass());
+ root->AddChild(child.Pass());
+ root->AddChild(occluding_child.Pass());
+ host_impl.active_tree()->SetRootLayer(root.Pass());
+ host_impl.InitializeRenderer(output_surface.get());
+ bool update_lcd_text = false;
+ host_impl.active_tree()->UpdateDrawProperties(update_lcd_text);
+
+ LayerImpl* grand_child_ptr =
+ host_impl.active_tree()->root_layer()->children()[0]->children()[0];
+
+ // Though all layers have invertible transforms, matrix multiplication using
+ // floating-point math makes the draw transform uninvertible.
+ EXPECT_FALSE(grand_child_ptr->draw_transform().IsInvertible());
+
+ // Since |grand_child| has an uninvertible draw transform, it is treated as
+ // unoccluded (even though |occluding_child| comes later in draw order, and
+ // hence potentially occludes it).
+ gfx::Rect layer_bounds = gfx::Rect(grand_child_ptr->bounds());
+ EXPECT_EQ(
+ layer_bounds,
+ grand_child_ptr->draw_properties()
+ .occlusion_in_content_space.GetUnoccludedContentRect(layer_bounds));
+}
+
+TEST_F(LayerTreeHostCommonTest,
SingularTransformDoesNotPreventClearingDrawProperties) {
scoped_refptr<Layer> root = Layer::Create(layer_settings());
scoped_refptr<LayerWithForcedDrawsContent> child =
@@ -3065,76 +2690,50 @@ TEST_F(LayerTreeHostCommonTest,
TEST_F(LayerTreeHostCommonTest,
DrawableAndVisibleContentRectsForLayersInClippedRenderSurface) {
- scoped_refptr<Layer> root = Layer::Create(layer_settings());
- scoped_refptr<Layer> render_surface1 = Layer::Create(layer_settings());
- scoped_refptr<LayerWithForcedDrawsContent> child1 =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
- scoped_refptr<LayerWithForcedDrawsContent> child2 =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
- scoped_refptr<LayerWithForcedDrawsContent> child3 =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
- root->AddChild(render_surface1);
- render_surface1->AddChild(child1);
- render_surface1->AddChild(child2);
- render_surface1->AddChild(child3);
-
- host()->SetRootLayer(root);
+ LayerImpl* root = root_layer();
+ LayerImpl* render_surface = AddChildToRoot<LayerImpl>();
+ LayerImpl* child1 = AddChild<LayerImpl>(render_surface);
+ child1->SetDrawsContent(true);
+ LayerImpl* child2 = AddChild<LayerImpl>(render_surface);
+ child2->SetDrawsContent(true);
+ LayerImpl* child3 = AddChild<LayerImpl>(render_surface);
+ child3->SetDrawsContent(true);
gfx::Transform identity_matrix;
- SetLayerPropertiesForTesting(root.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(100, 100),
- true,
- false);
- SetLayerPropertiesForTesting(render_surface1.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(3, 4),
- true,
- false);
- SetLayerPropertiesForTesting(child1.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(5.f, 5.f),
- gfx::Size(50, 50),
- true,
- false);
- SetLayerPropertiesForTesting(child2.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(75.f, 75.f),
- gfx::Size(50, 50),
- true,
- false);
- SetLayerPropertiesForTesting(child3.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(125.f, 125.f),
- gfx::Size(50, 50),
- true,
- false);
+ SetLayerPropertiesForTesting(root, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(100, 100), true, false,
+ true);
+ SetLayerPropertiesForTesting(render_surface, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(3, 4), true, false,
+ true);
+ SetLayerPropertiesForTesting(child1, identity_matrix, gfx::Point3F(),
+ gfx::PointF(5.f, 5.f), gfx::Size(50, 50), true,
+ false, false);
+ SetLayerPropertiesForTesting(child2, identity_matrix, gfx::Point3F(),
+ gfx::PointF(75.f, 75.f), gfx::Size(50, 50), true,
+ false, false);
+ SetLayerPropertiesForTesting(child3, identity_matrix, gfx::Point3F(),
+ gfx::PointF(125.f, 125.f), gfx::Size(50, 50),
+ true, false, false);
root->SetMasksToBounds(true);
- render_surface1->SetForceRenderSurface(true);
- ExecuteCalculateDrawProperties(root.get());
- ASSERT_TRUE(render_surface1->render_surface());
+ ExecuteCalculateDrawProperties(root);
- EXPECT_EQ(gfx::Rect(0, 0, 100, 100),
+ ASSERT_TRUE(render_surface->render_surface());
+
+ EXPECT_EQ(gfx::RectF(100.f, 100.f),
root->render_surface()->DrawableContentRect());
- EXPECT_EQ(gfx::Rect(0, 0, 100, 100), root->drawable_content_rect());
+ EXPECT_EQ(gfx::Rect(100, 100), root->drawable_content_rect());
// Layers that do not draw content should have empty visible content rects.
EXPECT_EQ(gfx::Rect(0, 0, 0, 0), root->visible_layer_rect());
- EXPECT_EQ(gfx::Rect(0, 0, 0, 0), render_surface1->visible_layer_rect());
+ EXPECT_EQ(gfx::Rect(0, 0, 0, 0), render_surface->visible_layer_rect());
// A clipped surface grows its DrawableContentRect to include all drawable
// regions of the subtree, but also gets clamped by the ancestor's clip.
- EXPECT_EQ(gfx::Rect(5, 5, 95, 95),
- render_surface1->render_surface()->DrawableContentRect());
+ EXPECT_EQ(gfx::RectF(5.f, 5.f, 95.f, 95.f),
+ render_surface->render_surface()->DrawableContentRect());
// All layers that draw content into the surface have their visible content
// rect clipped by the surface clip rect.
@@ -3151,78 +2750,46 @@ TEST_F(LayerTreeHostCommonTest,
TEST_F(LayerTreeHostCommonTest,
DrawableAndVisibleContentRectsForSurfaceHierarchy) {
// Check that clipping does not propagate down surfaces.
- scoped_refptr<Layer> root = Layer::Create(layer_settings());
- scoped_refptr<Layer> render_surface1 = Layer::Create(layer_settings());
- scoped_refptr<Layer> render_surface2 = Layer::Create(layer_settings());
- scoped_refptr<LayerWithForcedDrawsContent> child1 =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
- scoped_refptr<LayerWithForcedDrawsContent> child2 =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
- scoped_refptr<LayerWithForcedDrawsContent> child3 =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
- root->AddChild(render_surface1);
- render_surface1->AddChild(render_surface2);
- render_surface2->AddChild(child1);
- render_surface2->AddChild(child2);
- render_surface2->AddChild(child3);
-
- host()->SetRootLayer(root);
+ LayerImpl* root = root_layer();
+ LayerImpl* render_surface1 = AddChildToRoot<LayerImpl>();
+ LayerImpl* render_surface2 = AddChild<LayerImpl>(render_surface1);
+ LayerImpl* child1 = AddChild<LayerImpl>(render_surface2);
+ child1->SetDrawsContent(true);
+ LayerImpl* child2 = AddChild<LayerImpl>(render_surface2);
+ child2->SetDrawsContent(true);
+ LayerImpl* child3 = AddChild<LayerImpl>(render_surface2);
+ child3->SetDrawsContent(true);
gfx::Transform identity_matrix;
- SetLayerPropertiesForTesting(root.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(100, 100),
- true,
- false);
- SetLayerPropertiesForTesting(render_surface1.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(3, 4),
- true,
- false);
- SetLayerPropertiesForTesting(render_surface2.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(7, 13),
- true,
- false);
- SetLayerPropertiesForTesting(child1.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(5.f, 5.f),
- gfx::Size(50, 50),
- true,
- false);
- SetLayerPropertiesForTesting(child2.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(75.f, 75.f),
- gfx::Size(50, 50),
- true,
- false);
- SetLayerPropertiesForTesting(child3.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(125.f, 125.f),
- gfx::Size(50, 50),
- true,
- false);
+ SetLayerPropertiesForTesting(root, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(100, 100), true, false,
+ true);
+ SetLayerPropertiesForTesting(render_surface1, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(3, 4), true, false,
+ true);
+ SetLayerPropertiesForTesting(render_surface2, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(7, 13), true, false,
+ true);
+ SetLayerPropertiesForTesting(child1, identity_matrix, gfx::Point3F(),
+ gfx::PointF(5.f, 5.f), gfx::Size(50, 50), true,
+ false, false);
+ SetLayerPropertiesForTesting(child2, identity_matrix, gfx::Point3F(),
+ gfx::PointF(75.f, 75.f), gfx::Size(50, 50), true,
+ false, false);
+ SetLayerPropertiesForTesting(child3, identity_matrix, gfx::Point3F(),
+ gfx::PointF(125.f, 125.f), gfx::Size(50, 50),
+ true, false, false);
root->SetMasksToBounds(true);
- render_surface1->SetForceRenderSurface(true);
- render_surface2->SetForceRenderSurface(true);
- ExecuteCalculateDrawProperties(root.get());
+
+ ExecuteCalculateDrawProperties(root);
ASSERT_TRUE(render_surface1->render_surface());
ASSERT_TRUE(render_surface2->render_surface());
- EXPECT_EQ(gfx::Rect(0, 0, 100, 100),
+ EXPECT_EQ(gfx::RectF(100.f, 100.f),
root->render_surface()->DrawableContentRect());
- EXPECT_EQ(gfx::Rect(0, 0, 100, 100), root->drawable_content_rect());
+ EXPECT_EQ(gfx::Rect(100, 100), root->drawable_content_rect());
// Layers that do not draw content should have empty visible content rects.
EXPECT_EQ(gfx::Rect(0, 0, 0, 0), root->visible_layer_rect());
@@ -3231,13 +2798,13 @@ TEST_F(LayerTreeHostCommonTest,
// A clipped surface grows its DrawableContentRect to include all drawable
// regions of the subtree, but also gets clamped by the ancestor's clip.
- EXPECT_EQ(gfx::Rect(5, 5, 95, 95),
+ EXPECT_EQ(gfx::RectF(5.f, 5.f, 95.f, 95.f),
render_surface1->render_surface()->DrawableContentRect());
// render_surface1 lives in the "unclipped universe" of render_surface1, and
// is only implicitly clipped by render_surface1's content rect. So,
// render_surface2 grows to enclose all drawable content of its subtree.
- EXPECT_EQ(gfx::Rect(5, 5, 170, 170),
+ EXPECT_EQ(gfx::RectF(5.f, 5.f, 170.f, 170.f),
render_surface2->render_surface()->DrawableContentRect());
// All layers that draw content into render_surface2 think they are unclipped.
@@ -3255,53 +2822,35 @@ TEST_F(LayerTreeHostCommonTest,
DrawableAndVisibleContentRectsWithTransformOnUnclippedSurface) {
// Layers that have non-axis aligned bounds (due to transforms) have an
// expanded, axis-aligned DrawableContentRect and visible content rect.
-
- scoped_refptr<Layer> root = Layer::Create(layer_settings());
- scoped_refptr<Layer> render_surface1 = Layer::Create(layer_settings());
- scoped_refptr<LayerWithForcedDrawsContent> child1 =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
- root->AddChild(render_surface1);
- render_surface1->AddChild(child1);
-
- host()->SetRootLayer(root);
+ LayerImpl* root = root_layer();
+ LayerImpl* render_surface = AddChildToRoot<LayerImpl>();
+ LayerImpl* child1 = AddChild<LayerImpl>(render_surface);
+ child1->SetDrawsContent(true);
gfx::Transform identity_matrix;
gfx::Transform child_rotation;
child_rotation.Rotate(45.0);
- SetLayerPropertiesForTesting(root.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(100, 100),
- true,
- false);
- SetLayerPropertiesForTesting(render_surface1.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(3, 4),
- true,
- false);
- SetLayerPropertiesForTesting(child1.get(),
- child_rotation,
- gfx::Point3F(25, 25, 0.f),
- gfx::PointF(25.f, 25.f),
- gfx::Size(50, 50),
- true,
- false);
+ SetLayerPropertiesForTesting(root, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(100, 100), true, false,
+ true);
+ SetLayerPropertiesForTesting(render_surface, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(3, 4), true, false,
+ true);
+ SetLayerPropertiesForTesting(
+ child1, child_rotation, gfx::Point3F(25, 25, 0.f),
+ gfx::PointF(25.f, 25.f), gfx::Size(50, 50), true, false, false);
- render_surface1->SetForceRenderSurface(true);
- ExecuteCalculateDrawProperties(root.get());
+ ExecuteCalculateDrawProperties(root);
- ASSERT_TRUE(render_surface1->render_surface());
+ ASSERT_TRUE(render_surface->render_surface());
- EXPECT_EQ(gfx::Rect(0, 0, 100, 100),
+ EXPECT_EQ(gfx::RectF(100.f, 100.f),
root->render_surface()->DrawableContentRect());
EXPECT_EQ(gfx::Rect(0, 0, 100, 100), root->drawable_content_rect());
// Layers that do not draw content should have empty visible content rects.
EXPECT_EQ(gfx::Rect(0, 0, 0, 0), root->visible_layer_rect());
- EXPECT_EQ(gfx::Rect(0, 0, 0, 0), render_surface1->visible_layer_rect());
+ EXPECT_EQ(gfx::Rect(0, 0, 0, 0), render_surface->visible_layer_rect());
// The unclipped surface grows its DrawableContentRect to include all drawable
// regions of the subtree.
@@ -3311,8 +2860,8 @@ TEST_F(LayerTreeHostCommonTest,
50 - diagonal_radius,
diagonal_radius * 2,
diagonal_radius * 2);
- EXPECT_EQ(expected_surface_drawable_content,
- render_surface1->render_surface()->DrawableContentRect());
+ EXPECT_EQ(gfx::RectF(expected_surface_drawable_content),
+ render_surface->render_surface()->DrawableContentRect());
// All layers that draw content into the unclipped surface are also unclipped.
EXPECT_EQ(gfx::Rect(0, 0, 50, 50), child1->visible_layer_rect());
@@ -3323,47 +2872,30 @@ TEST_F(LayerTreeHostCommonTest,
DrawableAndVisibleContentRectsWithTransformOnClippedSurface) {
// Layers that have non-axis aligned bounds (due to transforms) have an
// expanded, axis-aligned DrawableContentRect and visible content rect.
-
- scoped_refptr<Layer> root = Layer::Create(layer_settings());
- scoped_refptr<Layer> render_surface1 = Layer::Create(layer_settings());
- scoped_refptr<LayerWithForcedDrawsContent> child1 =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
- root->AddChild(render_surface1);
- render_surface1->AddChild(child1);
-
- host()->SetRootLayer(root);
+ LayerImpl* root = root_layer();
+ LayerImpl* render_surface = AddChildToRoot<LayerImpl>();
+ LayerImpl* child1 = AddChild<LayerImpl>(render_surface);
+ child1->SetDrawsContent(true);
gfx::Transform identity_matrix;
gfx::Transform child_rotation;
child_rotation.Rotate(45.0);
- SetLayerPropertiesForTesting(root.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(50, 50),
- true,
- false);
- SetLayerPropertiesForTesting(render_surface1.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(3, 4),
- true,
- false);
+ SetLayerPropertiesForTesting(root, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(50, 50), true, false,
+ true);
+ SetLayerPropertiesForTesting(render_surface, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(3, 4), true, false,
+ true);
- SetLayerPropertiesForTesting(child1.get(),
- child_rotation,
- gfx::Point3F(25, 25, 0.f),
- gfx::PointF(25.f, 25.f),
- gfx::Size(50, 50),
- true,
- false);
+ SetLayerPropertiesForTesting(
+ child1, child_rotation, gfx::Point3F(25, 25, 0.f),
+ gfx::PointF(25.f, 25.f), gfx::Size(50, 50), true, false, false);
root->SetMasksToBounds(true);
- render_surface1->SetForceRenderSurface(true);
- ExecuteCalculateDrawProperties(root.get());
- ASSERT_TRUE(render_surface1->render_surface());
+ ExecuteCalculateDrawProperties(root);
+
+ ASSERT_TRUE(render_surface->render_surface());
// The clipped surface clamps the DrawableContentRect that encloses the
// rotated layer.
@@ -3372,10 +2904,10 @@ TEST_F(LayerTreeHostCommonTest,
50 - diagonal_radius,
diagonal_radius * 2,
diagonal_radius * 2);
- gfx::Rect expected_surface_drawable_content =
- gfx::IntersectRects(unclipped_surface_content, gfx::Rect(0, 0, 50, 50));
+ gfx::RectF expected_surface_drawable_content(
+ gfx::IntersectRects(unclipped_surface_content, gfx::Rect(50, 50)));
EXPECT_EQ(expected_surface_drawable_content,
- render_surface1->render_surface()->DrawableContentRect());
+ render_surface->render_surface()->DrawableContentRect());
// On the clipped surface, only a quarter of the child1 is visible, but when
// rotating it back to child1's content space, the actual enclosing rect ends
@@ -3389,92 +2921,63 @@ TEST_F(LayerTreeHostCommonTest,
}
TEST_F(LayerTreeHostCommonTest, DrawableAndVisibleContentRectsInHighDPI) {
- MockContentLayerClient client;
-
- scoped_refptr<Layer> root = Layer::Create(layer_settings());
- scoped_refptr<FakePictureLayer> render_surface1 =
- CreateDrawablePictureLayer(layer_settings(), &client);
- scoped_refptr<FakePictureLayer> render_surface2 =
- CreateDrawablePictureLayer(layer_settings(), &client);
- scoped_refptr<FakePictureLayer> child1 =
- CreateDrawablePictureLayer(layer_settings(), &client);
- scoped_refptr<FakePictureLayer> child2 =
- CreateDrawablePictureLayer(layer_settings(), &client);
- scoped_refptr<FakePictureLayer> child3 =
- CreateDrawablePictureLayer(layer_settings(), &client);
- root->AddChild(render_surface1);
- render_surface1->AddChild(render_surface2);
- render_surface2->AddChild(child1);
- render_surface2->AddChild(child2);
- render_surface2->AddChild(child3);
-
- host()->SetRootLayer(root);
+ LayerImpl* root = root_layer();
+ FakePictureLayerImpl* render_surface1 =
+ AddChildToRoot<FakePictureLayerImpl>();
+ render_surface1->SetDrawsContent(true);
+ FakePictureLayerImpl* render_surface2 =
+ AddChild<FakePictureLayerImpl>(render_surface1);
+ render_surface2->SetDrawsContent(true);
+ FakePictureLayerImpl* child1 =
+ AddChild<FakePictureLayerImpl>(render_surface2);
+ child1->SetDrawsContent(true);
+ FakePictureLayerImpl* child2 =
+ AddChild<FakePictureLayerImpl>(render_surface2);
+ child2->SetDrawsContent(true);
+ FakePictureLayerImpl* child3 =
+ AddChild<FakePictureLayerImpl>(render_surface2);
+ child3->SetDrawsContent(true);
gfx::Transform identity_matrix;
- SetLayerPropertiesForTesting(root.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(100, 100),
- true,
- false);
- SetLayerPropertiesForTesting(render_surface1.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(5.f, 5.f),
- gfx::Size(3, 4),
- true,
- false);
- SetLayerPropertiesForTesting(render_surface2.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(5.f, 5.f),
- gfx::Size(7, 13),
- true,
- false);
- SetLayerPropertiesForTesting(child1.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(5.f, 5.f),
- gfx::Size(50, 50),
- true,
- false);
- SetLayerPropertiesForTesting(child2.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(75.f, 75.f),
- gfx::Size(50, 50),
- true,
- false);
- SetLayerPropertiesForTesting(child3.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(125.f, 125.f),
- gfx::Size(50, 50),
- true,
- false);
+ SetLayerPropertiesForTesting(root, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(100, 100), true, false,
+ true);
+ SetLayerPropertiesForTesting(render_surface1, identity_matrix, gfx::Point3F(),
+ gfx::PointF(5.f, 5.f), gfx::Size(3, 4), true,
+ false, true);
+ SetLayerPropertiesForTesting(render_surface2, identity_matrix, gfx::Point3F(),
+ gfx::PointF(5.f, 5.f), gfx::Size(7, 13), true,
+ false, true);
+ SetLayerPropertiesForTesting(child1, identity_matrix, gfx::Point3F(),
+ gfx::PointF(5.f, 5.f), gfx::Size(50, 50), true,
+ false, false);
+ SetLayerPropertiesForTesting(child2, identity_matrix, gfx::Point3F(),
+ gfx::PointF(75.f, 75.f), gfx::Size(50, 50), true,
+ false, false);
+ SetLayerPropertiesForTesting(child3, identity_matrix, gfx::Point3F(),
+ gfx::PointF(125.f, 125.f), gfx::Size(50, 50),
+ true, false, false);
float device_scale_factor = 2.f;
root->SetMasksToBounds(true);
- render_surface1->SetForceRenderSurface(true);
- render_surface2->SetForceRenderSurface(true);
- ExecuteCalculateDrawProperties(root.get(), device_scale_factor);
+
+ ExecuteCalculateDrawProperties(root, device_scale_factor);
ASSERT_TRUE(render_surface1->render_surface());
ASSERT_TRUE(render_surface2->render_surface());
// drawable_content_rects for all layers and surfaces are scaled by
// device_scale_factor.
- EXPECT_EQ(gfx::Rect(0, 0, 200, 200),
+ EXPECT_EQ(gfx::RectF(200.f, 200.f),
root->render_surface()->DrawableContentRect());
EXPECT_EQ(gfx::Rect(0, 0, 200, 200), root->drawable_content_rect());
- EXPECT_EQ(gfx::Rect(10, 10, 190, 190),
+ EXPECT_EQ(gfx::RectF(10.f, 10.f, 190.f, 190.f),
render_surface1->render_surface()->DrawableContentRect());
// render_surface2 lives in the "unclipped universe" of render_surface1, and
// is only implicitly clipped by render_surface1.
- EXPECT_EQ(gfx::Rect(10, 10, 350, 350),
+ EXPECT_EQ(gfx::RectF(10.f, 10.f, 350.f, 350.f),
render_surface2->render_surface()->DrawableContentRect());
EXPECT_EQ(gfx::Rect(10, 10, 100, 100), child1->drawable_content_rect());
@@ -3618,81 +3121,26 @@ TEST_F(LayerTreeHostCommonTest, BackFaceCullingWithoutPreserves3d) {
true,
false);
- RenderSurfaceLayerList render_surface_layer_list;
- LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
- parent.get(), parent->bounds(), &render_surface_layer_list);
- inputs.can_adjust_raster_scales = true;
- LayerTreeHostCommon::CalculateDrawProperties(&inputs);
+ ExecuteCalculateDrawPropertiesWithPropertyTrees(parent.get());
// Verify which render surfaces were created.
- EXPECT_FALSE(front_facing_child->render_surface());
- EXPECT_FALSE(back_facing_child->render_surface());
- EXPECT_TRUE(front_facing_surface->render_surface());
- EXPECT_TRUE(back_facing_surface->render_surface());
- EXPECT_FALSE(front_facing_child_of_front_facing_surface->render_surface());
- EXPECT_FALSE(back_facing_child_of_front_facing_surface->render_surface());
- EXPECT_FALSE(front_facing_child_of_back_facing_surface->render_surface());
- EXPECT_FALSE(back_facing_child_of_back_facing_surface->render_surface());
-
- // Verify the render_surface_layer_list.
- ASSERT_EQ(3u, render_surface_layer_list.size());
- EXPECT_EQ(parent->id(), render_surface_layer_list.at(0)->id());
- EXPECT_EQ(front_facing_surface->id(), render_surface_layer_list.at(1)->id());
- // Even though the back facing surface LAYER gets culled, the other
- // descendants should still be added, so the SURFACE should not be culled.
- EXPECT_EQ(back_facing_surface->id(), render_surface_layer_list.at(2)->id());
-
- // Verify root surface's layer list.
- ASSERT_EQ(
- 3u,
- render_surface_layer_list.at(0)->render_surface()->layer_list().size());
- EXPECT_EQ(front_facing_child->id(),
- render_surface_layer_list.at(0)
- ->render_surface()
- ->layer_list()
- .at(0)
- ->id());
- EXPECT_EQ(front_facing_surface->id(),
- render_surface_layer_list.at(0)
- ->render_surface()
- ->layer_list()
- .at(1)
- ->id());
- EXPECT_EQ(back_facing_surface->id(),
- render_surface_layer_list.at(0)
- ->render_surface()
- ->layer_list()
- .at(2)
- ->id());
-
- // Verify front_facing_surface's layer list.
- ASSERT_EQ(
- 2u,
- render_surface_layer_list.at(1)->render_surface()->layer_list().size());
- EXPECT_EQ(front_facing_surface->id(),
- render_surface_layer_list.at(1)
- ->render_surface()
- ->layer_list()
- .at(0)
- ->id());
- EXPECT_EQ(front_facing_child_of_front_facing_surface->id(),
- render_surface_layer_list.at(1)
- ->render_surface()
- ->layer_list()
- .at(1)
- ->id());
-
- // Verify back_facing_surface's layer list; its own layer should be culled
- // from the surface list.
- ASSERT_EQ(
- 1u,
- render_surface_layer_list.at(2)->render_surface()->layer_list().size());
- EXPECT_EQ(front_facing_child_of_back_facing_surface->id(),
- render_surface_layer_list.at(2)
- ->render_surface()
- ->layer_list()
- .at(0)
- ->id());
+ EXPECT_FALSE(front_facing_child->has_render_surface());
+ EXPECT_FALSE(back_facing_child->has_render_surface());
+ EXPECT_TRUE(front_facing_surface->has_render_surface());
+ EXPECT_TRUE(back_facing_surface->has_render_surface());
+ EXPECT_FALSE(
+ front_facing_child_of_front_facing_surface->has_render_surface());
+ EXPECT_FALSE(back_facing_child_of_front_facing_surface->has_render_surface());
+ EXPECT_FALSE(front_facing_child_of_back_facing_surface->has_render_surface());
+ EXPECT_FALSE(back_facing_child_of_back_facing_surface->has_render_surface());
+
+ EXPECT_EQ(4u, update_layer_list().size());
+ EXPECT_TRUE(UpdateLayerListContains(front_facing_child->id()));
+ EXPECT_TRUE(UpdateLayerListContains(front_facing_surface->id()));
+ EXPECT_TRUE(UpdateLayerListContains(
+ front_facing_child_of_front_facing_surface->id()));
+ EXPECT_TRUE(
+ UpdateLayerListContains(front_facing_child_of_back_facing_surface->id()));
}
TEST_F(LayerTreeHostCommonTest, BackFaceCullingWithPreserves3d) {
@@ -3829,51 +3277,26 @@ TEST_F(LayerTreeHostCommonTest, BackFaceCullingWithPreserves3d) {
true,
true);
- RenderSurfaceLayerList render_surface_layer_list;
- LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
- parent.get(), parent->bounds(), &render_surface_layer_list);
- inputs.can_adjust_raster_scales = true;
- LayerTreeHostCommon::CalculateDrawProperties(&inputs);
+ ExecuteCalculateDrawPropertiesWithPropertyTrees(parent.get());
// Verify which render surfaces were created and used.
- EXPECT_FALSE(front_facing_child->render_surface());
- EXPECT_FALSE(back_facing_child->render_surface());
- EXPECT_TRUE(front_facing_surface->render_surface());
- EXPECT_NE(back_facing_surface->render_target(), back_facing_surface);
- // We expect that a render_surface was created but not used.
- EXPECT_TRUE(back_facing_surface->render_surface());
- EXPECT_FALSE(front_facing_child_of_front_facing_surface->render_surface());
- EXPECT_FALSE(back_facing_child_of_front_facing_surface->render_surface());
- EXPECT_FALSE(front_facing_child_of_back_facing_surface->render_surface());
- EXPECT_FALSE(back_facing_child_of_back_facing_surface->render_surface());
-
- // Verify the render_surface_layer_list. The back-facing surface should be
- // culled.
- ASSERT_EQ(2u, render_surface_layer_list.size());
- EXPECT_EQ(parent->id(), render_surface_layer_list.at(0)->id());
- EXPECT_EQ(front_facing_surface->id(), render_surface_layer_list.at(1)->id());
-
- // Verify root surface's layer list.
- ASSERT_EQ(
- 2u,
- render_surface_layer_list.at(0)->render_surface()->layer_list().size());
- EXPECT_EQ(front_facing_child->id(),
- render_surface_layer_list.at(0)
- ->render_surface()->layer_list().at(0)->id());
- EXPECT_EQ(front_facing_surface->id(),
- render_surface_layer_list.at(0)
- ->render_surface()->layer_list().at(1)->id());
-
- // Verify front_facing_surface's layer list.
- ASSERT_EQ(
- 2u,
- render_surface_layer_list.at(1)->render_surface()->layer_list().size());
- EXPECT_EQ(front_facing_surface->id(),
- render_surface_layer_list.at(1)
- ->render_surface()->layer_list().at(0)->id());
- EXPECT_EQ(front_facing_child_of_front_facing_surface->id(),
- render_surface_layer_list.at(1)
- ->render_surface()->layer_list().at(1)->id());
+ EXPECT_FALSE(front_facing_child->has_render_surface());
+ EXPECT_FALSE(back_facing_child->has_render_surface());
+ EXPECT_TRUE(front_facing_surface->has_render_surface());
+ // We expect that a has_render_surface was created but not used.
+ EXPECT_TRUE(back_facing_surface->has_render_surface());
+ EXPECT_FALSE(
+ front_facing_child_of_front_facing_surface->has_render_surface());
+ EXPECT_FALSE(back_facing_child_of_front_facing_surface->has_render_surface());
+ EXPECT_FALSE(front_facing_child_of_back_facing_surface->has_render_surface());
+ EXPECT_FALSE(back_facing_child_of_back_facing_surface->has_render_surface());
+
+ EXPECT_EQ(3u, update_layer_list().size());
+
+ EXPECT_TRUE(UpdateLayerListContains(front_facing_child->id()));
+ EXPECT_TRUE(UpdateLayerListContains(front_facing_surface->id()));
+ EXPECT_TRUE(UpdateLayerListContains(
+ front_facing_child_of_front_facing_surface->id()));
}
TEST_F(LayerTreeHostCommonTest, BackFaceCullingWithAnimatingTransforms) {
@@ -3969,60 +3392,38 @@ TEST_F(LayerTreeHostCommonTest, BackFaceCullingWithAnimatingTransforms) {
true,
false);
- RenderSurfaceLayerList render_surface_layer_list;
- LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
- parent.get(), parent->bounds(), &render_surface_layer_list);
- inputs.can_adjust_raster_scales = true;
+ LayerTreeHostCommon::CalcDrawPropsMainInputs inputs(parent.get(),
+ parent->bounds());
LayerTreeHostCommon::CalculateDrawProperties(&inputs);
- EXPECT_FALSE(child->render_surface());
- EXPECT_TRUE(animating_surface->render_surface());
- EXPECT_FALSE(child_of_animating_surface->render_surface());
- EXPECT_FALSE(animating_child->render_surface());
- EXPECT_FALSE(child2->render_surface());
-
- // Verify that the animating_child and child_of_animating_surface were not
- // culled, but that child was.
- ASSERT_EQ(2u, render_surface_layer_list.size());
- EXPECT_EQ(parent->id(), render_surface_layer_list.at(0)->id());
- EXPECT_EQ(animating_surface->id(), render_surface_layer_list.at(1)->id());
+ EXPECT_FALSE(child->has_render_surface());
+ EXPECT_TRUE(animating_surface->has_render_surface());
+ EXPECT_FALSE(child_of_animating_surface->has_render_surface());
+ EXPECT_FALSE(animating_child->has_render_surface());
+ EXPECT_FALSE(child2->has_render_surface());
+
+ ExecuteCalculateDrawPropertiesWithPropertyTrees(parent.get());
+
+ EXPECT_EQ(4u, update_layer_list().size());
// The non-animating child be culled from the layer list for the parent render
// surface.
- ASSERT_EQ(
- 3u,
- render_surface_layer_list.at(0)->render_surface()->layer_list().size());
- EXPECT_EQ(animating_surface->id(),
- render_surface_layer_list.at(0)
- ->render_surface()->layer_list().at(0)->id());
- EXPECT_EQ(animating_child->id(),
- render_surface_layer_list.at(0)
- ->render_surface()->layer_list().at(1)->id());
- EXPECT_EQ(child2->id(),
- render_surface_layer_list.at(0)
- ->render_surface()->layer_list().at(2)->id());
-
- ASSERT_EQ(
- 2u,
- render_surface_layer_list.at(1)->render_surface()->layer_list().size());
- EXPECT_EQ(animating_surface->id(),
- render_surface_layer_list.at(1)
- ->render_surface()->layer_list().at(0)->id());
- EXPECT_EQ(child_of_animating_surface->id(),
- render_surface_layer_list.at(1)
- ->render_surface()->layer_list().at(1)->id());
-
- EXPECT_FALSE(child2->visible_layer_rect().IsEmpty());
+ EXPECT_TRUE(UpdateLayerListContains(animating_surface->id()));
+ EXPECT_TRUE(UpdateLayerListContains(animating_child->id()));
+ EXPECT_TRUE(UpdateLayerListContains(child2->id()));
+ EXPECT_TRUE(UpdateLayerListContains(child_of_animating_surface->id()));
+
+ EXPECT_FALSE(child2->visible_rect_from_property_trees().IsEmpty());
// The animating layers should have a visible content rect that represents the
// area of the front face that is within the viewport.
- EXPECT_EQ(animating_child->visible_layer_rect(),
+ EXPECT_EQ(animating_child->visible_rect_from_property_trees(),
gfx::Rect(animating_child->bounds()));
- EXPECT_EQ(animating_surface->visible_layer_rect(),
+ EXPECT_EQ(animating_surface->visible_rect_from_property_trees(),
gfx::Rect(animating_surface->bounds()));
// And layers in the subtree of the animating layer should have valid visible
// content rects also.
- EXPECT_EQ(child_of_animating_surface->visible_layer_rect(),
+ EXPECT_EQ(child_of_animating_surface->visible_rect_from_property_trees(),
gfx::Rect(child_of_animating_surface->bounds()));
}
@@ -4097,46 +3498,19 @@ TEST_F(LayerTreeHostCommonTest,
front_facing_surface->Set3dSortingContextId(1);
back_facing_surface->Set3dSortingContextId(1);
- RenderSurfaceLayerList render_surface_layer_list;
- LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
- parent.get(), parent->bounds(), &render_surface_layer_list);
- inputs.can_adjust_raster_scales = true;
- LayerTreeHostCommon::CalculateDrawProperties(&inputs);
+ ExecuteCalculateDrawPropertiesWithPropertyTrees(parent.get());
// Verify which render surfaces were created and used.
- EXPECT_TRUE(front_facing_surface->render_surface());
+ EXPECT_TRUE(front_facing_surface->has_render_surface());
// We expect the render surface to have been created, but remain unused.
- EXPECT_TRUE(back_facing_surface->render_surface());
- EXPECT_NE(back_facing_surface->render_target(),
- back_facing_surface); // because it should be culled
- EXPECT_FALSE(child1->render_surface());
- EXPECT_FALSE(child2->render_surface());
-
- // Verify the render_surface_layer_list. The back-facing surface should be
- // culled.
- ASSERT_EQ(2u, render_surface_layer_list.size());
- EXPECT_EQ(parent->id(), render_surface_layer_list.at(0)->id());
- EXPECT_EQ(front_facing_surface->id(), render_surface_layer_list.at(1)->id());
-
- // Verify root surface's layer list.
- ASSERT_EQ(
- 1u,
- render_surface_layer_list.at(0)->render_surface()->layer_list().size());
- EXPECT_EQ(front_facing_surface->id(),
- render_surface_layer_list.at(0)
- ->render_surface()->layer_list().at(0)->id());
-
- // Verify front_facing_surface's layer list.
- ASSERT_EQ(
- 2u,
- render_surface_layer_list.at(1)->render_surface()->layer_list().size());
- EXPECT_EQ(front_facing_surface->id(),
- render_surface_layer_list.at(1)
- ->render_surface()->layer_list().at(0)->id());
- EXPECT_EQ(child1->id(),
- render_surface_layer_list.at(1)
- ->render_surface()->layer_list().at(1)->id());
+ EXPECT_TRUE(back_facing_surface->has_render_surface());
+ EXPECT_FALSE(child1->has_render_surface());
+ EXPECT_FALSE(child2->has_render_surface());
+
+ EXPECT_EQ(2u, update_layer_list().size());
+ EXPECT_TRUE(UpdateLayerListContains(front_facing_surface->id()));
+ EXPECT_TRUE(UpdateLayerListContains(child1->id()));
}
TEST_F(LayerTreeHostCommonScalingTest, LayerTransformsInHighDPI) {
@@ -4177,14 +3551,14 @@ TEST_F(LayerTreeHostCommonScalingTest, LayerTransformsInHighDPI) {
parent->draw_transform());
// Verify results of transformed parent rects
- gfx::RectF parent_bounds(parent->bounds());
+ gfx::RectF parent_bounds(gfx::SizeF(parent->bounds()));
gfx::RectF parent_draw_rect =
MathUtil::MapClippedRect(parent->draw_transform(), parent_bounds);
gfx::RectF parent_screen_space_rect =
MathUtil::MapClippedRect(parent->screen_space_transform(), parent_bounds);
- gfx::RectF expected_parent_draw_rect(parent->bounds());
+ gfx::RectF expected_parent_draw_rect(gfx::SizeF(parent->bounds()));
expected_parent_draw_rect.Scale(device_scale_factor);
EXPECT_FLOAT_RECT_EQ(expected_parent_draw_rect, parent_draw_rect);
EXPECT_FLOAT_RECT_EQ(expected_parent_draw_rect, parent_screen_space_rect);
@@ -4205,7 +3579,7 @@ TEST_F(LayerTreeHostCommonScalingTest, LayerTransformsInHighDPI) {
// Verify results of transformed child and child_empty rects. They should
// match.
- gfx::RectF child_bounds(child->bounds());
+ gfx::RectF child_bounds(gfx::SizeF(child->bounds()));
gfx::RectF child_draw_rect =
MathUtil::MapClippedRect(child->draw_transform(), child_bounds);
@@ -4217,7 +3591,8 @@ TEST_F(LayerTreeHostCommonScalingTest, LayerTransformsInHighDPI) {
gfx::RectF child_empty_screen_space_rect = MathUtil::MapClippedRect(
child_empty->screen_space_transform(), child_bounds);
- gfx::RectF expected_child_draw_rect(child->position(), child->bounds());
+ gfx::RectF expected_child_draw_rect(child->position(),
+ gfx::SizeF(child->bounds()));
expected_child_draw_rect.Scale(device_scale_factor);
EXPECT_FLOAT_RECT_EQ(expected_child_draw_rect, child_draw_rect);
EXPECT_FLOAT_RECT_EQ(expected_child_draw_rect, child_screen_space_rect);
@@ -4392,71 +3767,44 @@ TEST_F(LayerTreeHostCommonScalingTest, IdealScaleForAnimatingLayer) {
}
TEST_F(LayerTreeHostCommonTest, RenderSurfaceTransformsInHighDPI) {
- MockContentLayerClient delegate;
gfx::Transform identity_matrix;
- scoped_refptr<FakePictureLayer> parent =
- CreateDrawablePictureLayer(layer_settings(), &delegate);
- SetLayerPropertiesForTesting(parent.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(30, 30),
- false,
+ LayerImpl* parent = root_layer();
+ parent->SetDrawsContent(true);
+ SetLayerPropertiesForTesting(parent, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(30, 30), false, true,
true);
- scoped_refptr<FakePictureLayer> child =
- CreateDrawablePictureLayer(layer_settings(), &delegate);
- SetLayerPropertiesForTesting(child.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(2.f, 2.f),
- gfx::Size(10, 10),
- false,
- true);
+ LayerImpl* child = AddChildToRoot<LayerImpl>();
+ child->SetDrawsContent(true);
+ SetLayerPropertiesForTesting(child, identity_matrix, gfx::Point3F(),
+ gfx::PointF(2.f, 2.f), gfx::Size(10, 10), false,
+ true, true);
gfx::Transform replica_transform;
replica_transform.Scale(1.0, -1.0);
- scoped_refptr<FakePictureLayer> replica =
- CreateDrawablePictureLayer(layer_settings(), &delegate);
- SetLayerPropertiesForTesting(replica.get(),
- replica_transform,
- gfx::Point3F(),
- gfx::PointF(2.f, 2.f),
- gfx::Size(10, 10),
- false,
- true);
+
+ scoped_ptr<LayerImpl> replica =
+ LayerImpl::Create(host_impl()->active_tree(), 7);
+ SetLayerPropertiesForTesting(replica.get(), replica_transform, gfx::Point3F(),
+ gfx::PointF(2.f, 2.f), gfx::Size(10, 10), false,
+ true, false);
+ child->SetReplicaLayer(replica.Pass());
// This layer should end up in the same surface as child, with the same draw
// and screen space transforms.
- scoped_refptr<FakePictureLayer> duplicate_child_non_owner =
- CreateDrawablePictureLayer(layer_settings(), &delegate);
- SetLayerPropertiesForTesting(duplicate_child_non_owner.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(10, 10),
- false,
- true);
-
- parent->AddChild(child);
- child->AddChild(duplicate_child_non_owner);
- child->SetReplicaLayer(replica.get());
-
- host()->SetRootLayer(parent);
-
- RenderSurfaceLayerList render_surface_layer_list;
+ LayerImpl* duplicate_child_non_owner = AddChild<LayerImpl>(child);
+ duplicate_child_non_owner->SetDrawsContent(true);
+ SetLayerPropertiesForTesting(duplicate_child_non_owner, identity_matrix,
+ gfx::Point3F(), gfx::PointF(), gfx::Size(10, 10),
+ false, true, false);
float device_scale_factor = 1.5f;
- LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
- parent.get(), parent->bounds(), &render_surface_layer_list);
- inputs.device_scale_factor = device_scale_factor;
- inputs.can_adjust_raster_scales = true;
- LayerTreeHostCommon::CalculateDrawProperties(&inputs);
+ ExecuteCalculateDrawProperties(parent, device_scale_factor);
// We should have two render surfaces. The root's render surface and child's
// render surface (it needs one because it has a replica layer).
- EXPECT_EQ(2u, render_surface_layer_list.size());
+ EXPECT_EQ(2u, render_surface_layer_list_impl()->size());
gfx::Transform expected_parent_transform;
expected_parent_transform.Scale(device_scale_factor, device_scale_factor);
@@ -4531,58 +3879,35 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceTransformsInHighDPI) {
TEST_F(LayerTreeHostCommonTest,
RenderSurfaceTransformsInHighDPIAccurateScaleZeroPosition) {
- MockContentLayerClient delegate;
gfx::Transform identity_matrix;
- scoped_refptr<FakePictureLayer> parent =
- CreateDrawablePictureLayer(layer_settings(), &delegate);
- SetLayerPropertiesForTesting(parent.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(33, 31),
- false,
+ LayerImpl* parent = root_layer();
+ parent->SetDrawsContent(true);
+ SetLayerPropertiesForTesting(parent, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(33, 31), false, true,
true);
- scoped_refptr<FakePictureLayer> child =
- CreateDrawablePictureLayer(layer_settings(), &delegate);
- SetLayerPropertiesForTesting(child.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(13, 11),
- false,
+ LayerImpl* child = AddChildToRoot<LayerImpl>();
+ child->SetDrawsContent(true);
+ SetLayerPropertiesForTesting(child, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(13, 11), false, true,
true);
gfx::Transform replica_transform;
replica_transform.Scale(1.0, -1.0);
- scoped_refptr<FakePictureLayer> replica =
- CreateDrawablePictureLayer(layer_settings(), &delegate);
- SetLayerPropertiesForTesting(replica.get(),
- replica_transform,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(13, 11),
- false,
- true);
-
- parent->AddChild(child);
- child->SetReplicaLayer(replica.get());
-
- host()->SetRootLayer(parent);
+ scoped_ptr<LayerImpl> replica =
+ LayerImpl::Create(host_impl()->active_tree(), 7);
+ SetLayerPropertiesForTesting(replica.get(), replica_transform, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(13, 11), false, true,
+ false);
+ child->SetReplicaLayer(replica.Pass());
float device_scale_factor = 1.7f;
-
- RenderSurfaceLayerList render_surface_layer_list;
- LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
- parent.get(), parent->bounds(), &render_surface_layer_list);
- inputs.device_scale_factor = device_scale_factor;
- inputs.can_adjust_raster_scales = true;
- LayerTreeHostCommon::CalculateDrawProperties(&inputs);
+ ExecuteCalculateDrawProperties(parent, device_scale_factor);
// We should have two render surfaces. The root's render surface and child's
// render surface (it needs one because it has a replica layer).
- EXPECT_EQ(2u, render_surface_layer_list.size());
+ EXPECT_EQ(2u, render_surface_layer_list_impl()->size());
gfx::Transform identity_transform;
EXPECT_TRANSFORMATION_MATRIX_EQ(identity_transform,
@@ -4674,7 +3999,7 @@ TEST_F(LayerTreeHostCommonTest, TransparentChildRenderSurfaceCreation) {
ExecuteCalculateDrawProperties(root.get());
- EXPECT_FALSE(child->render_surface());
+ EXPECT_FALSE(child->has_render_surface());
}
TEST_F(LayerTreeHostCommonTest, OpacityAnimatingOnPendingTree) {
@@ -4841,7 +4166,7 @@ TEST_P(LCDTextTest, CanUseLCDText) {
// Case 6: Skew.
gfx::Transform skew;
- skew.SkewX(10.0);
+ skew.Skew(10.0, 0.0);
child_->SetTransform(skew);
child_->layer_tree_impl()->property_trees()->needs_rebuild = true;
ExecuteCalculateDrawProperties(root_, 1.f, 1.f, NULL, can_use_lcd_text_,
@@ -4942,65 +4267,6 @@ INSTANTIATE_TEST_CASE_P(LayerTreeHostCommonTest,
testing::Bool(),
testing::Bool()));
-TEST_F(LayerTreeHostCommonTest, SubtreeHidden_SingleLayer) {
- FakeImplProxy proxy;
- TestSharedBitmapManager shared_bitmap_manager;
- TestTaskGraphRunner task_graph_runner;
- FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager,
- &task_graph_runner);
- host_impl.CreatePendingTree();
- const gfx::Transform identity_matrix;
-
- scoped_refptr<Layer> root = Layer::Create(layer_settings());
- SetLayerPropertiesForTesting(root.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(50, 50),
- true,
- false);
- root->SetIsDrawable(true);
-
- scoped_refptr<Layer> child = Layer::Create(layer_settings());
- SetLayerPropertiesForTesting(child.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(40, 40),
- true,
- false);
- child->SetIsDrawable(true);
-
- scoped_refptr<Layer> grand_child = Layer::Create(layer_settings());
- SetLayerPropertiesForTesting(grand_child.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(30, 30),
- true,
- false);
- grand_child->SetIsDrawable(true);
- grand_child->SetHideLayerAndSubtree(true);
-
- child->AddChild(grand_child);
- root->AddChild(child);
-
- host()->SetRootLayer(root);
-
- RenderSurfaceLayerList render_surface_layer_list;
- LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
- root.get(), root->bounds(), &render_surface_layer_list);
- inputs.can_adjust_raster_scales = true;
- LayerTreeHostCommon::CalculateDrawProperties(&inputs);
-
- // We should have one render surface and two layers. The grand child has
- // hidden itself.
- ASSERT_EQ(1u, render_surface_layer_list.size());
- ASSERT_EQ(2u, root->render_surface()->layer_list().size());
- EXPECT_EQ(root->id(), root->render_surface()->layer_list().at(0)->id());
- EXPECT_EQ(child->id(), root->render_surface()->layer_list().at(1)->id());
-}
-
TEST_F(LayerTreeHostCommonTest, SubtreeHidden_SingleLayerImpl) {
FakeImplProxy proxy;
TestSharedBitmapManager shared_bitmap_manager;
@@ -5048,64 +4314,6 @@ TEST_F(LayerTreeHostCommonTest, SubtreeHidden_SingleLayerImpl) {
EXPECT_EQ(2, root->render_surface()->layer_list().at(1)->id());
}
-TEST_F(LayerTreeHostCommonTest, SubtreeHidden_TwoLayers) {
- FakeImplProxy proxy;
- TestSharedBitmapManager shared_bitmap_manager;
- TestTaskGraphRunner task_graph_runner;
- FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager,
- &task_graph_runner);
- host_impl.CreatePendingTree();
- const gfx::Transform identity_matrix;
-
- scoped_refptr<Layer> root = Layer::Create(layer_settings());
- SetLayerPropertiesForTesting(root.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(50, 50),
- true,
- false);
- root->SetIsDrawable(true);
-
- scoped_refptr<Layer> child = Layer::Create(layer_settings());
- SetLayerPropertiesForTesting(child.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(40, 40),
- true,
- false);
- child->SetIsDrawable(true);
- child->SetHideLayerAndSubtree(true);
-
- scoped_refptr<Layer> grand_child = Layer::Create(layer_settings());
- SetLayerPropertiesForTesting(grand_child.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(30, 30),
- true,
- false);
- grand_child->SetIsDrawable(true);
-
- child->AddChild(grand_child);
- root->AddChild(child);
-
- host()->SetRootLayer(root);
-
- RenderSurfaceLayerList render_surface_layer_list;
- LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
- root.get(), root->bounds(), &render_surface_layer_list);
- inputs.can_adjust_raster_scales = true;
- LayerTreeHostCommon::CalculateDrawProperties(&inputs);
-
- // We should have one render surface and one layers. The child has
- // hidden itself and the grand child.
- ASSERT_EQ(1u, render_surface_layer_list.size());
- ASSERT_EQ(1u, root->render_surface()->layer_list().size());
- EXPECT_EQ(root->id(), root->render_surface()->layer_list().at(0)->id());
-}
-
TEST_F(LayerTreeHostCommonTest, SubtreeHidden_TwoLayersImpl) {
FakeImplProxy proxy;
TestSharedBitmapManager shared_bitmap_manager;
@@ -5162,122 +4370,105 @@ TEST_F(LayerTreeHostCommonTest, SubtreeHiddenWithCopyRequest) {
host_impl.CreatePendingTree();
const gfx::Transform identity_matrix;
- scoped_refptr<Layer> root = Layer::Create(layer_settings());
- SetLayerPropertiesForTesting(root.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(50, 50),
- true,
- false);
- root->SetIsDrawable(true);
+ scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl.pending_tree(), 1);
+ SetLayerPropertiesForTesting(root.get(), identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(50, 50), true, false,
+ true);
+ root->SetDrawsContent(true);
- scoped_refptr<Layer> copy_grand_parent = Layer::Create(layer_settings());
- SetLayerPropertiesForTesting(copy_grand_parent.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(40, 40),
- true,
- false);
- copy_grand_parent->SetIsDrawable(true);
+ scoped_ptr<LayerImpl> copy_grand_parent =
+ LayerImpl::Create(host_impl.pending_tree(), 2);
+ SetLayerPropertiesForTesting(copy_grand_parent.get(), identity_matrix,
+ gfx::Point3F(), gfx::PointF(), gfx::Size(40, 40),
+ true, false, false);
+ copy_grand_parent->SetDrawsContent(true);
+ LayerImpl* copy_grand_parent_layer = copy_grand_parent.get();
- scoped_refptr<Layer> copy_parent = Layer::Create(layer_settings());
- SetLayerPropertiesForTesting(copy_parent.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(30, 30),
- true,
- false);
- copy_parent->SetIsDrawable(true);
- copy_parent->SetForceRenderSurface(true);
+ scoped_ptr<LayerImpl> copy_parent =
+ LayerImpl::Create(host_impl.pending_tree(), 3);
+ SetLayerPropertiesForTesting(copy_parent.get(), identity_matrix,
+ gfx::Point3F(), gfx::PointF(), gfx::Size(30, 30),
+ true, false, true);
+ copy_parent->SetDrawsContent(true);
+ LayerImpl* copy_parent_layer = copy_parent.get();
- scoped_refptr<Layer> copy_layer = Layer::Create(layer_settings());
- SetLayerPropertiesForTesting(copy_layer.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(20, 20),
- true,
- false);
- copy_layer->SetIsDrawable(true);
+ scoped_ptr<LayerImpl> copy_request =
+ LayerImpl::Create(host_impl.pending_tree(), 4);
+ SetLayerPropertiesForTesting(copy_request.get(), identity_matrix,
+ gfx::Point3F(), gfx::PointF(), gfx::Size(20, 20),
+ true, false, true);
+ copy_request->SetDrawsContent(true);
+ LayerImpl* copy_layer = copy_request.get();
- scoped_refptr<Layer> copy_child = Layer::Create(layer_settings());
- SetLayerPropertiesForTesting(copy_child.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(20, 20),
- true,
- false);
- copy_child->SetIsDrawable(true);
+ scoped_ptr<LayerImpl> copy_child =
+ LayerImpl::Create(host_impl.pending_tree(), 5);
+ SetLayerPropertiesForTesting(copy_child.get(), identity_matrix,
+ gfx::Point3F(), gfx::PointF(), gfx::Size(20, 20),
+ true, false, false);
+ copy_child->SetDrawsContent(true);
+ LayerImpl* copy_child_layer = copy_child.get();
- scoped_refptr<Layer> copy_grand_parent_sibling_before =
- Layer::Create(layer_settings());
+ scoped_ptr<LayerImpl> copy_grand_parent_sibling_before =
+ LayerImpl::Create(host_impl.pending_tree(), 6);
SetLayerPropertiesForTesting(copy_grand_parent_sibling_before.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(40, 40),
- true,
- false);
- copy_grand_parent_sibling_before->SetIsDrawable(true);
-
- scoped_refptr<Layer> copy_grand_parent_sibling_after =
- Layer::Create(layer_settings());
+ identity_matrix, gfx::Point3F(), gfx::PointF(),
+ gfx::Size(40, 40), true, false, false);
+ copy_grand_parent_sibling_before->SetDrawsContent(true);
+ LayerImpl* copy_grand_parent_sibling_before_layer =
+ copy_grand_parent_sibling_before.get();
+
+ scoped_ptr<LayerImpl> copy_grand_parent_sibling_after =
+ LayerImpl::Create(host_impl.pending_tree(), 7);
SetLayerPropertiesForTesting(copy_grand_parent_sibling_after.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(40, 40),
- true,
- false);
- copy_grand_parent_sibling_after->SetIsDrawable(true);
-
- copy_layer->AddChild(copy_child);
- copy_parent->AddChild(copy_layer);
- copy_grand_parent->AddChild(copy_parent);
- root->AddChild(copy_grand_parent_sibling_before);
- root->AddChild(copy_grand_parent);
- root->AddChild(copy_grand_parent_sibling_after);
-
- host()->SetRootLayer(root);
+ identity_matrix, gfx::Point3F(), gfx::PointF(),
+ gfx::Size(40, 40), true, false, false);
+ copy_grand_parent_sibling_after->SetDrawsContent(true);
+ LayerImpl* copy_grand_parent_sibling_after_layer =
+ copy_grand_parent_sibling_after.get();
+
+ copy_request->AddChild(copy_child.Pass());
+ copy_parent->AddChild(copy_request.Pass());
+ copy_grand_parent->AddChild(copy_parent.Pass());
+ root->AddChild(copy_grand_parent_sibling_before.Pass());
+ root->AddChild(copy_grand_parent.Pass());
+ root->AddChild(copy_grand_parent_sibling_after.Pass());
// Hide the copy_grand_parent and its subtree. But make a copy request in that
// hidden subtree on copy_layer.
- copy_grand_parent->SetHideLayerAndSubtree(true);
- copy_grand_parent_sibling_before->SetHideLayerAndSubtree(true);
- copy_grand_parent_sibling_after->SetHideLayerAndSubtree(true);
- copy_layer->RequestCopyOfOutput(CopyOutputRequest::CreateRequest(
- base::Bind(&EmptyCopyOutputCallback)));
+ copy_grand_parent_layer->SetHideLayerAndSubtree(true);
+ copy_grand_parent_sibling_before_layer->SetHideLayerAndSubtree(true);
+ copy_grand_parent_sibling_after_layer->SetHideLayerAndSubtree(true);
+
+ ScopedPtrVector<CopyOutputRequest> copy_requests;
+ copy_requests.push_back(
+ CopyOutputRequest::CreateRequest(base::Bind(&EmptyCopyOutputCallback)));
+ copy_layer->PassCopyRequests(&copy_requests);
EXPECT_TRUE(copy_layer->HasCopyRequest());
- RenderSurfaceLayerList render_surface_layer_list;
- LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
+ LayerImplList render_surface_layer_list;
+ LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs(
root.get(), root->bounds(), &render_surface_layer_list);
inputs.can_adjust_raster_scales = true;
LayerTreeHostCommon::CalculateDrawProperties(&inputs);
- EXPECT_TRUE(root->draw_properties().layer_or_descendant_has_copy_request);
- EXPECT_TRUE(copy_grand_parent->draw_properties().
- layer_or_descendant_has_copy_request);
- EXPECT_TRUE(copy_parent->draw_properties().
- layer_or_descendant_has_copy_request);
- EXPECT_TRUE(copy_layer->draw_properties().
- layer_or_descendant_has_copy_request);
- EXPECT_FALSE(copy_child->draw_properties().
- layer_or_descendant_has_copy_request);
- EXPECT_FALSE(copy_grand_parent_sibling_before->draw_properties().
- layer_or_descendant_has_copy_request);
- EXPECT_FALSE(copy_grand_parent_sibling_after->draw_properties().
- layer_or_descendant_has_copy_request);
+ EXPECT_GT(root->num_layer_or_descendants_with_copy_request(), 0);
+ EXPECT_GT(
+ copy_grand_parent_layer->num_layer_or_descendants_with_copy_request(), 0);
+ EXPECT_GT(copy_parent_layer->num_layer_or_descendants_with_copy_request(), 0);
+ EXPECT_GT(copy_layer->num_layer_or_descendants_with_copy_request(), 0);
+ EXPECT_EQ(copy_child_layer->num_layer_or_descendants_with_copy_request(), 0);
+ EXPECT_EQ(copy_grand_parent_sibling_before_layer
+ ->num_layer_or_descendants_with_copy_request(),
+ 0);
+ EXPECT_EQ(copy_grand_parent_sibling_after_layer
+ ->num_layer_or_descendants_with_copy_request(),
+ 0);
// We should have three render surfaces, one for the root, one for the parent
// since it owns a surface, and one for the copy_layer.
ASSERT_EQ(3u, render_surface_layer_list.size());
EXPECT_EQ(root->id(), render_surface_layer_list.at(0)->id());
- EXPECT_EQ(copy_parent->id(), render_surface_layer_list.at(1)->id());
+ EXPECT_EQ(copy_parent_layer->id(), render_surface_layer_list.at(1)->id());
EXPECT_EQ(copy_layer->id(), render_surface_layer_list.at(2)->id());
// The root render surface should have 2 contributing layers. The
@@ -5286,20 +4477,20 @@ TEST_F(LayerTreeHostCommonTest, SubtreeHiddenWithCopyRequest) {
// request.
ASSERT_EQ(2u, root->render_surface()->layer_list().size());
EXPECT_EQ(root->id(), root->render_surface()->layer_list().at(0)->id());
- EXPECT_EQ(copy_parent->id(),
+ EXPECT_EQ(copy_parent_layer->id(),
root->render_surface()->layer_list().at(1)->id());
// Nothing actually draws into the copy parent, so only the copy_layer will
// appear in its list, since it needs to be drawn for the copy request.
- ASSERT_EQ(1u, copy_parent->render_surface()->layer_list().size());
+ ASSERT_EQ(1u, copy_parent_layer->render_surface()->layer_list().size());
EXPECT_EQ(copy_layer->id(),
- copy_parent->render_surface()->layer_list().at(0)->id());
+ copy_parent_layer->render_surface()->layer_list().at(0)->id());
// The copy_layer's render surface should have two contributing layers.
ASSERT_EQ(2u, copy_layer->render_surface()->layer_list().size());
EXPECT_EQ(copy_layer->id(),
copy_layer->render_surface()->layer_list().at(0)->id());
- EXPECT_EQ(copy_child->id(),
+ EXPECT_EQ(copy_child_layer->id(),
copy_layer->render_surface()->layer_list().at(1)->id());
}
@@ -5312,59 +4503,46 @@ TEST_F(LayerTreeHostCommonTest, ClippedOutCopyRequest) {
host_impl.CreatePendingTree();
const gfx::Transform identity_matrix;
- scoped_refptr<Layer> root = Layer::Create(layer_settings());
- SetLayerPropertiesForTesting(root.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(50, 50),
- true,
- false);
- root->SetIsDrawable(true);
+ scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl.pending_tree(), 1);
+ SetLayerPropertiesForTesting(root.get(), identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(50, 50), true, false,
+ true);
+ root->SetDrawsContent(true);
- scoped_refptr<Layer> copy_parent = Layer::Create(layer_settings());
- SetLayerPropertiesForTesting(copy_parent.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(),
- true,
- false);
- copy_parent->SetIsDrawable(true);
+ scoped_ptr<LayerImpl> copy_parent =
+ LayerImpl::Create(host_impl.pending_tree(), 2);
+ SetLayerPropertiesForTesting(copy_parent.get(), identity_matrix,
+ gfx::Point3F(), gfx::PointF(), gfx::Size(), true,
+ false, false);
+ copy_parent->SetDrawsContent(true);
copy_parent->SetMasksToBounds(true);
- scoped_refptr<Layer> copy_layer = Layer::Create(layer_settings());
- SetLayerPropertiesForTesting(copy_layer.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(30, 30),
- true,
- false);
- copy_layer->SetIsDrawable(true);
-
- scoped_refptr<Layer> copy_child = Layer::Create(layer_settings());
- SetLayerPropertiesForTesting(copy_child.get(),
- identity_matrix,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(20, 20),
- true,
- false);
- copy_child->SetIsDrawable(true);
-
- copy_layer->AddChild(copy_child);
- copy_parent->AddChild(copy_layer);
- root->AddChild(copy_parent);
+ scoped_ptr<LayerImpl> copy_layer =
+ LayerImpl::Create(host_impl.pending_tree(), 3);
+ SetLayerPropertiesForTesting(copy_layer.get(), identity_matrix,
+ gfx::Point3F(), gfx::PointF(), gfx::Size(30, 30),
+ true, false, true);
+ copy_layer->SetDrawsContent(true);
- host()->SetRootLayer(root);
+ scoped_ptr<LayerImpl> copy_child =
+ LayerImpl::Create(host_impl.pending_tree(), 4);
+ SetLayerPropertiesForTesting(copy_child.get(), identity_matrix,
+ gfx::Point3F(), gfx::PointF(), gfx::Size(20, 20),
+ true, false, false);
+ copy_child->SetDrawsContent(true);
- copy_layer->RequestCopyOfOutput(CopyOutputRequest::CreateRequest(
- base::Bind(&EmptyCopyOutputCallback)));
+ ScopedPtrVector<CopyOutputRequest> copy_requests;
+ copy_requests.push_back(
+ CopyOutputRequest::CreateRequest(base::Bind(&EmptyCopyOutputCallback)));
+ copy_layer->PassCopyRequests(&copy_requests);
EXPECT_TRUE(copy_layer->HasCopyRequest());
- RenderSurfaceLayerList render_surface_layer_list;
- LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
+ copy_layer->AddChild(copy_child.Pass());
+ copy_parent->AddChild(copy_layer.Pass());
+ root->AddChild(copy_parent.Pass());
+
+ LayerImplList render_surface_layer_list;
+ LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs(
root.get(), root->bounds(), &render_surface_layer_list);
inputs.can_adjust_raster_scales = true;
LayerTreeHostCommon::CalculateDrawProperties(&inputs);
@@ -5424,16 +4602,14 @@ TEST_F(LayerTreeHostCommonTest, VisibleContentRectInsideSurface) {
host()->SetRootLayer(root);
- RenderSurfaceLayerList render_surface_layer_list;
- LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
- root.get(), root->bounds(), &render_surface_layer_list);
- inputs.can_adjust_raster_scales = true;
+ LayerTreeHostCommon::CalcDrawPropsMainInputs inputs(root.get(),
+ root->bounds());
LayerTreeHostCommon::CalculateDrawProperties(&inputs);
// The visible_layer_rect for the |surface_child| should not be clipped by
// the viewport.
EXPECT_EQ(gfx::Rect(50, 50).ToString(),
- surface_child->visible_layer_rect().ToString());
+ surface_child->visible_rect_from_property_trees().ToString());
}
TEST_F(LayerTreeHostCommonTest, TransformedClipParent) {
@@ -5448,69 +4624,42 @@ TEST_F(LayerTreeHostCommonTest, TransformedClipParent) {
//
// The render surface should be resized correctly and the clip child should
// inherit the right clip rect.
- scoped_refptr<Layer> root = Layer::Create(layer_settings());
- scoped_refptr<Layer> render_surface = Layer::Create(layer_settings());
- scoped_refptr<Layer> clip_parent = Layer::Create(layer_settings());
- scoped_refptr<Layer> intervening = Layer::Create(layer_settings());
- scoped_refptr<LayerWithForcedDrawsContent> clip_child =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
-
- root->AddChild(render_surface);
- render_surface->AddChild(clip_parent);
- clip_parent->AddChild(intervening);
- intervening->AddChild(clip_child);
-
- clip_child->SetClipParent(clip_parent.get());
+ LayerImpl* root = root_layer();
+ LayerImpl* render_surface = AddChildToRoot<LayerImpl>();
+ LayerImpl* clip_parent = AddChild<LayerImpl>(render_surface);
+ LayerImpl* intervening = AddChild<LayerImpl>(clip_parent);
+ LayerImpl* clip_child = AddChild<LayerImpl>(intervening);
+ clip_child->SetDrawsContent(true);
+ clip_child->SetClipParent(clip_parent);
+ scoped_ptr<std::set<LayerImpl*>> clip_children(new std::set<LayerImpl*>);
+ clip_children->insert(clip_child);
+ clip_parent->SetClipChildren(clip_children.release());
intervening->SetMasksToBounds(true);
clip_parent->SetMasksToBounds(true);
- render_surface->SetForceRenderSurface(true);
-
gfx::Transform scale_transform;
scale_transform.Scale(2, 2);
gfx::Transform identity_transform;
- SetLayerPropertiesForTesting(root.get(),
- identity_transform,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(50, 50),
- true,
- false);
- SetLayerPropertiesForTesting(render_surface.get(),
- identity_transform,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(10, 10),
- true,
- false);
- SetLayerPropertiesForTesting(clip_parent.get(),
- scale_transform,
- gfx::Point3F(),
- gfx::PointF(1.f, 1.f),
- gfx::Size(10, 10),
- true,
- false);
- SetLayerPropertiesForTesting(intervening.get(),
- identity_transform,
- gfx::Point3F(),
- gfx::PointF(1.f, 1.f),
- gfx::Size(5, 5),
- true,
- false);
- SetLayerPropertiesForTesting(clip_child.get(),
- identity_transform,
- gfx::Point3F(),
- gfx::PointF(1.f, 1.f),
- gfx::Size(10, 10),
- true,
- false);
-
- host()->SetRootLayer(root);
+ SetLayerPropertiesForTesting(root, identity_transform, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(50, 50), true, false,
+ true);
+ SetLayerPropertiesForTesting(render_surface, identity_transform,
+ gfx::Point3F(), gfx::PointF(), gfx::Size(10, 10),
+ true, false, true);
+ SetLayerPropertiesForTesting(clip_parent, scale_transform, gfx::Point3F(),
+ gfx::PointF(1.f, 1.f), gfx::Size(10, 10), true,
+ false, false);
+ SetLayerPropertiesForTesting(intervening, identity_transform, gfx::Point3F(),
+ gfx::PointF(1.f, 1.f), gfx::Size(5, 5), true,
+ false, false);
+ SetLayerPropertiesForTesting(clip_child, identity_transform, gfx::Point3F(),
+ gfx::PointF(1.f, 1.f), gfx::Size(10, 10), true,
+ false, false);
- ExecuteCalculateDrawProperties(root.get());
+ ExecuteCalculateDrawProperties(root);
ASSERT_TRUE(root->render_surface());
ASSERT_TRUE(render_surface->render_surface());
@@ -5549,78 +4698,43 @@ TEST_F(LayerTreeHostCommonTest, ClipParentWithInterveningRenderSurface) {
// + render_surface2 (also sets opacity)
// + clip_child
//
- scoped_refptr<Layer> root = Layer::Create(layer_settings());
- scoped_refptr<Layer> clip_parent = Layer::Create(layer_settings());
- scoped_refptr<Layer> render_surface1 = Layer::Create(layer_settings());
- scoped_refptr<Layer> intervening = Layer::Create(layer_settings());
- scoped_refptr<Layer> render_surface2 = Layer::Create(layer_settings());
- scoped_refptr<LayerWithForcedDrawsContent> clip_child =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
-
- root->AddChild(clip_parent);
- clip_parent->AddChild(render_surface1);
- render_surface1->AddChild(intervening);
- intervening->AddChild(render_surface2);
- render_surface2->AddChild(clip_child);
+ LayerImpl* root = root_layer();
+ LayerImpl* clip_parent = AddChildToRoot<LayerImpl>();
+ LayerImpl* render_surface1 = AddChild<LayerImpl>(clip_parent);
+ LayerImpl* intervening = AddChild<LayerImpl>(render_surface1);
+ LayerImpl* render_surface2 = AddChild<LayerImpl>(intervening);
+ LayerImpl* clip_child = AddChild<LayerImpl>(render_surface2);
+ clip_child->SetDrawsContent(true);
- clip_child->SetClipParent(clip_parent.get());
+ clip_child->SetClipParent(clip_parent);
intervening->SetMasksToBounds(true);
clip_parent->SetMasksToBounds(true);
- render_surface1->SetForceRenderSurface(true);
- render_surface2->SetForceRenderSurface(true);
-
gfx::Transform translation_transform;
translation_transform.Translate(2, 2);
gfx::Transform identity_transform;
- SetLayerPropertiesForTesting(root.get(),
- identity_transform,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(50, 50),
- true,
- false);
- SetLayerPropertiesForTesting(clip_parent.get(),
- translation_transform,
- gfx::Point3F(),
- gfx::PointF(1.f, 1.f),
- gfx::Size(40, 40),
- true,
- false);
- SetLayerPropertiesForTesting(render_surface1.get(),
- identity_transform,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(10, 10),
- true,
- false);
- SetLayerPropertiesForTesting(intervening.get(),
- identity_transform,
- gfx::Point3F(),
- gfx::PointF(1.f, 1.f),
- gfx::Size(5, 5),
- true,
- false);
- SetLayerPropertiesForTesting(render_surface2.get(),
- identity_transform,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(10, 10),
- true,
- false);
- SetLayerPropertiesForTesting(clip_child.get(),
- identity_transform,
- gfx::Point3F(),
- gfx::PointF(-10.f, -10.f),
- gfx::Size(60, 60),
- true,
- false);
-
- host()->SetRootLayer(root);
+ SetLayerPropertiesForTesting(root, identity_transform, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(50, 50), true, false,
+ true);
+ SetLayerPropertiesForTesting(clip_parent, translation_transform,
+ gfx::Point3F(), gfx::PointF(1.f, 1.f),
+ gfx::Size(40, 40), true, false, false);
+ SetLayerPropertiesForTesting(render_surface1, identity_transform,
+ gfx::Point3F(), gfx::PointF(), gfx::Size(10, 10),
+ true, false, true);
+ SetLayerPropertiesForTesting(intervening, identity_transform, gfx::Point3F(),
+ gfx::PointF(1.f, 1.f), gfx::Size(5, 5), true,
+ false, false);
+ SetLayerPropertiesForTesting(render_surface2, identity_transform,
+ gfx::Point3F(), gfx::PointF(), gfx::Size(10, 10),
+ true, false, true);
+ SetLayerPropertiesForTesting(clip_child, identity_transform, gfx::Point3F(),
+ gfx::PointF(-10.f, -10.f), gfx::Size(60, 60),
+ true, false, false);
- ExecuteCalculateDrawProperties(root.get());
+ ExecuteCalculateDrawProperties(root);
EXPECT_TRUE(root->render_surface());
EXPECT_TRUE(render_surface1->render_surface());
@@ -5675,80 +4789,45 @@ TEST_F(LayerTreeHostCommonTest, ClipParentScrolledInterveningLayer) {
// + render_surface2 (also sets opacity)
// + clip_child
//
- scoped_refptr<Layer> root = Layer::Create(layer_settings());
- scoped_refptr<Layer> clip_parent = Layer::Create(layer_settings());
- scoped_refptr<Layer> render_surface1 = Layer::Create(layer_settings());
- scoped_refptr<Layer> intervening = Layer::Create(layer_settings());
- scoped_refptr<Layer> render_surface2 = Layer::Create(layer_settings());
- scoped_refptr<LayerWithForcedDrawsContent> clip_child =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
-
- root->AddChild(clip_parent);
- clip_parent->AddChild(render_surface1);
- render_surface1->AddChild(intervening);
- intervening->AddChild(render_surface2);
- render_surface2->AddChild(clip_child);
+ LayerImpl* root = root_layer();
+ LayerImpl* clip_parent = AddChildToRoot<LayerImpl>();
+ LayerImpl* render_surface1 = AddChild<LayerImpl>(clip_parent);
+ LayerImpl* intervening = AddChild<LayerImpl>(render_surface1);
+ LayerImpl* render_surface2 = AddChild<LayerImpl>(intervening);
+ LayerImpl* clip_child = AddChild<LayerImpl>(render_surface2);
+ clip_child->SetDrawsContent(true);
- clip_child->SetClipParent(clip_parent.get());
+ clip_child->SetClipParent(clip_parent);
intervening->SetMasksToBounds(true);
clip_parent->SetMasksToBounds(true);
- intervening->SetScrollClipLayerId(clip_parent->id());
- intervening->SetScrollOffset(gfx::ScrollOffset(3, 3));
-
- render_surface1->SetForceRenderSurface(true);
- render_surface2->SetForceRenderSurface(true);
+ intervening->SetScrollClipLayer(clip_parent->id());
+ intervening->SetCurrentScrollOffset(gfx::ScrollOffset(3, 3));
gfx::Transform translation_transform;
translation_transform.Translate(2, 2);
gfx::Transform identity_transform;
- SetLayerPropertiesForTesting(root.get(),
- identity_transform,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(50, 50),
- true,
- false);
- SetLayerPropertiesForTesting(clip_parent.get(),
- translation_transform,
- gfx::Point3F(),
- gfx::PointF(1.f, 1.f),
- gfx::Size(40, 40),
- true,
- false);
- SetLayerPropertiesForTesting(render_surface1.get(),
- identity_transform,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(10, 10),
- true,
- false);
- SetLayerPropertiesForTesting(intervening.get(),
- identity_transform,
- gfx::Point3F(),
- gfx::PointF(1.f, 1.f),
- gfx::Size(5, 5),
- true,
- false);
- SetLayerPropertiesForTesting(render_surface2.get(),
- identity_transform,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(10, 10),
- true,
- false);
- SetLayerPropertiesForTesting(clip_child.get(),
- identity_transform,
- gfx::Point3F(),
- gfx::PointF(-10.f, -10.f),
- gfx::Size(60, 60),
- true,
- false);
-
- host()->SetRootLayer(root);
+ SetLayerPropertiesForTesting(root, identity_transform, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(50, 50), true, false,
+ true);
+ SetLayerPropertiesForTesting(clip_parent, translation_transform,
+ gfx::Point3F(), gfx::PointF(1.f, 1.f),
+ gfx::Size(40, 40), true, false, false);
+ SetLayerPropertiesForTesting(render_surface1, identity_transform,
+ gfx::Point3F(), gfx::PointF(), gfx::Size(10, 10),
+ true, false, true);
+ SetLayerPropertiesForTesting(intervening, identity_transform, gfx::Point3F(),
+ gfx::PointF(1.f, 1.f), gfx::Size(5, 5), true,
+ false, false);
+ SetLayerPropertiesForTesting(render_surface2, identity_transform,
+ gfx::Point3F(), gfx::PointF(), gfx::Size(10, 10),
+ true, false, true);
+ SetLayerPropertiesForTesting(clip_child, identity_transform, gfx::Point3F(),
+ gfx::PointF(-10.f, -10.f), gfx::Size(60, 60),
+ true, false, false);
- ExecuteCalculateDrawProperties(root.get());
+ ExecuteCalculateDrawProperties(root);
EXPECT_TRUE(root->render_surface());
EXPECT_TRUE(render_surface1->render_surface());
@@ -5800,63 +4879,39 @@ TEST_F(LayerTreeHostCommonTest, DescendantsOfClipChildren) {
// + clip_child
// + child
//
- scoped_refptr<Layer> root = Layer::Create(layer_settings());
- scoped_refptr<Layer> clip_parent = Layer::Create(layer_settings());
- scoped_refptr<Layer> intervening = Layer::Create(layer_settings());
- scoped_refptr<Layer> clip_child = Layer::Create(layer_settings());
- scoped_refptr<LayerWithForcedDrawsContent> child =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
-
- root->AddChild(clip_parent);
- clip_parent->AddChild(intervening);
- intervening->AddChild(clip_child);
- clip_child->AddChild(child);
+ LayerImpl* root = root_layer();
+ LayerImpl* clip_parent = AddChild<LayerImpl>(root);
+ LayerImpl* intervening = AddChild<LayerImpl>(clip_parent);
+ LayerImpl* clip_child = AddChild<LayerImpl>(intervening);
+ LayerImpl* child = AddChild<LayerImpl>(clip_child);
+ child->SetDrawsContent(true);
- clip_child->SetClipParent(clip_parent.get());
+ clip_child->SetClipParent(clip_parent);
+ scoped_ptr<std::set<LayerImpl*>> clip_children(new std::set<LayerImpl*>);
+ clip_children->insert(clip_child);
+ clip_parent->SetClipChildren(clip_children.release());
intervening->SetMasksToBounds(true);
clip_parent->SetMasksToBounds(true);
gfx::Transform identity_transform;
- SetLayerPropertiesForTesting(root.get(),
- identity_transform,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(50, 50),
- true,
- false);
- SetLayerPropertiesForTesting(clip_parent.get(),
- identity_transform,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(40, 40),
- true,
+ SetLayerPropertiesForTesting(root, identity_transform, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(50, 50), true, false,
+ true);
+ SetLayerPropertiesForTesting(clip_parent, identity_transform, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(40, 40), true, false,
false);
- SetLayerPropertiesForTesting(intervening.get(),
- identity_transform,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(5, 5),
- true,
+ SetLayerPropertiesForTesting(intervening, identity_transform, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(5, 5), true, false,
false);
- SetLayerPropertiesForTesting(clip_child.get(),
- identity_transform,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(60, 60),
- true,
+ SetLayerPropertiesForTesting(clip_child, identity_transform, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(60, 60), true, false,
false);
- SetLayerPropertiesForTesting(child.get(),
- identity_transform,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(60, 60),
- true,
+ SetLayerPropertiesForTesting(child, identity_transform, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(60, 60), true, false,
false);
- host()->SetRootLayer(root);
-
- ExecuteCalculateDrawProperties(root.get());
+ ExecuteCalculateDrawProperties(root);
EXPECT_TRUE(root->render_surface());
@@ -5883,76 +4938,44 @@ TEST_F(LayerTreeHostCommonTest,
// + non_clip_child
//
// In this example render_surface2 should be unaffected by clip_child.
- scoped_refptr<Layer> root = Layer::Create(layer_settings());
- scoped_refptr<Layer> clip_parent = Layer::Create(layer_settings());
- scoped_refptr<Layer> render_surface1 = Layer::Create(layer_settings());
- scoped_refptr<LayerWithForcedDrawsContent> clip_child =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
- scoped_refptr<Layer> render_surface2 = Layer::Create(layer_settings());
- scoped_refptr<LayerWithForcedDrawsContent> non_clip_child =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
-
- root->AddChild(clip_parent);
- clip_parent->AddChild(render_surface1);
- render_surface1->AddChild(clip_child);
- clip_parent->AddChild(render_surface2);
- render_surface2->AddChild(non_clip_child);
-
- clip_child->SetClipParent(clip_parent.get());
+ LayerImpl* root = root_layer();
+ LayerImpl* clip_parent = AddChildToRoot<LayerImpl>();
+ LayerImpl* render_surface1 = AddChild<LayerImpl>(clip_parent);
+ LayerImpl* clip_child = AddChild<LayerImpl>(render_surface1);
+ clip_child->SetDrawsContent(true);
+ LayerImpl* render_surface2 = AddChild<LayerImpl>(clip_parent);
+ LayerImpl* non_clip_child = AddChild<LayerImpl>(render_surface2);
+ non_clip_child->SetDrawsContent(true);
+
+ clip_child->SetClipParent(clip_parent);
+ scoped_ptr<std::set<LayerImpl*>> clip_children(new std::set<LayerImpl*>);
+ clip_children->insert(clip_child);
+ clip_parent->SetClipChildren(clip_children.release());
clip_parent->SetMasksToBounds(true);
render_surface1->SetMasksToBounds(true);
gfx::Transform identity_transform;
- SetLayerPropertiesForTesting(root.get(),
- identity_transform,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(15, 15),
- true,
- false);
- SetLayerPropertiesForTesting(clip_parent.get(),
- identity_transform,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(10, 10),
- true,
- false);
- SetLayerPropertiesForTesting(render_surface1.get(),
- identity_transform,
- gfx::Point3F(),
- gfx::PointF(5, 5),
- gfx::Size(5, 5),
- true,
- false);
- SetLayerPropertiesForTesting(render_surface2.get(),
- identity_transform,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(5, 5),
- true,
- false);
- SetLayerPropertiesForTesting(clip_child.get(),
- identity_transform,
- gfx::Point3F(),
- gfx::PointF(-1, 1),
- gfx::Size(10, 10),
- true,
- false);
- SetLayerPropertiesForTesting(non_clip_child.get(),
- identity_transform,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(5, 5),
- true,
+ SetLayerPropertiesForTesting(root, identity_transform, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(15, 15), true, false,
+ true);
+ SetLayerPropertiesForTesting(clip_parent, identity_transform, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(10, 10), true, false,
false);
+ SetLayerPropertiesForTesting(render_surface1, identity_transform,
+ gfx::Point3F(), gfx::PointF(5, 5),
+ gfx::Size(5, 5), true, false, true);
+ SetLayerPropertiesForTesting(render_surface2, identity_transform,
+ gfx::Point3F(), gfx::PointF(), gfx::Size(5, 5),
+ true, false, true);
+ SetLayerPropertiesForTesting(clip_child, identity_transform, gfx::Point3F(),
+ gfx::PointF(-1, 1), gfx::Size(10, 10), true,
+ false, false);
+ SetLayerPropertiesForTesting(non_clip_child, identity_transform,
+ gfx::Point3F(), gfx::PointF(), gfx::Size(5, 5),
+ true, false, false);
- render_surface1->SetForceRenderSurface(true);
- render_surface2->SetForceRenderSurface(true);
-
- host()->SetRootLayer(root);
-
- ExecuteCalculateDrawProperties(root.get());
+ ExecuteCalculateDrawProperties(root);
EXPECT_TRUE(root->render_surface());
EXPECT_TRUE(render_surface1->render_surface());
@@ -6152,64 +5175,39 @@ TEST_F(LayerTreeHostCommonTest, ClippedByScrollParent) {
// | + scroll_parent
// + scroll_child
//
- scoped_refptr<Layer> root = Layer::Create(layer_settings());
- scoped_refptr<Layer> scroll_parent_border = Layer::Create(layer_settings());
- scoped_refptr<Layer> scroll_parent_clip = Layer::Create(layer_settings());
- scoped_refptr<LayerWithForcedDrawsContent> scroll_parent =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
- scoped_refptr<LayerWithForcedDrawsContent> scroll_child =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
-
- root->AddChild(scroll_child);
-
- root->AddChild(scroll_parent_border);
- scroll_parent_border->AddChild(scroll_parent_clip);
- scroll_parent_clip->AddChild(scroll_parent);
+ LayerImpl* root = root_layer();
+ LayerImpl* scroll_parent_border = AddChildToRoot<LayerImpl>();
+ LayerImpl* scroll_parent_clip = AddChild<LayerImpl>(scroll_parent_border);
+ LayerImpl* scroll_parent = AddChild<LayerImpl>(scroll_parent_clip);
+ LayerImpl* scroll_child = AddChild<LayerImpl>(root);
+ scroll_parent->SetDrawsContent(true);
+ scroll_child->SetDrawsContent(true);
scroll_parent_clip->SetMasksToBounds(true);
- scroll_child->SetScrollParent(scroll_parent.get());
+ scroll_child->SetScrollParent(scroll_parent);
+ scoped_ptr<std::set<LayerImpl*>> scroll_children(new std::set<LayerImpl*>);
+ scroll_children->insert(scroll_child);
+ scroll_parent->SetScrollChildren(scroll_children.release());
gfx::Transform identity_transform;
- SetLayerPropertiesForTesting(root.get(),
- identity_transform,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(50, 50),
- true,
- false);
- SetLayerPropertiesForTesting(scroll_parent_border.get(),
- identity_transform,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(40, 40),
- true,
- false);
- SetLayerPropertiesForTesting(scroll_parent_clip.get(),
- identity_transform,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(30, 30),
- true,
- false);
- SetLayerPropertiesForTesting(scroll_parent.get(),
- identity_transform,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(50, 50),
- true,
- false);
- SetLayerPropertiesForTesting(scroll_child.get(),
- identity_transform,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(50, 50),
- true,
+ SetLayerPropertiesForTesting(root, identity_transform, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(50, 50), true, false,
+ true);
+ SetLayerPropertiesForTesting(scroll_parent_border, identity_transform,
+ gfx::Point3F(), gfx::PointF(), gfx::Size(40, 40),
+ true, false, false);
+ SetLayerPropertiesForTesting(scroll_parent_clip, identity_transform,
+ gfx::Point3F(), gfx::PointF(), gfx::Size(30, 30),
+ true, false, false);
+ SetLayerPropertiesForTesting(scroll_parent, identity_transform,
+ gfx::Point3F(), gfx::PointF(), gfx::Size(50, 50),
+ true, false, false);
+ SetLayerPropertiesForTesting(scroll_child, identity_transform, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(50, 50), true, false,
false);
- host()->SetRootLayer(root);
-
- ExecuteCalculateDrawProperties(root.get());
+ ExecuteCalculateDrawProperties(root);
EXPECT_TRUE(root->render_surface());
@@ -6219,47 +5217,27 @@ TEST_F(LayerTreeHostCommonTest, ClippedByScrollParent) {
}
TEST_F(LayerTreeHostCommonTest, SingularTransformSubtreesDoNotDraw) {
- scoped_refptr<LayerWithForcedDrawsContent> root =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
- scoped_refptr<LayerWithForcedDrawsContent> parent =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
- scoped_refptr<LayerWithForcedDrawsContent> child =
- make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
-
- root->AddChild(parent);
- parent->AddChild(child);
+ LayerImpl* root = root_layer();
+ root->SetDrawsContent(true);
+ LayerImpl* parent = AddChildToRoot<LayerImpl>();
+ parent->SetDrawsContent(true);
+ LayerImpl* child = AddChild<LayerImpl>(parent);
+ child->SetDrawsContent(true);
gfx::Transform identity_transform;
- SetLayerPropertiesForTesting(root.get(),
- identity_transform,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(50, 50),
- true,
+ SetLayerPropertiesForTesting(root, identity_transform, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(50, 50), true, true,
true);
- root->SetForceRenderSurface(true);
- SetLayerPropertiesForTesting(parent.get(),
- identity_transform,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(30, 30),
- true,
+ SetLayerPropertiesForTesting(parent, identity_transform, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(30, 30), true, true,
true);
- parent->SetForceRenderSurface(true);
- SetLayerPropertiesForTesting(child.get(),
- identity_transform,
- gfx::Point3F(),
- gfx::PointF(),
- gfx::Size(20, 20),
- true,
+ SetLayerPropertiesForTesting(child, identity_transform, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(20, 20), true, true,
true);
- child->SetForceRenderSurface(true);
- host()->SetRootLayer(root);
-
- ExecuteCalculateDrawProperties(root.get());
+ ExecuteCalculateDrawProperties(root);
- EXPECT_EQ(3u, render_surface_layer_list()->size());
+ EXPECT_EQ(3u, render_surface_layer_list_impl()->size());
gfx::Transform singular_transform;
singular_transform.Scale3d(
@@ -6267,18 +5245,18 @@ TEST_F(LayerTreeHostCommonTest, SingularTransformSubtreesDoNotDraw) {
child->SetTransform(singular_transform);
- ExecuteCalculateDrawProperties(root.get());
+ ExecuteCalculateDrawProperties(root);
- EXPECT_EQ(2u, render_surface_layer_list()->size());
+ EXPECT_EQ(2u, render_surface_layer_list_impl()->size());
// Ensure that the entire subtree under a layer with singular transform does
// not get rendered.
parent->SetTransform(singular_transform);
child->SetTransform(identity_transform);
- ExecuteCalculateDrawProperties(root.get());
+ ExecuteCalculateDrawProperties(root);
- EXPECT_EQ(1u, render_surface_layer_list()->size());
+ EXPECT_EQ(1u, render_surface_layer_list_impl()->size());
}
TEST_F(LayerTreeHostCommonTest, ClippedByOutOfOrderScrollParent) {
@@ -6560,23 +5538,27 @@ TEST_F(LayerTreeHostCommonTest, FixedPositionWithInterveningRenderSurface) {
ExecuteCalculateDrawProperties(root.get());
+ TransformTree& tree = host()->property_trees()->transform_tree;
+
gfx::Transform expected_fixed_draw_transform;
expected_fixed_draw_transform.Translate(10.f, 15.f);
- EXPECT_EQ(expected_fixed_draw_transform, fixed->draw_transform());
+ EXPECT_EQ(expected_fixed_draw_transform,
+ DrawTransformFromPropertyTrees(fixed.get(), tree));
gfx::Transform expected_fixed_screen_space_transform;
expected_fixed_screen_space_transform.Translate(17.f, 24.f);
EXPECT_EQ(expected_fixed_screen_space_transform,
- fixed->screen_space_transform());
+ ScreenSpaceTransformFromPropertyTrees(fixed.get(), tree));
gfx::Transform expected_child_draw_transform;
expected_child_draw_transform.Translate(11.f, 17.f);
- EXPECT_EQ(expected_child_draw_transform, child->draw_transform());
+ EXPECT_EQ(expected_child_draw_transform,
+ DrawTransformFromPropertyTrees(child.get(), tree));
gfx::Transform expected_child_screen_space_transform;
expected_child_screen_space_transform.Translate(18.f, 26.f);
EXPECT_EQ(expected_child_screen_space_transform,
- child->screen_space_transform());
+ ScreenSpaceTransformFromPropertyTrees(child.get(), tree));
}
TEST_F(LayerTreeHostCommonTest, ScrollCompensationWithRounding) {
@@ -6810,6 +5792,63 @@ TEST_F(LayerTreeHostCommonTest,
container_offset - rounded_effective_scroll_offset);
}
+TEST_F(LayerTreeHostCommonTest,
+ ScrollSnappingWithAnimatedScreenSpaceTransform) {
+ // This test verifies that a scrolling layer whose screen space transform is
+ // animating doesn't get snapped to integer coordinates.
+ //
+ // + root
+ // + animated layer
+ // + surface
+ // + container
+ // + scroller
+ //
+ LayerImpl* root = root_layer();
+ LayerImpl* animated_layer = AddChildToRoot<FakePictureLayerImpl>();
+ LayerImpl* surface = AddChild<LayerImpl>(animated_layer);
+ LayerImpl* container = AddChild<LayerImpl>(surface);
+ LayerImpl* scroller = AddChild<LayerImpl>(container);
+ scroller->SetScrollClipLayer(container->id());
+ scroller->SetDrawsContent(true);
+
+ gfx::Transform identity_transform;
+ gfx::Transform start_scale;
+ start_scale.Scale(1.5f, 1.5f);
+ SetLayerPropertiesForTesting(root, identity_transform, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(50, 50), true, false,
+ true);
+ SetLayerPropertiesForTesting(animated_layer, start_scale, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(50, 50), true, false,
+ false);
+ SetLayerPropertiesForTesting(surface, identity_transform, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(50, 50), true, false,
+ true);
+ SetLayerPropertiesForTesting(container, identity_transform, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(50, 50), true, false,
+ false);
+ SetLayerPropertiesForTesting(scroller, identity_transform, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(100, 100), true, false,
+ false);
+
+ gfx::Transform end_scale;
+ end_scale.Scale(2.f, 2.f);
+ TransformOperations start_operations;
+ start_operations.AppendMatrix(start_scale);
+ TransformOperations end_operations;
+ end_operations.AppendMatrix(end_scale);
+ AddAnimatedTransformToLayer(animated_layer, 1.0, start_operations,
+ end_operations);
+
+ gfx::Vector2dF scroll_delta(5.f, 9.f);
+ scroller->SetScrollDelta(scroll_delta);
+
+ ExecuteCalculateDrawProperties(root);
+
+ gfx::Vector2dF expected_draw_transform_translation(-7.5f, -13.5f);
+ EXPECT_VECTOR2DF_EQ(expected_draw_transform_translation,
+ scroller->draw_transform().To2dTranslation());
+}
+
class AnimationScaleFactorTrackingLayerImpl : public LayerImpl {
public:
static scoped_ptr<AnimationScaleFactorTrackingLayerImpl> Create(
@@ -6833,7 +5872,9 @@ TEST_F(LayerTreeHostCommonTest, MaximumAnimationScaleFactor) {
FakeImplProxy proxy;
TestSharedBitmapManager shared_bitmap_manager;
TestTaskGraphRunner task_graph_runner;
- FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager,
+ LayerTreeSettings settings;
+ settings.layer_transforms_should_scale_layer_contents = true;
+ FakeLayerTreeHostImpl host_impl(settings, &proxy, &shared_bitmap_manager,
&task_graph_runner);
gfx::Transform identity_matrix;
scoped_ptr<AnimationScaleFactorTrackingLayerImpl> grand_parent =
@@ -6878,6 +5919,16 @@ TEST_F(LayerTreeHostCommonTest, MaximumAnimationScaleFactor) {
EXPECT_EQ(
0.f, grand_child_raw->draw_properties().maximum_animation_contents_scale);
+ EXPECT_EQ(0.f,
+ grand_parent->draw_properties().starting_animation_contents_scale);
+ EXPECT_EQ(0.f,
+ parent_raw->draw_properties().starting_animation_contents_scale);
+ EXPECT_EQ(0.f,
+ child_raw->draw_properties().starting_animation_contents_scale);
+ EXPECT_EQ(
+ 0.f,
+ grand_child_raw->draw_properties().starting_animation_contents_scale);
+
TransformOperations translation;
translation.AppendTranslate(1.f, 2.f, 3.f);
@@ -6893,10 +5944,21 @@ TEST_F(LayerTreeHostCommonTest, MaximumAnimationScaleFactor) {
EXPECT_EQ(
0.f, grand_child_raw->draw_properties().maximum_animation_contents_scale);
+ EXPECT_EQ(0.f,
+ grand_parent->draw_properties().starting_animation_contents_scale);
+ EXPECT_EQ(0.f,
+ parent_raw->draw_properties().starting_animation_contents_scale);
+ EXPECT_EQ(0.f,
+ child_raw->draw_properties().starting_animation_contents_scale);
+ EXPECT_EQ(
+ 0.f,
+ grand_child_raw->draw_properties().starting_animation_contents_scale);
+
TransformOperations scale;
scale.AppendScale(5.f, 4.f, 3.f);
AddAnimatedTransformToLayer(child_raw, 1.0, TransformOperations(), scale);
+ child_raw->layer_tree_impl()->property_trees()->needs_rebuild = true;
ExecuteCalculateDrawProperties(grand_parent.get());
// Only |child| has a scale-affecting animation.
@@ -6908,8 +5970,19 @@ TEST_F(LayerTreeHostCommonTest, MaximumAnimationScaleFactor) {
EXPECT_EQ(
5.f, grand_child_raw->draw_properties().maximum_animation_contents_scale);
+ EXPECT_EQ(0.f,
+ grand_parent->draw_properties().starting_animation_contents_scale);
+ EXPECT_EQ(0.f,
+ parent_raw->draw_properties().starting_animation_contents_scale);
+ EXPECT_EQ(1.f,
+ child_raw->draw_properties().starting_animation_contents_scale);
+ EXPECT_EQ(
+ 1.f,
+ grand_child_raw->draw_properties().starting_animation_contents_scale);
+
AddAnimatedTransformToLayer(
grand_parent.get(), 1.0, TransformOperations(), scale);
+ grand_parent->layer_tree_impl()->property_trees()->needs_rebuild = true;
ExecuteCalculateDrawProperties(grand_parent.get());
// |grand_parent| and |child| have scale-affecting animations.
@@ -6923,7 +5996,18 @@ TEST_F(LayerTreeHostCommonTest, MaximumAnimationScaleFactor) {
EXPECT_EQ(
0.f, grand_child_raw->draw_properties().maximum_animation_contents_scale);
+ EXPECT_EQ(1.f,
+ grand_parent->draw_properties().starting_animation_contents_scale);
+ EXPECT_EQ(1.f,
+ parent_raw->draw_properties().starting_animation_contents_scale);
+ EXPECT_EQ(0.f,
+ child_raw->draw_properties().starting_animation_contents_scale);
+ EXPECT_EQ(
+ 0.f,
+ grand_child_raw->draw_properties().starting_animation_contents_scale);
+
AddAnimatedTransformToLayer(parent_raw, 1.0, TransformOperations(), scale);
+ parent_raw->layer_tree_impl()->property_trees()->needs_rebuild = true;
ExecuteCalculateDrawProperties(grand_parent.get());
// |grand_parent|, |parent|, and |child| have scale-affecting animations.
@@ -6935,6 +6019,16 @@ TEST_F(LayerTreeHostCommonTest, MaximumAnimationScaleFactor) {
EXPECT_EQ(
0.f, grand_child_raw->draw_properties().maximum_animation_contents_scale);
+ EXPECT_EQ(1.f,
+ grand_parent->draw_properties().starting_animation_contents_scale);
+ EXPECT_EQ(0.f,
+ parent_raw->draw_properties().starting_animation_contents_scale);
+ EXPECT_EQ(0.f,
+ child_raw->draw_properties().starting_animation_contents_scale);
+ EXPECT_EQ(
+ 0.f,
+ grand_child_raw->draw_properties().starting_animation_contents_scale);
+
grand_parent->layer_animation_controller()->AbortAnimations(
Animation::TRANSFORM);
parent_raw->layer_animation_controller()->AbortAnimations(
@@ -6947,6 +6041,7 @@ TEST_F(LayerTreeHostCommonTest, MaximumAnimationScaleFactor) {
AddAnimatedTransformToLayer(
child_raw, 1.0, TransformOperations(), perspective);
+ child_raw->layer_tree_impl()->property_trees()->needs_rebuild = true;
ExecuteCalculateDrawProperties(grand_parent.get());
// |child| has a scale-affecting animation but computing the maximum of this
@@ -6959,6 +6054,16 @@ TEST_F(LayerTreeHostCommonTest, MaximumAnimationScaleFactor) {
EXPECT_EQ(
0.f, grand_child_raw->draw_properties().maximum_animation_contents_scale);
+ EXPECT_EQ(0.f,
+ grand_parent->draw_properties().starting_animation_contents_scale);
+ EXPECT_EQ(0.f,
+ parent_raw->draw_properties().starting_animation_contents_scale);
+ EXPECT_EQ(0.f,
+ child_raw->draw_properties().starting_animation_contents_scale);
+ EXPECT_EQ(
+ 0.f,
+ grand_child_raw->draw_properties().starting_animation_contents_scale);
+
child_raw->layer_animation_controller()->AbortAnimations(
Animation::TRANSFORM);
@@ -6982,6 +6087,16 @@ TEST_F(LayerTreeHostCommonTest, MaximumAnimationScaleFactor) {
10.f,
grand_child_raw->draw_properties().maximum_animation_contents_scale);
+ EXPECT_EQ(0.f,
+ grand_parent->draw_properties().starting_animation_contents_scale);
+ EXPECT_EQ(2.f,
+ parent_raw->draw_properties().starting_animation_contents_scale);
+ EXPECT_EQ(2.f,
+ child_raw->draw_properties().starting_animation_contents_scale);
+ EXPECT_EQ(
+ 2.f,
+ grand_child_raw->draw_properties().starting_animation_contents_scale);
+
gfx::Transform perspective_matrix;
perspective_matrix.ApplyPerspectiveDepth(2.f);
child_raw->SetTransform(perspective_matrix);
@@ -6997,6 +6112,16 @@ TEST_F(LayerTreeHostCommonTest, MaximumAnimationScaleFactor) {
EXPECT_EQ(
0.f, grand_child_raw->draw_properties().maximum_animation_contents_scale);
+ EXPECT_EQ(0.f,
+ grand_parent->draw_properties().starting_animation_contents_scale);
+ EXPECT_EQ(2.f,
+ parent_raw->draw_properties().starting_animation_contents_scale);
+ EXPECT_EQ(0.f,
+ child_raw->draw_properties().starting_animation_contents_scale);
+ EXPECT_EQ(
+ 0.f,
+ grand_child_raw->draw_properties().starting_animation_contents_scale);
+
parent_raw->SetTransform(perspective_matrix);
grand_parent->layer_tree_impl()->property_trees()->needs_rebuild = true;
ExecuteCalculateDrawProperties(grand_parent.get());
@@ -7011,6 +6136,16 @@ TEST_F(LayerTreeHostCommonTest, MaximumAnimationScaleFactor) {
EXPECT_EQ(
0.f, grand_child_raw->draw_properties().maximum_animation_contents_scale);
+ EXPECT_EQ(0.f,
+ grand_parent->draw_properties().starting_animation_contents_scale);
+ EXPECT_EQ(0.f,
+ parent_raw->draw_properties().starting_animation_contents_scale);
+ EXPECT_EQ(0.f,
+ child_raw->draw_properties().starting_animation_contents_scale);
+ EXPECT_EQ(
+ 0.f,
+ grand_child_raw->draw_properties().starting_animation_contents_scale);
+
parent_raw->SetTransform(identity_matrix);
child_raw->SetTransform(identity_matrix);
grand_parent->SetTransform(perspective_matrix);
@@ -7026,6 +6161,16 @@ TEST_F(LayerTreeHostCommonTest, MaximumAnimationScaleFactor) {
EXPECT_EQ(0.f, child_raw->draw_properties().maximum_animation_contents_scale);
EXPECT_EQ(
0.f, grand_child_raw->draw_properties().maximum_animation_contents_scale);
+
+ EXPECT_EQ(0.f,
+ grand_parent->draw_properties().starting_animation_contents_scale);
+ EXPECT_EQ(0.f,
+ parent_raw->draw_properties().starting_animation_contents_scale);
+ EXPECT_EQ(0.f,
+ child_raw->draw_properties().starting_animation_contents_scale);
+ EXPECT_EQ(
+ 0.f,
+ grand_child_raw->draw_properties().starting_animation_contents_scale);
}
static int membership_id(LayerImpl* layer) {
@@ -7116,6 +6261,7 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceLayerListMembership) {
// If we force render surface, but none of the layers are in the layer list,
// then this layer should not appear in RSLL.
grand_child1_raw->SetHasRenderSurface(true);
+ grand_child1_raw->layer_tree_impl()->property_trees()->needs_rebuild = true;
ExecuteCalculateDrawProperties(grand_parent_raw);
member_id = render_surface_layer_list_count();
@@ -7155,6 +6301,7 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceLayerListMembership) {
// content.
grand_child1_raw->SetDrawsContent(false);
grand_child1_raw->SetHasRenderSurface(false);
+ grand_child1_raw->layer_tree_impl()->property_trees()->needs_rebuild = true;
child_raw->SetHasRenderSurface(true);
grand_child2_raw->SetDrawsContent(true);
@@ -7176,6 +6323,7 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceLayerListMembership) {
// Add a mask layer to child.
child_raw->SetMaskLayer(LayerImpl::Create(host_impl.active_tree(), 6).Pass());
+ child_raw->layer_tree_impl()->property_trees()->needs_rebuild = true;
ExecuteCalculateDrawProperties(grand_parent_raw);
member_id = render_surface_layer_list_count();
@@ -7204,6 +6352,7 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceLayerListMembership) {
LayerImpl::Create(host_impl.active_tree(), 20);
replica_layer->SetMaskLayer(LayerImpl::Create(host_impl.active_tree(), 21));
child_raw->SetReplicaLayer(replica_layer.Pass());
+ child_raw->layer_tree_impl()->property_trees()->needs_rebuild = true;
ExecuteCalculateDrawProperties(grand_parent_raw);
member_id = render_surface_layer_list_count();
@@ -7267,6 +6416,7 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceLayerListMembership) {
EXPECT_EQ(expected, actual);
child_raw->TakeMaskLayer();
+ child_raw->layer_tree_impl()->property_trees()->needs_rebuild = true;
// Now everyone's a member!
grand_parent_raw->SetDrawsContent(true);
@@ -7483,9 +6633,8 @@ TEST_F(LayerTreeHostCommonTest, VisibleContentRectInChildRenderSurface) {
host()->SetRootLayer(root);
gfx::Size device_viewport_size(768, 582);
- RenderSurfaceLayerList render_surface_layer_list;
- LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
- host()->root_layer(), device_viewport_size, &render_surface_layer_list);
+ LayerTreeHostCommon::CalcDrawPropsMainInputs inputs(host()->root_layer(),
+ device_viewport_size);
inputs.device_scale_factor = 2.f;
inputs.page_scale_factor = 1.f;
inputs.page_scale_layer = NULL;
@@ -7493,11 +6642,13 @@ TEST_F(LayerTreeHostCommonTest, VisibleContentRectInChildRenderSurface) {
// Layers in the root render surface have their visible content rect clipped
// by the viewport.
- EXPECT_EQ(gfx::Rect(768 / 2, 582 / 2), root->visible_layer_rect());
+ EXPECT_EQ(gfx::Rect(768 / 2, 582 / 2),
+ root->visible_rect_from_property_trees());
// Layers drawing to a child render surface should still have their visible
// content rect clipped by the viewport.
- EXPECT_EQ(gfx::Rect(768 / 2, 582 / 2), content->visible_layer_rect());
+ EXPECT_EQ(gfx::Rect(768 / 2, 582 / 2),
+ content->visible_rect_from_property_trees());
}
TEST_F(LayerTreeHostCommonTest, BoundsDeltaAffectVisibleContentRect) {
@@ -7552,11 +6703,9 @@ TEST_F(LayerTreeHostCommonTest, BoundsDeltaAffectVisibleContentRect) {
root, device_viewport_size, &layer_impl_list);
LayerTreeHostCommon::CalculateDrawProperties(&inputs);
-
EXPECT_EQ(gfx::Rect(root_size), sublayer->visible_layer_rect());
root->SetBoundsDelta(gfx::Vector2dF(0.0, 50.0));
-
LayerTreeHostCommon::CalculateDrawProperties(&inputs);
gfx::Rect affected_by_delta(0, 0, root_size.width(),
@@ -7723,9 +6872,9 @@ TEST_F(LayerTreeHostCommonTest,
// This time, flattening does not make |animated|'s transform invertible. This
// means the clip cannot be projected into |surface|'s space, so we treat
- // |surface| and layers that draw into it as fully visible.
- EXPECT_EQ(gfx::Rect(100, 100), surface->visible_rect_from_property_trees());
- EXPECT_EQ(gfx::Rect(200, 200),
+ // |surface| and layers that draw into it as having empty visible rect.
+ EXPECT_EQ(gfx::Rect(), surface->visible_rect_from_property_trees());
+ EXPECT_EQ(gfx::Rect(),
descendant_of_animation->visible_rect_from_property_trees());
}
@@ -7752,9 +6901,9 @@ TEST_F(LayerTreeHostCommonTest, AnimatedFilterCreatesRenderSurface) {
ExecuteCalculateDrawProperties(root.get());
- EXPECT_TRUE(root->render_surface());
- EXPECT_TRUE(child->render_surface());
- EXPECT_FALSE(grandchild->render_surface());
+ EXPECT_TRUE(root->has_render_surface());
+ EXPECT_TRUE(child->has_render_surface());
+ EXPECT_FALSE(grandchild->has_render_surface());
EXPECT_TRUE(root->filters().IsEmpty());
EXPECT_TRUE(child->filters().IsEmpty());
@@ -7765,6 +6914,59 @@ TEST_F(LayerTreeHostCommonTest, AnimatedFilterCreatesRenderSurface) {
EXPECT_FALSE(grandchild->FilterIsAnimating());
}
+// Verify that having a filter animation with a delayed start time creates a
+// render surface.
+TEST_F(LayerTreeHostCommonTest, DelayedFilterAnimationCreatesRenderSurface) {
+ scoped_refptr<Layer> root = Layer::Create(layer_settings());
+ scoped_refptr<Layer> child = Layer::Create(layer_settings());
+ scoped_refptr<Layer> grandchild = Layer::Create(layer_settings());
+ root->AddChild(child);
+ child->AddChild(grandchild);
+
+ gfx::Transform identity_transform;
+ SetLayerPropertiesForTesting(root.get(), identity_transform, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(50, 50), true, false);
+ SetLayerPropertiesForTesting(child.get(), identity_transform, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(50, 50), true, false);
+ SetLayerPropertiesForTesting(grandchild.get(), identity_transform,
+ gfx::Point3F(), gfx::PointF(), gfx::Size(50, 50),
+ true, false);
+ host()->SetRootLayer(root);
+
+ scoped_ptr<KeyframedFilterAnimationCurve> curve(
+ KeyframedFilterAnimationCurve::Create());
+ FilterOperations start_filters;
+ start_filters.Append(FilterOperation::CreateBrightnessFilter(0.1f));
+ FilterOperations end_filters;
+ end_filters.Append(FilterOperation::CreateBrightnessFilter(0.3f));
+ curve->AddKeyframe(
+ FilterKeyframe::Create(base::TimeDelta(), start_filters, nullptr));
+ curve->AddKeyframe(FilterKeyframe::Create(
+ base::TimeDelta::FromMilliseconds(100), end_filters, nullptr));
+ scoped_ptr<Animation> animation =
+ Animation::Create(curve.Pass(), 0, 1, Animation::FILTER);
+ animation->set_fill_mode(Animation::FILL_MODE_NONE);
+ animation->set_time_offset(base::TimeDelta::FromMilliseconds(-1000));
+ child->layer_animation_controller()->AddAnimation(animation.Pass());
+
+ ExecuteCalculateDrawProperties(root.get());
+
+ EXPECT_TRUE(root->has_render_surface());
+ EXPECT_TRUE(child->has_render_surface());
+ EXPECT_FALSE(grandchild->has_render_surface());
+
+ EXPECT_TRUE(root->filters().IsEmpty());
+ EXPECT_TRUE(child->filters().IsEmpty());
+ EXPECT_TRUE(grandchild->filters().IsEmpty());
+
+ EXPECT_FALSE(root->FilterIsAnimating());
+ EXPECT_FALSE(root->HasPotentiallyRunningFilterAnimation());
+ EXPECT_FALSE(child->FilterIsAnimating());
+ EXPECT_TRUE(child->HasPotentiallyRunningFilterAnimation());
+ EXPECT_FALSE(grandchild->FilterIsAnimating());
+ EXPECT_FALSE(grandchild->HasPotentiallyRunningFilterAnimation());
+}
+
// Ensures that the property tree code accounts for offsets between fixed
// position layers and their respective containers.
TEST_F(LayerTreeHostCommonTest, PropertyTreesAccountForFixedParentOffset) {
@@ -8174,6 +7376,25 @@ TEST_F(LayerTreeHostCommonTest, SkippingSubtreeMain) {
EXPECT_EQ(gfx::Rect(0, 0), grandchild->visible_rect_from_property_trees());
child->SetHideLayerAndSubtree(false);
+ gfx::Transform zero_z_scale;
+ zero_z_scale.Scale3d(1, 1, 0);
+ child->SetTransform(zero_z_scale);
+
+ // Add a transform animation with a start delay. Now, even though |child| has
+ // a singular transform, the subtree should still get processed.
+ int animation_id = 0;
+ scoped_ptr<Animation> animation = Animation::Create(
+ scoped_ptr<AnimationCurve>(new FakeTransformTransition(1.0)).Pass(),
+ animation_id, 1, Animation::TRANSFORM);
+ animation->set_fill_mode(Animation::FILL_MODE_NONE);
+ animation->set_time_offset(base::TimeDelta::FromMilliseconds(-1000));
+ child->AddAnimation(animation.Pass());
+ ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get());
+ EXPECT_EQ(gfx::Rect(10, 10), grandchild->visible_rect_from_property_trees());
+ grandchild->set_visible_rect_from_property_trees(gfx::Rect());
+
+ child->RemoveAnimation(animation_id);
+ child->SetTransform(identity);
child->SetOpacity(0.f);
ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get());
EXPECT_EQ(gfx::Rect(0, 0), grandchild->visible_rect_from_property_trees());
@@ -8181,17 +7402,20 @@ TEST_F(LayerTreeHostCommonTest, SkippingSubtreeMain) {
// Now, even though child has zero opacity, we will configure |grandchild| and
// |greatgrandchild| in several ways that should force the subtree to be
// processed anyhow.
- grandchild->SetTouchEventHandlerRegion(Region(gfx::Rect(0, 0, 10, 10)));
+ greatgrandchild->RequestCopyOfOutput(
+ CopyOutputRequest::CreateBitmapRequest(base::Bind(&CopyOutputCallback)));
ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get());
EXPECT_EQ(gfx::Rect(10, 10), grandchild->visible_rect_from_property_trees());
grandchild->set_visible_rect_from_property_trees(gfx::Rect());
- grandchild->SetTouchEventHandlerRegion(Region());
- ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get());
- EXPECT_EQ(gfx::Rect(0, 0), grandchild->visible_rect_from_property_trees());
- grandchild->set_visible_rect_from_property_trees(gfx::Rect());
- greatgrandchild->RequestCopyOfOutput(
- CopyOutputRequest::CreateBitmapRequest(base::Bind(&CopyOutputCallback)));
+ // Add an opacity animation with a start delay.
+ animation_id = 1;
+ animation = Animation::Create(
+ scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(),
+ animation_id, 1, Animation::OPACITY);
+ animation->set_fill_mode(Animation::FILL_MODE_NONE);
+ animation->set_time_offset(base::TimeDelta::FromMilliseconds(-1000));
+ child->AddAnimation(animation.Pass());
ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get());
EXPECT_EQ(gfx::Rect(10, 10), grandchild->visible_rect_from_property_trees());
}
@@ -8270,17 +7494,6 @@ TEST_F(LayerTreeHostCommonTest, SkippingSubtreeImpl) {
// Now, even though child has zero opacity, we will configure |grandchild| and
// |greatgrandchild| in several ways that should force the subtree to be
// processed anyhow.
- grandchild_ptr->SetTouchEventHandlerRegion(Region(gfx::Rect(0, 0, 10, 10)));
- ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get());
- EXPECT_EQ(gfx::Rect(10, 10),
- grandchild_ptr->visible_rect_from_property_trees());
- grandchild_ptr->set_visible_rect_from_property_trees(gfx::Rect());
- grandchild_ptr->SetTouchEventHandlerRegion(Region());
- ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get());
- EXPECT_EQ(gfx::Rect(0, 0),
- grandchild_ptr->visible_rect_from_property_trees());
- grandchild_ptr->set_visible_rect_from_property_trees(gfx::Rect());
-
ScopedPtrVector<CopyOutputRequest> requests;
requests.push_back(CopyOutputRequest::CreateEmptyRequest());
@@ -8356,50 +7569,37 @@ TEST_F(LayerTreeHostCommonTest, LayerTreeRebuildTest) {
host()->SetRootLayer(root);
ExecuteCalculateDrawProperties(root.get());
- EXPECT_EQ(parent->draw_properties().num_unclipped_descendants, 1u);
-
- // Ensure the dynamic update to input handlers happens.
- child->SetHaveWheelEventHandlers(true);
- EXPECT_TRUE(root->draw_properties().layer_or_descendant_has_input_handler);
- ExecuteCalculateDrawProperties(root.get());
- EXPECT_TRUE(root->draw_properties().layer_or_descendant_has_input_handler);
-
- child->SetHaveWheelEventHandlers(false);
- EXPECT_FALSE(root->draw_properties().layer_or_descendant_has_input_handler);
- ExecuteCalculateDrawProperties(root.get());
- EXPECT_FALSE(root->draw_properties().layer_or_descendant_has_input_handler);
+ EXPECT_EQ(parent->num_unclipped_descendants(), 1u);
child->RequestCopyOfOutput(
CopyOutputRequest::CreateRequest(base::Bind(&EmptyCopyOutputCallback)));
- EXPECT_TRUE(root->draw_properties().layer_or_descendant_has_copy_request);
+ EXPECT_GT(root->num_layer_or_descendants_with_copy_request(), 0);
ExecuteCalculateDrawProperties(root.get());
- EXPECT_TRUE(root->draw_properties().layer_or_descendant_has_copy_request);
+ EXPECT_GT(root->num_layer_or_descendants_with_copy_request(), 0);
}
TEST_F(LayerTreeHostCommonTest, InputHandlersRecursiveUpdateTest) {
// Ensure that the treewalk in LayertreeHostCommon::
// PreCalculateMetaInformation updates input handlers correctly.
- scoped_refptr<Layer> root = Layer::Create(layer_settings());
- scoped_refptr<Layer> child = Layer::Create(layer_settings());
-
- root->AddChild(child);
-
- child->SetHaveWheelEventHandlers(true);
+ LayerImpl* root = root_layer();
+ LayerImpl* child = AddChild<LayerImpl>(root);
gfx::Transform identity;
- SetLayerPropertiesForTesting(root.get(), identity, gfx::Point3F(),
- gfx::PointF(), gfx::Size(100, 100), true, false);
- SetLayerPropertiesForTesting(child.get(), identity, gfx::Point3F(),
- gfx::PointF(), gfx::Size(100, 100), true, false);
+ SetLayerPropertiesForTesting(root, identity, gfx::Point3F(), gfx::PointF(),
+ gfx::Size(100, 100), true, false, true);
+ SetLayerPropertiesForTesting(child, identity, gfx::Point3F(), gfx::PointF(),
+ gfx::Size(100, 100), true, false, false);
- host()->SetRootLayer(root);
+ EXPECT_EQ(root->layer_or_descendant_has_input_handler(), false);
+
+ child->SetHaveWheelEventHandlers(true);
+ ExecuteCalculateDrawProperties(root);
+ EXPECT_EQ(root->layer_or_descendant_has_input_handler(), true);
- EXPECT_EQ(root->num_layer_or_descendants_with_input_handler(), 0);
- ExecuteCalculateDrawProperties(root.get());
- EXPECT_EQ(root->num_layer_or_descendants_with_input_handler(), 1);
child->SetHaveWheelEventHandlers(false);
- EXPECT_EQ(root->num_layer_or_descendants_with_input_handler(), 0);
+ ExecuteCalculateDrawProperties(root);
+ EXPECT_EQ(root->layer_or_descendant_has_input_handler(), false);
}
TEST_F(LayerTreeHostCommonTest, ResetPropertyTreeIndices) {
@@ -8466,5 +7666,302 @@ TEST_F(LayerTreeHostCommonTest, ResetLayerDrawPropertiestest) {
EXPECT_FALSE(child->sorted_for_recursion());
}
+TEST_F(LayerTreeHostCommonTest, RenderSurfaceClipsSubtree) {
+ // Ensure that a Clip Node is added when a render surface applies clip.
+ LayerImpl* root = root_layer();
+ LayerImpl* significant_transform = AddChildToRoot<LayerImpl>();
+ LayerImpl* layer_clips_subtree = AddChild<LayerImpl>(significant_transform);
+ LayerImpl* render_surface = AddChild<LayerImpl>(layer_clips_subtree);
+ LayerImpl* test_layer = AddChild<LayerImpl>(render_surface);
+
+ const gfx::Transform identity_matrix;
+ // This transform should be a significant one so that a transform node is
+ // formed for it.
+ gfx::Transform transform1;
+ transform1.RotateAboutYAxis(45);
+ transform1.RotateAboutXAxis(30);
+ // This transform should be a 3d transform as we want the render surface
+ // to flatten the transform
+ gfx::Transform transform2;
+ transform2.Translate3d(10, 10, 10);
+
+ layer_clips_subtree->SetMasksToBounds(true);
+ test_layer->SetDrawsContent(true);
+
+ SetLayerPropertiesForTesting(root, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(30, 30), true, false,
+ true);
+ SetLayerPropertiesForTesting(significant_transform, transform1,
+ gfx::Point3F(), gfx::PointF(), gfx::Size(30, 30),
+ true, false, false);
+ SetLayerPropertiesForTesting(layer_clips_subtree, identity_matrix,
+ gfx::Point3F(), gfx::PointF(), gfx::Size(30, 30),
+ true, false, false);
+ SetLayerPropertiesForTesting(render_surface, transform2, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(30, 30), true, false,
+ true);
+ SetLayerPropertiesForTesting(test_layer, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(30, 30), true, false,
+ false);
+
+ ExecuteCalculateDrawProperties(root);
+
+ TransformTree transform_tree =
+ root->layer_tree_impl()->property_trees()->transform_tree;
+ TransformNode* transform_node =
+ transform_tree.Node(significant_transform->transform_tree_index());
+ EXPECT_EQ(transform_node->owner_id, significant_transform->id());
+
+ ClipTree clip_tree = root->layer_tree_impl()->property_trees()->clip_tree;
+ ClipNode* clip_node = clip_tree.Node(render_surface->clip_tree_index());
+ EXPECT_TRUE(clip_node->data.use_only_parent_clip);
+ EXPECT_EQ(gfx::Rect(30, 21), test_layer->visible_rect_from_property_trees());
+}
+
+TEST_F(LayerTreeHostCommonTest, TransformOfParentClipNodeAncestorOfTarget) {
+ // Ensure that when parent clip node's transform is an ancestor of current
+ // clip node's target, clip is 'projected' from parent space to current
+ // target space and visible rects are calculated correctly.
+ LayerImpl* root = root_layer();
+ LayerImpl* clip_layer = AddChild<LayerImpl>(root);
+ LayerImpl* target_layer = AddChild<LayerImpl>(clip_layer);
+ LayerImpl* test_layer = AddChild<LayerImpl>(target_layer);
+
+ const gfx::Transform identity_matrix;
+ gfx::Transform transform;
+ transform.RotateAboutYAxis(45);
+ clip_layer->SetMasksToBounds(true);
+ target_layer->SetMasksToBounds(true);
+ test_layer->SetDrawsContent(true);
+
+ SetLayerPropertiesForTesting(root, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(30, 30), true, false,
+ true);
+ SetLayerPropertiesForTesting(clip_layer, transform, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(30, 30), true, false,
+ false);
+ SetLayerPropertiesForTesting(target_layer, transform, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(30, 30), true, false,
+ true);
+ SetLayerPropertiesForTesting(test_layer, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(30, 30), true, false,
+ false);
+ ExecuteCalculateDrawProperties(root);
+
+ EXPECT_EQ(gfx::Rect(30, 30), test_layer->visible_rect_from_property_trees());
+}
+
+TEST_F(LayerTreeHostCommonTest,
+ RenderSurfaceWithUnclippedDescendantsClipsSubtree) {
+ // Ensure clip rect is calculated correctly when render surface has unclipped
+ // descendants.
+ LayerImpl* root = root_layer();
+ LayerImpl* clip_parent = AddChildToRoot<LayerImpl>();
+ LayerImpl* between_clip_parent_and_child = AddChild<LayerImpl>(clip_parent);
+ LayerImpl* render_surface =
+ AddChild<LayerImpl>(between_clip_parent_and_child);
+ LayerImpl* test_layer = AddChild<LayerImpl>(render_surface);
+
+ const gfx::Transform identity_matrix;
+ gfx::Transform transform;
+ transform.Translate(2.0, 2.0);
+
+ test_layer->SetDrawsContent(true);
+ render_surface->SetClipParent(clip_parent);
+ scoped_ptr<std::set<LayerImpl*>> clip_children(new std::set<LayerImpl*>);
+ clip_children->insert(render_surface);
+ clip_parent->SetClipChildren(clip_children.release());
+ SetLayerPropertiesForTesting(root, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(30, 30), true, false,
+ true);
+ SetLayerPropertiesForTesting(clip_parent, transform, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(30, 30), true, false,
+ false);
+ SetLayerPropertiesForTesting(between_clip_parent_and_child, transform,
+ gfx::Point3F(), gfx::PointF(), gfx::Size(30, 30),
+ true, false, false);
+ SetLayerPropertiesForTesting(render_surface, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(30, 30), true, false,
+ true);
+ SetLayerPropertiesForTesting(test_layer, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(30, 30), true, false,
+ false);
+
+ ExecuteCalculateDrawProperties(root);
+
+ EXPECT_EQ(gfx::Rect(30, 30), test_layer->clip_rect());
+}
+
+TEST_F(LayerTreeHostCommonTest,
+ RenderSurfaceClipsSubtreeAndHasUnclippedDescendants) {
+ LayerImpl* root = root_layer();
+ LayerImpl* clip_parent = AddChildToRoot<LayerImpl>();
+ LayerImpl* render_surface = AddChild<LayerImpl>(clip_parent);
+ LayerImpl* test_layer1 = AddChild<LayerImpl>(render_surface);
+ LayerImpl* clip_child = AddChild<LayerImpl>(test_layer1);
+ LayerImpl* test_layer2 = AddChild<LayerImpl>(clip_child);
+
+ const gfx::Transform identity_matrix;
+ root->SetMasksToBounds(true);
+ render_surface->SetMasksToBounds(true);
+ render_surface->SetDrawsContent(true);
+ clip_child->SetDrawsContent(true);
+ test_layer1->SetDrawsContent(true);
+ test_layer2->SetDrawsContent(true);
+ clip_child->SetClipParent(clip_parent);
+ scoped_ptr<std::set<LayerImpl*>> clip_children(new std::set<LayerImpl*>);
+ clip_children->insert(clip_child);
+ clip_parent->SetClipChildren(clip_children.release());
+
+ SetLayerPropertiesForTesting(root, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(30, 30), true, false,
+ true);
+ SetLayerPropertiesForTesting(clip_parent, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(30, 30), true, false,
+ false);
+ SetLayerPropertiesForTesting(render_surface, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(50, 50), true, false,
+ true);
+ SetLayerPropertiesForTesting(test_layer1, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(50, 50), true, false,
+ false);
+ SetLayerPropertiesForTesting(clip_child, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(50, 50), true, false,
+ false);
+ SetLayerPropertiesForTesting(test_layer2, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(50, 50), true, false,
+ false);
+
+ ExecuteCalculateDrawProperties(root);
+ EXPECT_EQ(gfx::Rect(50, 50), render_surface->visible_layer_rect());
+ EXPECT_EQ(gfx::Rect(50, 50), test_layer1->visible_layer_rect());
+ EXPECT_EQ(gfx::Rect(30, 30), clip_child->visible_layer_rect());
+ EXPECT_EQ(gfx::Rect(30, 30), test_layer2->visible_layer_rect());
+}
+
+TEST_F(LayerTreeHostCommonTest, UnclippedClipParent) {
+ LayerImpl* root = root_layer();
+ LayerImpl* clip_parent = AddChildToRoot<LayerImpl>();
+ LayerImpl* render_surface = AddChild<LayerImpl>(clip_parent);
+ LayerImpl* clip_child = AddChild<LayerImpl>(render_surface);
+
+ const gfx::Transform identity_matrix;
+ clip_parent->SetDrawsContent(true);
+ render_surface->SetMasksToBounds(true);
+ render_surface->SetDrawsContent(true);
+ clip_child->SetDrawsContent(true);
+
+ clip_child->SetClipParent(clip_parent);
+ scoped_ptr<std::set<LayerImpl*>> clip_children(new std::set<LayerImpl*>);
+ clip_children->insert(clip_child);
+ clip_parent->SetClipChildren(clip_children.release());
+
+ SetLayerPropertiesForTesting(root, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(50, 50), true, false,
+ true);
+ SetLayerPropertiesForTesting(clip_parent, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(50, 50), true, false,
+ false);
+ SetLayerPropertiesForTesting(render_surface, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(30, 30), true, false,
+ true);
+ SetLayerPropertiesForTesting(clip_child, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(50, 50), true, false,
+ false);
+
+ ExecuteCalculateDrawProperties(root);
+
+ // The clip child should inherit its clip parent's clipping state, not its
+ // tree parent's clipping state.
+ EXPECT_FALSE(clip_parent->is_clipped());
+ EXPECT_TRUE(render_surface->is_clipped());
+ EXPECT_FALSE(clip_child->is_clipped());
+}
+
+TEST_F(LayerTreeHostCommonTest, LayerWithInputHandlerAndZeroOpacity) {
+ LayerImpl* root = root_layer();
+ LayerImpl* render_surface = AddChild<LayerImpl>(root);
+ LayerImpl* test_layer = AddChild<LayerImpl>(render_surface);
+
+ const gfx::Transform identity_matrix;
+ SetLayerPropertiesForTesting(root, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(30, 30), true, false,
+ true);
+ SetLayerPropertiesForTesting(render_surface, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(30, 30), true, false,
+ true);
+ SetLayerPropertiesForTesting(test_layer, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(20, 20), true, false,
+ false);
+
+ render_surface->SetMasksToBounds(true);
+ test_layer->SetDrawsContent(true);
+ test_layer->SetOpacity(0);
+ test_layer->SetHaveWheelEventHandlers(true);
+
+ ExecuteCalculateDrawProperties(root);
+ EXPECT_EQ(gfx::Rect(20, 20), test_layer->drawable_content_rect());
+ EXPECT_EQ(gfx::RectF(20, 20),
+ render_surface->render_surface()->DrawableContentRect());
+}
+
+TEST_F(LayerTreeHostCommonTest,
+ LayerClipRectLargerThanClippingRenderSurfaceRect) {
+ LayerImpl* root = root_layer();
+ LayerImpl* render_surface = AddChild<LayerImpl>(root);
+ LayerImpl* test_layer = AddChild<LayerImpl>(render_surface);
+ const gfx::Transform identity_matrix;
+ SetLayerPropertiesForTesting(root, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(30, 30), true, false,
+ true);
+ SetLayerPropertiesForTesting(render_surface, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(50, 50), true, false,
+ true);
+ SetLayerPropertiesForTesting(test_layer, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(50, 50), true, false,
+ false);
+ root->SetMasksToBounds(true);
+ render_surface->SetMasksToBounds(true);
+ test_layer->SetMasksToBounds(true);
+ test_layer->SetDrawsContent(true);
+ ExecuteCalculateDrawProperties(root);
+
+ EXPECT_EQ(gfx::Rect(30, 30), root->clip_rect());
+ EXPECT_EQ(gfx::Rect(50, 50), render_surface->clip_rect());
+ EXPECT_EQ(gfx::Rect(50, 50), test_layer->clip_rect());
+}
+
+TEST_F(LayerTreeHostCommonTest, TwoUnclippedRenderSurfaces) {
+ LayerImpl* root = root_layer();
+ LayerImpl* render_surface1 = AddChild<LayerImpl>(root);
+ LayerImpl* render_surface2 = AddChild<LayerImpl>(render_surface1);
+ LayerImpl* clip_child = AddChild<LayerImpl>(render_surface2);
+
+ const gfx::Transform identity_matrix;
+ clip_child->SetClipParent(root);
+ scoped_ptr<std::set<LayerImpl*>> clip_children(new std::set<LayerImpl*>);
+ clip_children->insert(clip_child);
+ root->SetClipChildren(clip_children.release());
+ root->SetMasksToBounds(true);
+ render_surface1->SetDrawsContent(true);
+ render_surface2->SetDrawsContent(true);
+
+ SetLayerPropertiesForTesting(root, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(30, 30), true, false,
+ true);
+ SetLayerPropertiesForTesting(render_surface1, identity_matrix, gfx::Point3F(),
+ gfx::PointF(10, 10), gfx::Size(30, 30), true,
+ false, true);
+ SetLayerPropertiesForTesting(render_surface2, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(30, 30), true, false,
+ true);
+ SetLayerPropertiesForTesting(clip_child, identity_matrix, gfx::Point3F(),
+ gfx::PointF(), gfx::Size(30, 30), true, false,
+ false);
+ ExecuteCalculateDrawProperties(root);
+
+ EXPECT_EQ(gfx::Rect(-10, -10, 30, 30), render_surface2->clip_rect());
+}
+
} // namespace
} // namespace cc
diff --git a/chromium/cc/trees/layer_tree_host_impl.cc b/chromium/cc/trees/layer_tree_host_impl.cc
index f122aeb58b9..ab75b9c0c11 100644
--- a/chromium/cc/trees/layer_tree_host_impl.cc
+++ b/chromium/cc/trees/layer_tree_host_impl.cc
@@ -23,17 +23,18 @@
#include "cc/animation/scroll_offset_animation_curve.h"
#include "cc/animation/scrollbar_animation_controller.h"
#include "cc/animation/timing_function.h"
+#include "cc/base/histograms.h"
#include "cc/base/math_util.h"
#include "cc/debug/benchmark_instrumentation.h"
#include "cc/debug/debug_rect_history.h"
#include "cc/debug/devtools_instrumentation.h"
#include "cc/debug/frame_rate_counter.h"
#include "cc/debug/frame_viewer_instrumentation.h"
-#include "cc/debug/paint_time_counter.h"
#include "cc/debug/rendering_stats_instrumentation.h"
#include "cc/debug/traced_value.h"
#include "cc/input/page_scale_animation.h"
#include "cc/input/scroll_elasticity_helper.h"
+#include "cc/input/scroll_state.h"
#include "cc/input/top_controls_manager.h"
#include "cc/layers/append_quads_data.h"
#include "cc/layers/heads_up_display_layer_impl.h"
@@ -57,7 +58,6 @@
#include "cc/raster/gpu_rasterizer.h"
#include "cc/raster/gpu_tile_task_worker_pool.h"
#include "cc/raster/one_copy_tile_task_worker_pool.h"
-#include "cc/raster/pixel_buffer_tile_task_worker_pool.h"
#include "cc/raster/tile_task_worker_pool.h"
#include "cc/raster/zero_copy_tile_task_worker_pool.h"
#include "cc/resources/memory_history.h"
@@ -129,34 +129,6 @@ void DidVisibilityChange(LayerTreeHostImpl* id, bool visible) {
TRACE_EVENT_ASYNC_END0("cc", "LayerTreeHostImpl::SetVisible", id);
}
-size_t GetMaxTransferBufferUsageBytes(
- const ContextProvider::Capabilities& context_capabilities,
- double refresh_rate) {
- // We want to make sure the default transfer buffer size is equal to the
- // amount of data that can be uploaded by the compositor to avoid stalling
- // the pipeline.
- // For reference Chromebook Pixel can upload 1MB in about 0.5ms.
- const size_t kMaxBytesUploadedPerMs = 1024 * 1024 * 2;
-
- // We need to upload at least enough work to keep the GPU process busy until
- // the next time it can handle a request to start more uploads from the
- // compositor. We assume that it will pick up any sent upload requests within
- // the time of a vsync, since the browser will want to swap a frame within
- // that time interval, and then uploads should have a chance to be processed.
- size_t ms_per_frame = std::floor(1000.0 / refresh_rate);
- size_t max_transfer_buffer_usage_bytes =
- ms_per_frame * kMaxBytesUploadedPerMs;
-
- // The context may request a lower limit based on the device capabilities.
- return std::min(context_capabilities.max_transfer_buffer_usage_bytes,
- max_transfer_buffer_usage_bytes);
-}
-
-size_t GetMaxStagingResourceCount() {
- // Upper bound for number of staging resource to allow.
- return 32;
-}
-
size_t GetDefaultMemoryAllocationLimit() {
// TODO(ccameron): (http://crbug.com/137094) This 64MB default is a straggler
// from the old texture manager and is just to give us a default memory
@@ -169,8 +141,8 @@ size_t GetDefaultMemoryAllocationLimit() {
} // namespace
-LayerTreeHostImpl::FrameData::FrameData() : has_no_damage(false) {
-}
+LayerTreeHostImpl::FrameData::FrameData()
+ : render_surface_layer_list(nullptr), has_no_damage(false) {}
LayerTreeHostImpl::FrameData::~FrameData() {}
@@ -200,6 +172,7 @@ LayerTreeHostImpl::LayerTreeHostImpl(
: client_(client),
proxy_(proxy),
current_begin_frame_tracker_(BEGINFRAMETRACKER_FROM_HERE),
+ output_surface_(nullptr),
content_is_suitable_for_gpu_rasterization_(true),
has_gpu_rasterization_trigger_(false),
use_gpu_rasterization_(false),
@@ -208,34 +181,32 @@ LayerTreeHostImpl::LayerTreeHostImpl(
tree_resources_for_gpu_rasterization_dirty_(false),
input_handler_client_(NULL),
did_lock_scrolling_layer_(false),
- should_bubble_scrolls_(false),
wheel_scrolling_(false),
scroll_affects_scroll_handler_(false),
scroll_layer_id_when_mouse_over_scrollbar_(0),
tile_priorities_dirty_(false),
- root_layer_scroll_offset_delegate_(NULL),
settings_(settings),
visible_(true),
cached_managed_memory_policy_(
GetDefaultMemoryAllocationLimit(),
gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING,
ManagedMemoryPolicy::kDefaultNumResourcesLimit),
- // Must be initialized after settings_ and proxy_.
+ is_synchronous_single_threaded_(!proxy->HasImplThread() &&
+ !settings.single_thread_proxy_scheduler),
+ // Must be initialized after is_synchronous_single_threaded_ and proxy_.
tile_manager_(
TileManager::Create(this,
GetTaskRunner(),
- IsSynchronousSingleThreaded()
+ is_synchronous_single_threaded_
? std::numeric_limits<size_t>::max()
: settings.scheduled_raster_task_limit)),
pinch_gesture_active_(false),
pinch_gesture_end_should_clear_scrolling_layer_(false),
fps_counter_(FrameRateCounter::Create(proxy_->HasImplThread())),
- paint_time_counter_(PaintTimeCounter::Create()),
memory_history_(MemoryHistory::Create()),
debug_rect_history_(DebugRectHistory::Create()),
texture_mailbox_deleter_(new TextureMailboxDeleter(GetTaskRunner())),
max_memory_needed_bytes_(0),
- device_scale_factor_(1.f),
resourceless_software_draw_(false),
animation_registrar_(),
rendering_stats_instrumentation_(rendering_stats_instrumentation),
@@ -261,8 +232,6 @@ LayerTreeHostImpl::LayerTreeHostImpl(
}
DCHECK(proxy_->IsImplThread());
- DCHECK_IMPLIES(settings.use_one_copy, !settings.use_zero_copy);
- DCHECK_IMPLIES(settings.use_zero_copy, !settings.use_one_copy);
DidVisibilityChange(this, visible_);
SetDebugState(settings.initial_debug_state);
@@ -314,6 +283,13 @@ LayerTreeHostImpl::~LayerTreeHostImpl() {
}
CleanUpTileManager();
+ renderer_ = nullptr;
+ resource_provider_ = nullptr;
+
+ if (output_surface_) {
+ output_surface_->DetachFromClient();
+ output_surface_ = nullptr;
+ }
}
void LayerTreeHostImpl::BeginMainFrameAborted(CommitEarlyOutReason reason) {
@@ -343,6 +319,19 @@ void LayerTreeHostImpl::BeginCommit() {
void LayerTreeHostImpl::CommitComplete() {
TRACE_EVENT0("cc", "LayerTreeHostImpl::CommitComplete");
+ if (proxy_->CommitToActiveTree()) {
+ // We have to activate animations here or "IsActive()" is true on the layers
+ // but the animations aren't activated yet so they get ignored by
+ // UpdateDrawProperties.
+ ActivateAnimations();
+ }
+
+ // Start animations before UpdateDrawProperties and PrepareTiles, as they can
+ // change the results. When doing commit to the active tree, this must happen
+ // after ActivateAnimations() in order for this ticking to be propogated to
+ // layers on the active tree.
+ Animate();
+
// LayerTreeHost may have changed the GPU rasterization flags state, which
// may require an update of the tree resources.
UpdateTreeResourcesForGpuRasterizationIfNeeded();
@@ -418,20 +407,32 @@ bool LayerTreeHostImpl::CanDraw() const {
return true;
}
-void LayerTreeHostImpl::Animate(base::TimeTicks monotonic_time) {
+void LayerTreeHostImpl::Animate() {
+ DCHECK(proxy_->IsImplThread());
+ base::TimeTicks monotonic_time = CurrentBeginFrameArgs().frame_time;
+
// mithro(TODO): Enable these checks.
// DCHECK(!current_begin_frame_tracker_.HasFinished());
// DCHECK(monotonic_time == current_begin_frame_tracker_.Current().frame_time)
// << "Called animate with unknown frame time!?";
- if (!root_layer_scroll_offset_delegate_ ||
- (CurrentlyScrollingLayer() != InnerViewportScrollLayer() &&
- CurrentlyScrollingLayer() != OuterViewportScrollLayer())) {
- AnimateInput(monotonic_time);
+
+ if (input_handler_client_) {
+ // This animates fling scrolls. But on Android WebView root flings are
+ // controlled by the application, so the compositor does not animate them.
+ bool ignore_fling =
+ settings_.ignore_root_layer_flings && IsCurrentlyScrollingRoot();
+ if (!ignore_fling)
+ input_handler_client_->Animate(monotonic_time);
}
+
AnimatePageScale(monotonic_time);
AnimateLayers(monotonic_time);
AnimateScrollbars(monotonic_time);
AnimateTopControls(monotonic_time);
+
+ // Animating stuff can change the root scroll offset, so inform the
+ // synchronous input handler.
+ UpdateRootLayerStateForSynchronousInputHandler();
}
bool LayerTreeHostImpl::PrepareTiles() {
@@ -457,7 +458,7 @@ void LayerTreeHostImpl::StartPageScaleAnimation(
gfx::ScrollOffset scroll_total = active_tree_->TotalScrollOffset();
gfx::SizeF scaled_scrollable_size = active_tree_->ScrollableSize();
gfx::SizeF viewport_size =
- active_tree_->InnerViewportContainerLayer()->bounds();
+ gfx::SizeF(active_tree_->InnerViewportContainerLayer()->bounds());
// Easing constants experimentally determined.
scoped_ptr<TimingFunction> timing_function =
@@ -487,48 +488,46 @@ void LayerTreeHostImpl::StartPageScaleAnimation(
}
void LayerTreeHostImpl::SetNeedsAnimateInput() {
- if (root_layer_scroll_offset_delegate_ &&
- (CurrentlyScrollingLayer() == InnerViewportScrollLayer() ||
- CurrentlyScrollingLayer() == OuterViewportScrollLayer())) {
- if (root_layer_animation_callback_.is_null()) {
- root_layer_animation_callback_ =
- base::Bind(&LayerTreeHostImpl::AnimateInput, AsWeakPtr());
- }
- root_layer_scroll_offset_delegate_->SetNeedsAnimate(
- root_layer_animation_callback_);
- return;
- }
-
+ DCHECK_IMPLIES(IsCurrentlyScrollingRoot(),
+ !settings_.ignore_root_layer_flings);
SetNeedsAnimate();
}
+bool LayerTreeHostImpl::IsCurrentlyScrollingRoot() const {
+ LayerImpl* scrolling_layer = CurrentlyScrollingLayer();
+ if (!scrolling_layer)
+ return false;
+ return scrolling_layer == InnerViewportScrollLayer();
+}
+
bool LayerTreeHostImpl::IsCurrentlyScrollingLayerAt(
const gfx::Point& viewport_point,
- InputHandler::ScrollInputType type) {
- if (!CurrentlyScrollingLayer())
+ InputHandler::ScrollInputType type) const {
+ LayerImpl* scrolling_layer_impl = CurrentlyScrollingLayer();
+ if (!scrolling_layer_impl)
return false;
gfx::PointF device_viewport_point =
- gfx::ScalePoint(viewport_point, device_scale_factor_);
+ gfx::ScalePoint(viewport_point, active_tree_->device_scale_factor());
LayerImpl* layer_impl =
active_tree_->FindLayerThatIsHitByPoint(device_viewport_point);
bool scroll_on_main_thread = false;
- LayerImpl* scrolling_layer_impl = FindScrollLayerForDeviceViewportPoint(
+ LayerImpl* test_layer_impl = FindScrollLayerForDeviceViewportPoint(
device_viewport_point, type, layer_impl, &scroll_on_main_thread, NULL);
- if (!scrolling_layer_impl)
+ if (!test_layer_impl)
return false;
- if (CurrentlyScrollingLayer() == scrolling_layer_impl)
+ if (scrolling_layer_impl == test_layer_impl)
return true;
// For active scrolling state treat the inner/outer viewports interchangeably.
- if ((CurrentlyScrollingLayer() == InnerViewportScrollLayer() &&
- scrolling_layer_impl == OuterViewportScrollLayer()) ||
- (CurrentlyScrollingLayer() == OuterViewportScrollLayer() &&
- scrolling_layer_impl == InnerViewportScrollLayer())) {
+ if ((scrolling_layer_impl == InnerViewportScrollLayer() &&
+ test_layer_impl == OuterViewportScrollLayer()) ||
+ (scrolling_layer_impl == OuterViewportScrollLayer() &&
+ test_layer_impl == InnerViewportScrollLayer())) {
return true;
}
@@ -538,7 +537,7 @@ bool LayerTreeHostImpl::IsCurrentlyScrollingLayerAt(
bool LayerTreeHostImpl::HaveWheelEventHandlersAt(
const gfx::Point& viewport_point) {
gfx::PointF device_viewport_point =
- gfx::ScalePoint(viewport_point, device_scale_factor_);
+ gfx::ScalePoint(viewport_point, active_tree_->device_scale_factor());
LayerImpl* layer_impl =
active_tree_->FindLayerWithWheelHandlerThatIsHitByPoint(
@@ -547,15 +546,16 @@ bool LayerTreeHostImpl::HaveWheelEventHandlersAt(
return layer_impl != NULL;
}
-static LayerImpl* NextScrollLayer(LayerImpl* layer) {
- if (LayerImpl* scroll_parent = layer->scroll_parent())
- return scroll_parent;
+static LayerImpl* NextLayerInScrollOrder(LayerImpl* layer) {
+ if (layer->scroll_parent())
+ return layer->scroll_parent();
+
return layer->parent();
}
static ScrollBlocksOn EffectiveScrollBlocksOn(LayerImpl* layer) {
ScrollBlocksOn blocks = SCROLL_BLOCKS_ON_NONE;
- for (; layer; layer = NextScrollLayer(layer)) {
+ for (; layer; layer = NextLayerInScrollOrder(layer)) {
blocks |= layer->scroll_blocks_on();
}
return blocks;
@@ -564,7 +564,7 @@ static ScrollBlocksOn EffectiveScrollBlocksOn(LayerImpl* layer) {
bool LayerTreeHostImpl::DoTouchEventsBlockScrollAt(
const gfx::Point& viewport_point) {
gfx::PointF device_viewport_point =
- gfx::ScalePoint(viewport_point, device_scale_factor_);
+ gfx::ScalePoint(viewport_point, active_tree_->device_scale_factor());
// First check if scrolling at this point is required to block on any
// touch event handlers. Note that we must start at the innermost layer
@@ -816,6 +816,16 @@ DrawResult LayerTreeHostImpl::CalculateRenderPasses(
root_pass->damage_rect = root_pass->output_rect;
}
+ // Because the active tree could be drawn again if this fails for some reason,
+ // clear all of the copy request flags so that sanity checks for the counts
+ // succeed.
+ if (!active_tree_->LayersWithCopyOutputRequest().empty()) {
+ LayerTreeHostCommon::CallFunctionForSubtree(
+ active_tree_->root_layer(), [](LayerImpl* layer) {
+ layer->set_num_layer_or_descendant_with_copy_request(0);
+ });
+ }
+
// Grab this region here before iterating layers. Taking copy requests from
// the layers while constructing the render passes will dirty the render
// surface layer list and this unoccluded region, flipping the dirty bit to
@@ -919,8 +929,7 @@ DrawResult LayerTreeHostImpl::CalculateRenderPasses(
if (append_quads_data.num_missing_tiles) {
bool layer_has_animating_transform =
- it->screen_space_transform_is_animating() ||
- it->draw_transform_is_animating();
+ it->screen_space_transform_is_animating();
if (layer_has_animating_transform)
have_missing_animated_tiles = true;
}
@@ -1036,13 +1045,18 @@ DrawResult LayerTreeHostImpl::PrepareToDraw(FrameData* frame) {
"Compositing.NumActiveLayers",
base::saturated_cast<int>(active_tree_->NumLayers()), 1, 400, 20);
- size_t total_picture_memory = 0;
- for (const PictureLayerImpl* layer : active_tree()->picture_layers())
- total_picture_memory += layer->GetRasterSource()->GetPictureMemoryUsage();
- if (total_picture_memory != 0) {
- UMA_HISTOGRAM_COUNTS(
- "Compositing.PictureMemoryUsageKb",
- base::saturated_cast<int>(total_picture_memory / 1024));
+ if (const char* client_name = GetClientNameForMetrics()) {
+ size_t total_picture_memory = 0;
+ for (const PictureLayerImpl* layer : active_tree()->picture_layers())
+ total_picture_memory += layer->GetRasterSource()->GetPictureMemoryUsage();
+ if (total_picture_memory != 0) {
+ // GetClientNameForMetrics only returns one non-null value over the
+ // lifetime of the process, so this histogram name is runtime constant.
+ UMA_HISTOGRAM_COUNTS(
+ base::StringPrintf("Compositing.%s.PictureMemoryUsageKb",
+ client_name),
+ base::saturated_cast<int>(total_picture_memory / 1024));
+ }
}
bool update_lcd_text = false;
@@ -1096,28 +1110,20 @@ void LayerTreeHostImpl::RemoveRenderPasses(FrameData* frame) {
RenderPass* pass = frame->render_passes[i];
// Remove orphan RenderPassDrawQuads.
- bool removed = true;
- while (removed) {
- removed = false;
- for (auto it = pass->quad_list.begin(); it != pass->quad_list.end();
- ++it) {
- if (it->material != DrawQuad::RENDER_PASS)
- continue;
- const RenderPassDrawQuad* quad = RenderPassDrawQuad::MaterialCast(*it);
- // If the RenderPass doesn't exist, we can remove the quad.
- if (pass_exists.count(quad->render_pass_id)) {
- // Otherwise, save a reference to the RenderPass so we know there's a
- // quad using it.
- pass_references[quad->render_pass_id]++;
- continue;
- }
- // This invalidates the iterator. So break out of the loop and look
- // again. Luckily there's not a lot of render passes cuz this is
- // terrible.
- // TODO(danakj): We could make erase not invalidate the iterator.
- pass->quad_list.EraseAndInvalidateAllPointers(it);
- removed = true;
- break;
+ for (auto it = pass->quad_list.begin(); it != pass->quad_list.end();) {
+ if (it->material != DrawQuad::RENDER_PASS) {
+ ++it;
+ continue;
+ }
+ const RenderPassDrawQuad* quad = RenderPassDrawQuad::MaterialCast(*it);
+ // If the RenderPass doesn't exist, we can remove the quad.
+ if (pass_exists.count(quad->render_pass_id)) {
+ // Otherwise, save a reference to the RenderPass so we know there's a
+ // quad using it.
+ pass_references[quad->render_pass_id]++;
+ ++it;
+ } else {
+ it = pass->quad_list.EraseAndInvalidateAllPointers(it);
}
}
@@ -1223,33 +1229,14 @@ void LayerTreeHostImpl::UpdateTileManagerMemoryPolicy(
false /* aggressively_free_resources */);
}
- // TODO(reveman): We should avoid keeping around unused resources if
- // possible. crbug.com/224475
- // Unused limit is calculated from soft-limit, as hard-limit may
- // be very high and shouldn't typically be exceeded.
- size_t unused_memory_limit_in_bytes = static_cast<size_t>(
- (static_cast<int64>(global_tile_state_.soft_memory_limit_in_bytes) *
- settings_.max_unused_resource_memory_percentage) /
- 100);
-
DCHECK(resource_pool_);
- resource_pool_->CheckBusyResources(false);
+ resource_pool_->CheckBusyResources();
// Soft limit is used for resource pool such that memory returns to soft
// limit after going over.
resource_pool_->SetResourceUsageLimits(
global_tile_state_.soft_memory_limit_in_bytes,
- unused_memory_limit_in_bytes,
global_tile_state_.num_resources_limit);
- // Release all staging resources when invisible.
- if (staging_resource_pool_) {
- staging_resource_pool_->CheckBusyResources(false);
- staging_resource_pool_->SetResourceUsageLimits(
- std::numeric_limits<size_t>::max(),
- std::numeric_limits<size_t>::max(),
- visible_ ? GetMaxStagingResourceCount() : 0);
- }
-
DidModifyTilePriorities();
}
@@ -1419,8 +1406,8 @@ void LayerTreeHostImpl::SetExternalDrawConstraints(
if (transform_for_tile_priority.GetInverse(&screen_to_view)) {
// Convert from screen space to view space.
viewport_rect_for_tile_priority_in_view_space =
- gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
- screen_to_view, viewport_rect_for_tile_priority));
+ MathUtil::ProjectEnclosingClippedRect(
+ screen_to_view, viewport_rect_for_tile_priority);
}
}
@@ -1463,7 +1450,7 @@ void LayerTreeHostImpl::ReclaimResources(const CompositorFrameAck* ack) {
// In OOM, we now might be able to release more resources that were held
// because they were exported.
if (resource_pool_) {
- resource_pool_->CheckBusyResources(false);
+ resource_pool_->CheckBusyResources();
resource_pool_->ReduceResourceUsage();
}
// If we're not visible, we likely released resources, so we want to
@@ -1484,7 +1471,7 @@ void LayerTreeHostImpl::OnCanDrawStateChangedForTree() {
CompositorFrameMetadata LayerTreeHostImpl::MakeCompositorFrameMetadata() const {
CompositorFrameMetadata metadata;
- metadata.device_scale_factor = device_scale_factor_;
+ metadata.device_scale_factor = active_tree_->device_scale_factor();
metadata.page_scale_factor = active_tree_->current_page_scale_factor();
metadata.scrollable_viewport_size = active_tree_->ScrollableViewportSize();
metadata.root_layer_size = active_tree_->ScrollableSize();
@@ -1494,22 +1481,25 @@ CompositorFrameMetadata LayerTreeHostImpl::MakeCompositorFrameMetadata() const {
gfx::Vector2dF(0.f, top_controls_manager_->ControlsTopOffset());
metadata.location_bar_content_translation =
gfx::Vector2dF(0.f, top_controls_manager_->ContentTopOffset());
+ metadata.root_background_color = active_tree_->background_color();
active_tree_->GetViewportSelection(&metadata.selection);
- LayerImpl* root_layer_for_overflow = OuterViewportScrollLayer()
- ? OuterViewportScrollLayer()
- : InnerViewportScrollLayer();
- if (root_layer_for_overflow) {
+ if (OuterViewportScrollLayer()) {
metadata.root_overflow_x_hidden =
- !root_layer_for_overflow->user_scrollable_horizontal();
+ !OuterViewportScrollLayer()->user_scrollable_horizontal();
metadata.root_overflow_y_hidden =
- !root_layer_for_overflow->user_scrollable_vertical();
+ !OuterViewportScrollLayer()->user_scrollable_vertical();
}
if (!InnerViewportScrollLayer())
return metadata;
+ metadata.root_overflow_x_hidden |=
+ !InnerViewportScrollLayer()->user_scrollable_horizontal();
+ metadata.root_overflow_y_hidden |=
+ !InnerViewportScrollLayer()->user_scrollable_vertical();
+
// TODO(miletus) : Change the metadata to hold ScrollOffset.
metadata.root_scroll_offset = gfx::ScrollOffsetToVector2dF(
active_tree_->TotalScrollOffset());
@@ -1590,18 +1580,14 @@ void LayerTreeHostImpl::DrawLayers(FrameData* frame) {
scoped_ptr<SoftwareRenderer> temp_software_renderer =
SoftwareRenderer::Create(this, &settings_.renderer_settings,
- output_surface_.get(), NULL);
- temp_software_renderer->DrawFrame(&frame->render_passes,
- device_scale_factor_,
- DeviceViewport(),
- DeviceClip(),
- disable_picture_quad_image_filtering);
+ output_surface_, NULL);
+ temp_software_renderer->DrawFrame(
+ &frame->render_passes, active_tree_->device_scale_factor(),
+ DeviceViewport(), DeviceClip(), disable_picture_quad_image_filtering);
} else {
renderer_->DrawFrame(&frame->render_passes,
- device_scale_factor_,
- DeviceViewport(),
- DeviceClip(),
- false);
+ active_tree_->device_scale_factor(), DeviceViewport(),
+ DeviceClip(), false);
}
// The render passes should be consumed by the renderer.
DCHECK(frame->render_passes.empty());
@@ -1637,6 +1623,18 @@ void LayerTreeHostImpl::FinishAllRendering() {
renderer_->Finish();
}
+int LayerTreeHostImpl::RequestedMSAASampleCount() const {
+ if (settings_.gpu_rasterization_msaa_sample_count == -1) {
+ // Use the most up-to-date version of device_scale_factor that we have.
+ float device_scale_factor = pending_tree_
+ ? pending_tree_->device_scale_factor()
+ : active_tree_->device_scale_factor();
+ return device_scale_factor >= 2.0f ? 4 : 8;
+ }
+
+ return settings_.gpu_rasterization_msaa_sample_count;
+}
+
bool LayerTreeHostImpl::CanUseGpuRasterization() {
if (!(output_surface_ && output_surface_->context_provider() &&
output_surface_->worker_context_provider()))
@@ -1644,7 +1642,7 @@ bool LayerTreeHostImpl::CanUseGpuRasterization() {
ContextProvider* context_provider =
output_surface_->worker_context_provider();
- base::AutoLock context_lock(*context_provider->GetLock());
+ ContextProvider::ScopedContextLock scoped_context(context_provider);
if (!context_provider->GrContext())
return false;
@@ -1655,9 +1653,8 @@ void LayerTreeHostImpl::UpdateGpuRasterizationStatus() {
bool use_gpu = false;
bool use_msaa = false;
bool using_msaa_for_complex_content =
- renderer() && settings_.gpu_rasterization_msaa_sample_count > 0 &&
- GetRendererCapabilities().max_msaa_samples >=
- settings_.gpu_rasterization_msaa_sample_count;
+ renderer() && RequestedMSAASampleCount() > 0 &&
+ GetRendererCapabilities().max_msaa_samples >= RequestedMSAASampleCount();
if (settings_.gpu_rasterization_forced) {
use_gpu = true;
gpu_rasterization_status_ = GpuRasterizationStatus::ON_FORCED;
@@ -1740,11 +1737,11 @@ bool LayerTreeHostImpl::SwapBuffers(const LayerTreeHostImpl::FrameData& frame) {
CompositorFrameMetadata metadata = MakeCompositorFrameMetadata();
active_tree()->FinishSwapPromises(&metadata);
for (auto& latency : metadata.latency_info) {
- TRACE_EVENT_FLOW_STEP0(
- "input,benchmark",
- "LatencyInfo.Flow",
- TRACE_ID_DONT_MANGLE(latency.trace_id),
- "SwapBuffers");
+ TRACE_EVENT_WITH_FLOW1("input,benchmark",
+ "LatencyInfo.Flow",
+ TRACE_ID_DONT_MANGLE(latency.trace_id()),
+ TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
+ "step", "SwapBuffers");
// Only add the latency component once for renderer swap, not the browser
// swap.
if (!latency.FindLatency(ui::INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT,
@@ -1782,54 +1779,36 @@ void LayerTreeHostImpl::UpdateViewportContainerSizes() {
if (!inner_container)
return;
- // TODO(bokan): This code is currently specific to top controls. It should be
- // made general. crbug.com/464814.
- if (!TopControlsHeight()) {
- inner_container->SetBoundsDelta(gfx::Vector2dF());
- active_tree_->InnerViewportScrollLayer()->SetBoundsDelta(gfx::Vector2dF());
-
- if (outer_container) {
- outer_container->SetBoundsDelta(gfx::Vector2dF());
- ViewportAnchor anchor(InnerViewportScrollLayer(),
- OuterViewportScrollLayer());
- anchor.ResetViewportToAnchoredPosition();
- }
-
- return;
- }
-
ViewportAnchor anchor(InnerViewportScrollLayer(),
OuterViewportScrollLayer());
- // Adjust the inner viewport by shrinking/expanding the container to account
- // for the change in top controls height since the last Resize from Blink.
float top_controls_layout_height =
active_tree_->top_controls_shrink_blink_size()
? active_tree_->top_controls_height()
: 0.f;
- inner_container->SetBoundsDelta(gfx::Vector2dF(
- 0,
- top_controls_layout_height - top_controls_manager_->ContentTopOffset()));
-
- if (!outer_container || outer_container->BoundsForScrolling().IsEmpty())
- return;
+ float delta_from_top_controls =
+ top_controls_layout_height - top_controls_manager_->ContentTopOffset();
- // Adjust the outer viewport container as well, since adjusting only the
- // inner may cause its bounds to exceed those of the outer, causing scroll
- // clamping. We adjust it so it maintains the same aspect ratio as the
- // inner viewport.
- float aspect_ratio = inner_container->BoundsForScrolling().width() /
- inner_container->BoundsForScrolling().height();
- float target_height = outer_container->BoundsForScrolling().width() /
- aspect_ratio;
- float current_outer_height = outer_container->BoundsForScrolling().height() -
- outer_container->bounds_delta().y();
- gfx::Vector2dF delta(0, target_height - current_outer_height);
+ // Adjust the viewport layers by shrinking/expanding the container to account
+ // for changes in the size (e.g. top controls) since the last resize from
+ // Blink.
+ gfx::Vector2dF amount_to_expand(
+ 0.f,
+ delta_from_top_controls);
+ inner_container->SetBoundsDelta(amount_to_expand);
- outer_container->SetBoundsDelta(delta);
- active_tree_->InnerViewportScrollLayer()->SetBoundsDelta(delta);
+ if (outer_container && !outer_container->BoundsForScrolling().IsEmpty()) {
+ // Adjust the outer viewport container as well, since adjusting only the
+ // inner may cause its bounds to exceed those of the outer, causing scroll
+ // clamping.
+ gfx::Vector2dF amount_to_expand_scaled = gfx::ScaleVector2d(
+ amount_to_expand, 1.f / active_tree_->min_page_scale_factor());
+ outer_container->SetBoundsDelta(amount_to_expand_scaled);
+ active_tree_->InnerViewportScrollLayer()->SetBoundsDelta(
+ amount_to_expand_scaled);
- anchor.ResetViewportToAnchoredPosition();
+ anchor.ResetViewportToAnchoredPosition();
+ }
}
void LayerTreeHostImpl::SynchronouslyInitializeAllTiles() {
@@ -1867,12 +1846,11 @@ LayerImpl* LayerTreeHostImpl::CurrentlyScrollingLayer() const {
bool LayerTreeHostImpl::IsActivelyScrolling() const {
if (!CurrentlyScrollingLayer())
return false;
- if (root_layer_scroll_offset_delegate_ &&
- (CurrentlyScrollingLayer() == InnerViewportScrollLayer() ||
- CurrentlyScrollingLayer() == OuterViewportScrollLayer())) {
- // ScrollDelegate cannot determine current scroll, so assume no.
+ // On Android WebView root flings are controlled by the application,
+ // so the compositor does not animate them and can't tell if they
+ // are actually animating. So assume there are none.
+ if (settings_.ignore_root_layer_flings && IsCurrentlyScrollingRoot())
return false;
- }
return did_lock_scrolling_layer_;
}
@@ -1912,8 +1890,6 @@ void LayerTreeHostImpl::ActivateSyncTree() {
if (pending_tree_) {
TRACE_EVENT_ASYNC_END0("cc", "PendingTree:waiting", pending_tree_.get());
- active_tree_->SetRootLayerScrollOffsetDelegate(NULL);
- active_tree_->PushPersistedState(pending_tree_.get());
// Process any requests in the UI resource queue. The request queue is
// given in LayerTreeHost::FinishCommitOnImplThread. This must take place
// before the swap.
@@ -1937,8 +1913,9 @@ void LayerTreeHostImpl::ActivateSyncTree() {
UpdateViewportContainerSizes();
- active_tree_->SetRootLayerScrollOffsetDelegate(
- root_layer_scroll_offset_delegate_);
+ // If we commit to the active tree directly, this is already done during
+ // commit.
+ ActivateAnimations();
} else {
active_tree_->ProcessUIResourceRequestQueue();
}
@@ -1947,7 +1924,6 @@ void LayerTreeHostImpl::ActivateSyncTree() {
// won't already account for current bounds_delta values.
active_tree_->UpdatePropertyTreesForBoundsDelta();
active_tree_->DidBecomeActive();
- ActivateAnimations();
client_->RenewTreePriority();
// If we have any picture layers, then by activating we also modified tile
// priorities.
@@ -1959,16 +1935,6 @@ void LayerTreeHostImpl::ActivateSyncTree() {
if (!tree_activation_callback_.is_null())
tree_activation_callback_.Run();
- if (debug_state_.continuous_painting) {
- const RenderingStats& stats =
- rendering_stats_instrumentation_->GetRenderingStats();
- // TODO(hendrikw): This requires a different metric when we commit directly
- // to the active tree. See crbug.com/429311.
- paint_time_counter_->SavePaintTime(
- stats.commit_to_activate_duration.GetLastTimeDelta() +
- stats.draw_duration.GetLastTimeDelta());
- }
-
scoped_ptr<PendingPageScaleAnimation> pending_page_scale_animation =
active_tree_->TakePendingPageScaleAnimation();
if (pending_page_scale_animation) {
@@ -1978,6 +1944,9 @@ void LayerTreeHostImpl::ActivateSyncTree() {
pending_page_scale_animation->scale,
pending_page_scale_animation->duration);
}
+ // Activation can change the root scroll offset, so inform the synchronous
+ // input handler.
+ UpdateRootLayerStateForSynchronousInputHandler();
}
void LayerTreeHostImpl::SetVisible(bool visible) {
@@ -1996,11 +1965,9 @@ void LayerTreeHostImpl::SetVisible(bool visible) {
else
EvictAllUIResources();
- // Call PrepareTiles unconditionally on visibility change since this tab may
- // never get another draw or timer tick. When becoming visible we care about
- // unblocking the scheduler which might be waiting for activation / ready to
- // draw. When becoming invisible we care about evicting tiles immediately.
- PrepareTiles();
+ // Call PrepareTiles to evict tiles when we become invisible.
+ if (!visible)
+ PrepareTiles();
if (!renderer_)
return;
@@ -2058,18 +2025,18 @@ void LayerTreeHostImpl::CreateAndSetRenderer() {
DCHECK(resource_provider_);
if (output_surface_->capabilities().delegated_rendering) {
- renderer_ = DelegatingRenderer::Create(this, &settings_.renderer_settings,
- output_surface_.get(),
- resource_provider_.get());
+ renderer_ =
+ DelegatingRenderer::Create(this, &settings_.renderer_settings,
+ output_surface_, resource_provider_.get());
} else if (output_surface_->context_provider()) {
renderer_ = GLRenderer::Create(
- this, &settings_.renderer_settings, output_surface_.get(),
+ this, &settings_.renderer_settings, output_surface_,
resource_provider_.get(), texture_mailbox_deleter_.get(),
settings_.renderer_settings.highp_threshold_min);
} else if (output_surface_->software_device()) {
- renderer_ = SoftwareRenderer::Create(this, &settings_.renderer_settings,
- output_surface_.get(),
- resource_provider_.get());
+ renderer_ =
+ SoftwareRenderer::Create(this, &settings_.renderer_settings,
+ output_surface_, resource_provider_.get());
}
DCHECK(renderer_);
@@ -2086,25 +2053,27 @@ void LayerTreeHostImpl::CreateAndSetRenderer() {
}
void LayerTreeHostImpl::CreateTileManagerResources() {
- CreateResourceAndTileTaskWorkerPool(&tile_task_worker_pool_, &resource_pool_,
- &staging_resource_pool_);
+ CreateResourceAndTileTaskWorkerPool(&tile_task_worker_pool_, &resource_pool_);
+ // TODO(vmpstr): Initialize tile task limit at ctor time.
tile_manager_->SetResources(
resource_pool_.get(), tile_task_worker_pool_->AsTileTaskRunner(),
- IsSynchronousSingleThreaded() ? std::numeric_limits<size_t>::max()
- : settings_.scheduled_raster_task_limit);
+ is_synchronous_single_threaded_ ? std::numeric_limits<size_t>::max()
+ : settings_.scheduled_raster_task_limit);
UpdateTileManagerMemoryPolicy(ActualManagedMemoryPolicy());
}
void LayerTreeHostImpl::CreateResourceAndTileTaskWorkerPool(
scoped_ptr<TileTaskWorkerPool>* tile_task_worker_pool,
- scoped_ptr<ResourcePool>* resource_pool,
- scoped_ptr<ResourcePool>* staging_resource_pool) {
+ scoped_ptr<ResourcePool>* resource_pool) {
DCHECK(GetTaskRunner());
+ // TODO(vmpstr): Make this a DCHECK (or remove) when crbug.com/419086 is
+ // resolved.
+ CHECK(resource_provider_);
// Pass the single-threaded synchronous task graph runner to the worker pool
// if we're in synchronous single-threaded mode.
TaskGraphRunner* task_graph_runner = task_graph_runner_;
- if (IsSynchronousSingleThreaded()) {
+ if (is_synchronous_single_threaded_) {
DCHECK(!single_thread_synchronous_task_graph_runner_);
single_thread_synchronous_task_graph_runner_.reset(new TaskGraphRunner);
task_graph_runner = single_thread_synchronous_task_graph_runner_.get();
@@ -2112,8 +2081,8 @@ void LayerTreeHostImpl::CreateResourceAndTileTaskWorkerPool(
ContextProvider* context_provider = output_surface_->context_provider();
if (!context_provider) {
- *resource_pool =
- ResourcePool::Create(resource_provider_.get(), GL_TEXTURE_2D);
+ *resource_pool = ResourcePool::Create(resource_provider_.get(),
+ GetTaskRunner(), GL_TEXTURE_2D);
*tile_task_worker_pool = BitmapTileTaskWorkerPool::Create(
GetTaskRunner(), task_graph_runner, resource_provider_.get());
@@ -2121,11 +2090,12 @@ void LayerTreeHostImpl::CreateResourceAndTileTaskWorkerPool(
}
if (use_gpu_rasterization_) {
- *resource_pool =
- ResourcePool::Create(resource_provider_.get(), GL_TEXTURE_2D);
+ DCHECK(resource_provider_->output_surface()->worker_context_provider());
+
+ *resource_pool = ResourcePool::Create(resource_provider_.get(),
+ GetTaskRunner(), GL_TEXTURE_2D);
- int msaa_sample_count =
- use_msaa_ ? settings_.gpu_rasterization_msaa_sample_count : 0;
+ int msaa_sample_count = use_msaa_ ? RequestedMSAASampleCount() : 0;
*tile_task_worker_pool = GpuTileTaskWorkerPool::Create(
GetTaskRunner(), task_graph_runner, context_provider,
@@ -2135,59 +2105,38 @@ void LayerTreeHostImpl::CreateResourceAndTileTaskWorkerPool(
}
DCHECK(GetRendererCapabilities().using_image);
- unsigned image_target = settings_.use_image_texture_target;
- DCHECK_IMPLIES(image_target == GL_TEXTURE_RECTANGLE_ARB,
- context_provider->ContextCapabilities().gpu.texture_rectangle);
- DCHECK_IMPLIES(
- image_target == GL_TEXTURE_EXTERNAL_OES,
- context_provider->ContextCapabilities().gpu.egl_image_external);
-
- if (settings_.use_zero_copy) {
- *resource_pool =
- ResourcePool::Create(resource_provider_.get(), image_target);
- *tile_task_worker_pool = ZeroCopyTileTaskWorkerPool::Create(
- GetTaskRunner(), task_graph_runner, resource_provider_.get());
- return;
+ bool use_zero_copy = settings_.use_zero_copy;
+ // TODO(reveman): Remove this when mojo supports worker contexts.
+ // crbug.com/522440
+ if (!resource_provider_->output_surface()->worker_context_provider()) {
+ LOG(ERROR)
+ << "Forcing zero-copy tile initialization as worker context is missing";
+ use_zero_copy = true;
}
- if (settings_.use_one_copy) {
- // Synchronous single-threaded mode depends on tiles being ready to
- // draw when raster is complete. Therefore, it must use one of zero
- // copy, software raster, or GPU raster.
- DCHECK(!IsSynchronousSingleThreaded());
-
- // We need to create a staging resource pool when using copy rasterizer.
- *staging_resource_pool =
- ResourcePool::Create(resource_provider_.get(), image_target);
+ if (use_zero_copy) {
*resource_pool =
- ResourcePool::Create(resource_provider_.get(), GL_TEXTURE_2D);
-
- int max_copy_texture_chromium_size =
- context_provider->ContextCapabilities()
- .gpu.max_copy_texture_chromium_size;
+ ResourcePool::Create(resource_provider_.get(), GetTaskRunner());
- *tile_task_worker_pool = OneCopyTileTaskWorkerPool::Create(
- GetTaskRunner(), task_graph_runner, context_provider,
- resource_provider_.get(), staging_resource_pool_.get(),
- max_copy_texture_chromium_size,
- settings_.use_persistent_map_for_gpu_memory_buffers);
+ *tile_task_worker_pool = ZeroCopyTileTaskWorkerPool::Create(
+ GetTaskRunner(), task_graph_runner, resource_provider_.get(),
+ settings_.renderer_settings.use_rgba_4444_textures);
return;
}
- // Synchronous single-threaded mode depends on tiles being ready to
- // draw when raster is complete. Therefore, it must use one of zero
- // copy, software raster, or GPU raster (in the branches above).
- DCHECK(!IsSynchronousSingleThreaded());
+ *resource_pool = ResourcePool::Create(resource_provider_.get(),
+ GetTaskRunner(), GL_TEXTURE_2D);
- *resource_pool = ResourcePool::Create(
- resource_provider_.get(), GL_TEXTURE_2D);
+ int max_copy_texture_chromium_size = context_provider->ContextCapabilities()
+ .gpu.max_copy_texture_chromium_size;
- *tile_task_worker_pool = PixelBufferTileTaskWorkerPool::Create(
- GetTaskRunner(), task_graph_runner_, context_provider,
- resource_provider_.get(),
- GetMaxTransferBufferUsageBytes(context_provider->ContextCapabilities(),
- settings_.renderer_settings.refresh_rate));
+ *tile_task_worker_pool = OneCopyTileTaskWorkerPool::Create(
+ GetTaskRunner(), task_graph_runner, context_provider,
+ resource_provider_.get(), max_copy_texture_chromium_size,
+ settings_.use_persistent_map_for_gpu_memory_buffers,
+ settings_.max_staging_buffer_usage_in_bytes,
+ settings_.renderer_settings.use_rgba_4444_textures);
}
void LayerTreeHostImpl::RecordMainFrameTiming(
@@ -2214,18 +2163,12 @@ void LayerTreeHostImpl::PostFrameTimingEvents(
void LayerTreeHostImpl::CleanUpTileManager() {
tile_manager_->FinishTasksAndCleanUp();
resource_pool_ = nullptr;
- staging_resource_pool_ = nullptr;
tile_task_worker_pool_ = nullptr;
single_thread_synchronous_task_graph_runner_ = nullptr;
}
-bool LayerTreeHostImpl::IsSynchronousSingleThreaded() const {
- return !proxy_->HasImplThread() && !settings_.single_thread_proxy_scheduler;
-}
-
-bool LayerTreeHostImpl::InitializeRenderer(
- scoped_ptr<OutputSurface> output_surface) {
- TRACE_EVENT0("cc", "LayerTreeHostImpl::InitializeRenderer");
+void LayerTreeHostImpl::ReleaseOutputSurface() {
+ TRACE_EVENT0("cc", "LayerTreeHostImpl::ReleaseOutputSurface");
// Since we will create a new resource provider, we cannot continue to use
// the old resources (i.e. render_surfaces and texture IDs). Clear them
@@ -2236,8 +2179,20 @@ bool LayerTreeHostImpl::InitializeRenderer(
renderer_ = nullptr;
CleanUpTileManager();
resource_provider_ = nullptr;
- output_surface_ = nullptr;
+ // Detach from the old output surface and reset |output_surface_| pointer
+ // as this surface is going to be destroyed independent of if binding the
+ // new output surface succeeds or not.
+ if (output_surface_) {
+ output_surface_->DetachFromClient();
+ output_surface_ = nullptr;
+ }
+}
+
+bool LayerTreeHostImpl::InitializeRenderer(OutputSurface* output_surface) {
+ TRACE_EVENT0("cc", "LayerTreeHostImpl::InitializeRenderer");
+
+ ReleaseOutputSurface();
if (!output_surface->BindToClient(this)) {
// Avoid recreating tree resources because we might not have enough
// information to do this yet (eg. we don't have a TileManager at this
@@ -2245,14 +2200,13 @@ bool LayerTreeHostImpl::InitializeRenderer(
return false;
}
- output_surface_ = output_surface.Pass();
+ output_surface_ = output_surface;
resource_provider_ = ResourceProvider::Create(
- output_surface_.get(), shared_bitmap_manager_, gpu_memory_buffer_manager_,
+ output_surface_, shared_bitmap_manager_, gpu_memory_buffer_manager_,
proxy_->blocking_main_thread_task_runner(),
settings_.renderer_settings.highp_threshold_min,
- settings_.renderer_settings.use_rgba_4444_textures,
settings_.renderer_settings.texture_id_allocation_chunk_size,
- settings_.use_persistent_map_for_gpu_memory_buffers);
+ settings_.use_image_texture_targets);
CreateAndSetRenderer();
@@ -2313,18 +2267,8 @@ void LayerTreeHostImpl::SetViewportSize(const gfx::Size& device_viewport_size) {
client_->OnCanDrawStateChanged(CanDraw());
SetFullRootLayerDamage();
active_tree_->set_needs_update_draw_properties();
-}
-
-void LayerTreeHostImpl::SetDeviceScaleFactor(float device_scale_factor) {
- if (device_scale_factor == device_scale_factor_)
- return;
- device_scale_factor_ = device_scale_factor;
-
- SetFullRootLayerDamage();
-}
-
-void LayerTreeHostImpl::SetPageScaleOnActiveTree(float page_scale_factor) {
- active_tree_->SetPageScaleOnActiveTree(page_scale_factor);
+ active_tree_->property_trees()->clip_tree.SetViewportClip(
+ gfx::RectF(gfx::SizeF(device_viewport_size)));
}
const gfx::Rect LayerTreeHostImpl::ViewportRectForTilePriority() const {
@@ -2394,7 +2338,7 @@ LayerImpl* LayerTreeHostImpl::FindScrollLayerForDeviceViewportPoint(
// Walk up the hierarchy and look for a scrollable layer.
LayerImpl* potentially_scrolling_layer_impl = NULL;
- for (; layer_impl; layer_impl = NextScrollLayer(layer_impl)) {
+ for (; layer_impl; layer_impl = NextLayerInScrollOrder(layer_impl)) {
// The content layer can also block attempts to scroll outside the main
// thread.
ScrollStatus status =
@@ -2426,11 +2370,14 @@ LayerImpl* LayerTreeHostImpl::FindScrollLayerForDeviceViewportPoint(
// Falling back to the root scroll layer ensures generation of root overscroll
// notifications while preventing scroll updates from being unintentionally
- // forwarded to the main thread.
+ // forwarded to the main thread. The inner viewport layer represents the
+ // viewport during scrolling.
if (!potentially_scrolling_layer_impl)
- potentially_scrolling_layer_impl = OuterViewportScrollLayer()
- ? OuterViewportScrollLayer()
- : InnerViewportScrollLayer();
+ potentially_scrolling_layer_impl = InnerViewportScrollLayer();
+
+ // The inner viewport layer represents the viewport.
+ if (potentially_scrolling_layer_impl == OuterViewportScrollLayer())
+ potentially_scrolling_layer_impl = InnerViewportScrollLayer();
return potentially_scrolling_layer_impl;
}
@@ -2439,7 +2386,7 @@ LayerImpl* LayerTreeHostImpl::FindScrollLayerForDeviceViewportPoint(
static bool HasScrollAncestor(LayerImpl* child, LayerImpl* scroll_ancestor) {
DCHECK(scroll_ancestor);
for (LayerImpl* ancestor = child; ancestor;
- ancestor = NextScrollLayer(ancestor)) {
+ ancestor = NextLayerInScrollOrder(ancestor)) {
if (ancestor->scrollable())
return ancestor == scroll_ancestor;
}
@@ -2455,7 +2402,6 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollBeginImpl(
top_controls_manager_->ScrollBegin();
active_tree_->SetCurrentlyScrollingLayer(scrolling_layer_impl);
- should_bubble_scrolls_ = (type != NON_BUBBLING_GESTURE);
wheel_scrolling_ = (type == WHEEL);
client_->RenewTreePriority();
UMA_HISTOGRAM_BOOLEAN("TryScroll.SlowScroll", false);
@@ -2481,7 +2427,7 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollBegin(
ClearCurrentlyScrollingLayer();
gfx::PointF device_viewport_point =
- gfx::ScalePoint(viewport_point, device_scale_factor_);
+ gfx::ScalePoint(viewport_point, active_tree_->device_scale_factor());
LayerImpl* layer_impl =
active_tree_->FindLayerThatIsHitByPoint(device_viewport_point);
@@ -2521,8 +2467,9 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollAnimated(
if (scroll_status == SCROLL_STARTED) {
gfx::Vector2dF pending_delta = scroll_delta;
for (LayerImpl* layer_impl = CurrentlyScrollingLayer(); layer_impl;
- layer_impl = layer_impl->parent()) {
- if (!layer_impl->scrollable())
+ layer_impl = NextLayerInScrollOrder(layer_impl)) {
+ // The inner viewport layer represents the viewport.
+ if (!layer_impl->scrollable() || layer_impl == OuterViewportScrollLayer())
continue;
gfx::ScrollOffset current_offset = layer_impl->CurrentScrollOffset();
@@ -2565,11 +2512,12 @@ gfx::Vector2dF LayerTreeHostImpl::ScrollLayerWithViewportSpaceDelta(
gfx::Transform::kSkipInitialization);
bool did_invert = layer_impl->screen_space_transform().GetInverse(
&inverse_screen_space_transform);
- // TODO(shawnsingh): With the advent of impl-side crolling for non-root
+ // TODO(shawnsingh): With the advent of impl-side scrolling for non-root
// layers, we may need to explicitly handle uninvertible transforms here.
DCHECK(did_invert);
- float scale_from_viewport_to_screen_space = device_scale_factor_;
+ float scale_from_viewport_to_screen_space =
+ active_tree_->device_scale_factor();
gfx::PointF screen_space_point =
gfx::ScalePoint(viewport_point, scale_from_viewport_to_screen_space);
@@ -2638,29 +2586,72 @@ static gfx::Vector2dF ScrollLayerWithLocalDelta(
gfx::Vector2dF LayerTreeHostImpl::ScrollLayer(LayerImpl* layer_impl,
const gfx::Vector2dF& delta,
const gfx::Point& viewport_point,
- bool is_wheel_scroll) {
- // Gesture events need to be transformed from viewport coordinates to
- // local layer coordinates so that the scrolling contents exactly follow
- // the user's finger. In contrast, wheel events represent a fixed amount
- // of scrolling so we can just apply them directly, but the page scale
- // factor is applied to the scroll delta.
- if (is_wheel_scroll) {
- float scale_factor = active_tree()->current_page_scale_factor();
- return ScrollLayerWithLocalDelta(layer_impl,
- delta,
- scale_factor);
+ bool is_direct_manipulation) {
+ // Events representing direct manipulation of the screen (such as gesture
+ // events) need to be transformed from viewport coordinates to local layer
+ // coordinates so that the scrolling contents exactly follow the user's
+ // finger. In contrast, events not representing direct manipulation of the
+ // screen (such as wheel events) represent a fixed amount of scrolling so we
+ // can just apply them directly, but the page scale factor is applied to the
+ // scroll delta.
+ if (is_direct_manipulation)
+ return ScrollLayerWithViewportSpaceDelta(layer_impl, viewport_point, delta);
+ float scale_factor = active_tree()->current_page_scale_factor();
+ return ScrollLayerWithLocalDelta(layer_impl, delta, scale_factor);
+}
+
+void LayerTreeHostImpl::ApplyScroll(LayerImpl* layer,
+ ScrollState* scroll_state) {
+ DCHECK(scroll_state);
+ gfx::Point viewport_point(scroll_state->start_position_x(),
+ scroll_state->start_position_y());
+ const gfx::Vector2dF delta(scroll_state->delta_x(), scroll_state->delta_y());
+ gfx::Vector2dF applied_delta;
+ // TODO(tdresser): Use a more rational epsilon. See crbug.com/510550 for
+ // details.
+ const float kEpsilon = 0.1f;
+
+ if (layer == InnerViewportScrollLayer()) {
+ bool affect_top_controls = !wheel_scrolling_;
+ Viewport::ScrollResult result = viewport()->ScrollBy(
+ delta, viewport_point, scroll_state->is_direct_manipulation(),
+ affect_top_controls);
+ applied_delta = result.consumed_delta;
+ scroll_state->set_caused_scroll(
+ std::abs(result.content_scrolled_delta.x()) > kEpsilon,
+ std::abs(result.content_scrolled_delta.y()) > kEpsilon);
+ scroll_state->ConsumeDelta(applied_delta.x(), applied_delta.y());
+ } else {
+ applied_delta = ScrollLayer(layer, delta, viewport_point,
+ scroll_state->is_direct_manipulation());
+ }
+
+ // If the layer wasn't able to move, try the next one in the hierarchy.
+ bool scrolled = std::abs(applied_delta.x()) > kEpsilon;
+ scrolled = scrolled || std::abs(applied_delta.y()) > kEpsilon;
+
+ if (scrolled && layer != InnerViewportScrollLayer()) {
+ // If the applied delta is within 45 degrees of the input
+ // delta, bail out to make it easier to scroll just one layer
+ // in one direction without affecting any of its parents.
+ float angle_threshold = 45;
+ if (MathUtil::SmallestAngleBetweenVectors(applied_delta, delta) <
+ angle_threshold) {
+ applied_delta = delta;
+ } else {
+ // Allow further movement only on an axis perpendicular to the direction
+ // in which the layer moved.
+ applied_delta = MathUtil::ProjectVector(delta, applied_delta);
+ }
+ scroll_state->set_caused_scroll(std::abs(applied_delta.x()) > kEpsilon,
+ std::abs(applied_delta.y()) > kEpsilon);
+ scroll_state->ConsumeDelta(applied_delta.x(), applied_delta.y());
}
- return ScrollLayerWithViewportSpaceDelta(layer_impl,
- viewport_point,
- delta);
-}
-
-static LayerImpl* nextLayerInScrollOrder(LayerImpl* layer) {
- if (layer->scroll_parent())
- return layer->scroll_parent();
+ if (!scrolled)
+ return;
- return layer->parent();
+ scroll_state->set_current_native_scrolling_layer(layer);
}
InputHandlerScrollResult LayerTreeHostImpl::ScrollBy(
@@ -2670,86 +2661,34 @@ InputHandlerScrollResult LayerTreeHostImpl::ScrollBy(
if (!CurrentlyScrollingLayer())
return InputHandlerScrollResult();
- gfx::Vector2dF pending_delta = scroll_delta;
- gfx::Vector2dF unused_root_delta;
- bool did_scroll_x = false;
- bool did_scroll_y = false;
- bool did_scroll_top_controls = false;
-
- if (pinch_gesture_active_ && settings().invert_viewport_scroll_order) {
- // Scrolls during a pinch gesture should pan the visual viewport, rather
- // than a typical bubbling scroll.
- viewport()->Pan(pending_delta);
- return InputHandlerScrollResult();
- }
-
- for (LayerImpl* layer_impl = CurrentlyScrollingLayer();
- layer_impl;
- layer_impl = nextLayerInScrollOrder(layer_impl)) {
+ float initial_top_controls_offset =
+ top_controls_manager_->ControlsTopOffset();
+ ScrollState scroll_state(
+ scroll_delta.x(), scroll_delta.y(), viewport_point.x(),
+ viewport_point.y(), false /* should_propagate */,
+ did_lock_scrolling_layer_ /* delta_consumed_for_scroll_sequence */,
+ !wheel_scrolling_ /* is_direct_manipulation */);
+ scroll_state.set_current_native_scrolling_layer(CurrentlyScrollingLayer());
+
+ std::list<LayerImpl*> current_scroll_chain;
+ for (LayerImpl* layer_impl = CurrentlyScrollingLayer(); layer_impl;
+ layer_impl = NextLayerInScrollOrder(layer_impl)) {
// Skip the outer viewport scroll layer so that we try to scroll the
// viewport only once. i.e. The inner viewport layer represents the
// viewport.
if (!layer_impl->scrollable() || layer_impl == OuterViewportScrollLayer())
continue;
-
- gfx::Vector2dF applied_delta;
- if (layer_impl == InnerViewportScrollLayer()) {
- bool affect_top_controls = true;
- Viewport::ScrollResult result = viewport()->ScrollBy(pending_delta,
- viewport_point,
- wheel_scrolling_,
- affect_top_controls);
- applied_delta = result.applied_delta;
- unused_root_delta = result.unused_scroll_delta;
- did_scroll_top_controls = result.top_controls_applied_delta.y() != 0;
- } else {
- applied_delta = ScrollLayer(layer_impl,
- pending_delta,
- viewport_point,
- wheel_scrolling_);
- }
-
- // If the layer wasn't able to move, try the next one in the hierarchy.
- const float kEpsilon = 0.1f;
- bool did_move_layer_x = std::abs(applied_delta.x()) > kEpsilon;
- bool did_move_layer_y = std::abs(applied_delta.y()) > kEpsilon;
- did_scroll_x |= did_move_layer_x;
- did_scroll_y |= did_move_layer_y;
-
- if (did_move_layer_x || did_move_layer_y) {
- did_lock_scrolling_layer_ = true;
-
- // When scrolls are allowed to bubble, it's important that the original
- // scrolling layer be preserved. This ensures that, after a scroll
- // bubbles, the user can reverse scroll directions and immediately resume
- // scrolling the original layer that scrolled.
- if (!should_bubble_scrolls_) {
- active_tree_->SetCurrentlyScrollingLayer(layer_impl);
- break;
- }
-
- // If the applied delta is within 45 degrees of the input delta, bail out
- // to make it easier to scroll just one layer in one direction without
- // affecting any of its parents.
- float angle_threshold = 45;
- if (MathUtil::SmallestAngleBetweenVectors(applied_delta, pending_delta) <
- angle_threshold)
- break;
-
- // Allow further movement only on an axis perpendicular to the direction
- // in which the layer moved.
- gfx::Vector2dF perpendicular_axis(-applied_delta.y(), applied_delta.x());
- pending_delta =
- MathUtil::ProjectVector(pending_delta, perpendicular_axis);
-
- if (gfx::ToRoundedVector2d(pending_delta).IsZero())
- break;
- }
-
- if (!should_bubble_scrolls_ && did_lock_scrolling_layer_)
- break;
+ current_scroll_chain.push_front(layer_impl);
}
+ scroll_state.set_scroll_chain(current_scroll_chain);
+ scroll_state.DistributeToScrollChainDescendant();
+ active_tree_->SetCurrentlyScrollingLayer(
+ scroll_state.current_native_scrolling_layer());
+ did_lock_scrolling_layer_ = scroll_state.delta_consumed_for_scroll_sequence();
+
+ bool did_scroll_x = scroll_state.caused_scroll_x();
+ bool did_scroll_y = scroll_state.caused_scroll_y();
bool did_scroll_content = did_scroll_x || did_scroll_y;
if (did_scroll_content) {
// If we are scrolling with an active scroll handler, forward latency
@@ -2767,13 +2706,32 @@ InputHandlerScrollResult LayerTreeHostImpl::ScrollBy(
accumulated_root_overscroll_.set_x(0);
if (did_scroll_y)
accumulated_root_overscroll_.set_y(0);
+ gfx::Vector2dF unused_root_delta(scroll_state.delta_x(),
+ scroll_state.delta_y());
+
+ // When inner viewport is unscrollable, disable overscrolls.
+ if (InnerViewportScrollLayer()) {
+ if (!InnerViewportScrollLayer()->user_scrollable_horizontal())
+ unused_root_delta.set_x(0);
+ if (!InnerViewportScrollLayer()->user_scrollable_vertical())
+ unused_root_delta.set_y(0);
+ }
+
accumulated_root_overscroll_ += unused_root_delta;
+ bool did_scroll_top_controls =
+ initial_top_controls_offset != top_controls_manager_->ControlsTopOffset();
+
InputHandlerScrollResult scroll_result;
scroll_result.did_scroll = did_scroll_content || did_scroll_top_controls;
scroll_result.did_overscroll_root = !unused_root_delta.IsZero();
scroll_result.accumulated_root_overscroll = accumulated_root_overscroll_;
scroll_result.unused_scroll_delta = unused_root_delta;
+
+ // Scrolling can change the root scroll offset, so inform the synchronous
+ // input handler.
+ UpdateRootLayerStateForSynchronousInputHandler();
+
return scroll_result;
}
@@ -2784,10 +2742,10 @@ bool LayerTreeHostImpl::ScrollVerticallyByPage(const gfx::Point& viewport_point,
ScrollDirection direction) {
DCHECK(wheel_scrolling_);
- for (LayerImpl* layer_impl = CurrentlyScrollingLayer();
- layer_impl;
- layer_impl = layer_impl->parent()) {
- if (!layer_impl->scrollable())
+ for (LayerImpl* layer_impl = CurrentlyScrollingLayer(); layer_impl;
+ layer_impl = NextLayerInScrollOrder(layer_impl)) {
+ // The inner viewport layer represents the viewport.
+ if (!layer_impl->scrollable() || layer_impl == OuterViewportScrollLayer())
continue;
if (!layer_impl->HasScrollbar(VERTICAL))
@@ -2819,19 +2777,19 @@ bool LayerTreeHostImpl::ScrollVerticallyByPage(const gfx::Point& viewport_point,
return false;
}
-void LayerTreeHostImpl::SetRootLayerScrollOffsetDelegate(
- LayerScrollOffsetDelegate* root_layer_scroll_offset_delegate) {
- root_layer_scroll_offset_delegate_ = root_layer_scroll_offset_delegate;
- active_tree_->SetRootLayerScrollOffsetDelegate(
- root_layer_scroll_offset_delegate_);
+void LayerTreeHostImpl::RequestUpdateForSynchronousInputHandler() {
+ UpdateRootLayerStateForSynchronousInputHandler();
}
-void LayerTreeHostImpl::OnRootLayerDelegatedScrollOffsetChanged() {
- DCHECK(root_layer_scroll_offset_delegate_);
- active_tree_->DistributeRootScrollOffset();
+void LayerTreeHostImpl::SetSynchronousInputHandlerRootScrollOffset(
+ const gfx::ScrollOffset& root_offset) {
+ active_tree_->DistributeRootScrollOffset(root_offset);
client_->SetNeedsCommitOnImplThread();
- SetNeedsRedraw();
- active_tree_->set_needs_update_draw_properties();
+ // After applying the synchronous input handler's scroll offset, tell it what
+ // we ended up with.
+ UpdateRootLayerStateForSynchronousInputHandler();
+ // No need to SetNeedsRedraw, this is for WebView and every frame has redraw
+ // requested by the WebView embedder already.
}
void LayerTreeHostImpl::ClearCurrentlyScrollingLayer() {
@@ -2849,17 +2807,6 @@ void LayerTreeHostImpl::ScrollEnd() {
InputHandler::ScrollStatus LayerTreeHostImpl::FlingScrollBegin() {
if (!CurrentlyScrollingLayer())
return SCROLL_IGNORED;
-
- bool currently_scrolling_viewport =
- CurrentlyScrollingLayer() == OuterViewportScrollLayer() ||
- CurrentlyScrollingLayer() == InnerViewportScrollLayer();
- if (!wheel_scrolling_ && !currently_scrolling_viewport) {
- // Allow the fling to lock to the first layer that moves after the initial
- // fling |ScrollBy()| event, unless we're already scrolling the viewport.
- did_lock_scrolling_layer_ = false;
- should_bubble_scrolls_ = false;
- }
-
return SCROLL_STARTED;
}
@@ -2872,16 +2819,15 @@ float LayerTreeHostImpl::DeviceSpaceDistanceToLayer(
gfx::Rect layer_impl_bounds(layer_impl->bounds());
gfx::RectF device_viewport_layer_impl_bounds = MathUtil::MapClippedRect(
- layer_impl->screen_space_transform(),
- layer_impl_bounds);
+ layer_impl->screen_space_transform(), gfx::RectF(layer_impl_bounds));
return device_viewport_layer_impl_bounds.ManhattanDistanceToPoint(
device_viewport_point);
}
void LayerTreeHostImpl::MouseMoveAt(const gfx::Point& viewport_point) {
- gfx::PointF device_viewport_point = gfx::ScalePoint(viewport_point,
- device_scale_factor_);
+ gfx::PointF device_viewport_point =
+ gfx::ScalePoint(viewport_point, active_tree_->device_scale_factor());
LayerImpl* layer_impl =
active_tree_->FindLayerThatIsHitByPoint(device_viewport_point);
if (HandleMouseOverScrollbar(layer_impl, device_viewport_point))
@@ -2925,7 +2871,7 @@ void LayerTreeHostImpl::MouseMoveAt(const gfx::Point& viewport_point) {
DeviceSpaceDistanceToLayer(device_viewport_point, *it));
animation_controller->DidMouseMoveNear(distance_to_scrollbar /
- device_scale_factor_);
+ active_tree_->device_scale_factor());
}
bool LayerTreeHostImpl::HandleMouseOverScrollbar(LayerImpl* layer_impl,
@@ -2950,36 +2896,23 @@ void LayerTreeHostImpl::PinchGestureBegin() {
pinch_gesture_active_ = true;
client_->RenewTreePriority();
pinch_gesture_end_should_clear_scrolling_layer_ = !CurrentlyScrollingLayer();
- if (active_tree_->OuterViewportScrollLayer()) {
- active_tree_->SetCurrentlyScrollingLayer(
- active_tree_->OuterViewportScrollLayer());
- } else {
- active_tree_->SetCurrentlyScrollingLayer(
- active_tree_->InnerViewportScrollLayer());
- }
+ active_tree_->SetCurrentlyScrollingLayer(
+ active_tree_->InnerViewportScrollLayer());
top_controls_manager_->PinchBegin();
}
void LayerTreeHostImpl::PinchGestureUpdate(float magnify_delta,
const gfx::Point& anchor) {
+ TRACE_EVENT0("cc", "LayerTreeHostImpl::PinchGestureUpdate");
if (!InnerViewportScrollLayer())
return;
-
- TRACE_EVENT0("cc", "LayerTreeHostImpl::PinchGestureUpdate");
-
- // For a moment the scroll offset ends up being outside of the max range. This
- // confuses the delegate so we switch it off till after we're done processing
- // the pinch update.
- active_tree_->SetRootLayerScrollOffsetDelegate(NULL);
-
viewport()->PinchUpdate(magnify_delta, anchor);
-
- active_tree_->SetRootLayerScrollOffsetDelegate(
- root_layer_scroll_offset_delegate_);
-
client_->SetNeedsCommitOnImplThread();
SetNeedsRedraw();
client_->RenewTreePriority();
+ // Pinching can change the root scroll offset, so inform the synchronous input
+ // handler.
+ UpdateRootLayerStateForSynchronousInputHandler();
}
void LayerTreeHostImpl::PinchGestureEnd() {
@@ -3056,12 +2989,6 @@ void LayerTreeHostImpl::ScrollViewportBy(gfx::Vector2dF scroll_delta) {
InnerViewportScrollLayer()->ScrollBy(unused_delta);
}
-void LayerTreeHostImpl::AnimateInput(base::TimeTicks monotonic_time) {
- DCHECK(proxy_->IsImplThread());
- if (input_handler_client_)
- input_handler_client_->Animate(monotonic_time);
-}
-
void LayerTreeHostImpl::AnimatePageScale(base::TimeTicks monotonic_time) {
if (!page_scale_animation_)
return;
@@ -3125,20 +3052,26 @@ void LayerTreeHostImpl::AnimateScrollbars(base::TimeTicks monotonic_time) {
}
void LayerTreeHostImpl::AnimateLayers(base::TimeTicks monotonic_time) {
- if (!settings_.accelerated_animation_enabled || !active_tree_->root_layer())
+ if (!settings_.accelerated_animation_enabled)
return;
+ bool animated = false;
if (animation_host_) {
if (animation_host_->AnimateLayers(monotonic_time))
- SetNeedsAnimate();
+ animated = true;
} else {
if (animation_registrar_->AnimateLayers(monotonic_time))
- SetNeedsAnimate();
+ animated = true;
}
+
+ // TODO(ajuma): Only do this if the animations are on the active tree, or if
+ // they are on the pending tree waiting for some future time to start.
+ if (animated)
+ SetNeedsAnimate();
}
void LayerTreeHostImpl::UpdateAnimationState(bool start_ready_animations) {
- if (!settings_.accelerated_animation_enabled || !active_tree_->root_layer())
+ if (!settings_.accelerated_animation_enabled)
return;
bool has_active_animations = false;
@@ -3162,15 +3095,25 @@ void LayerTreeHostImpl::UpdateAnimationState(bool start_ready_animations) {
}
void LayerTreeHostImpl::ActivateAnimations() {
- if (!settings_.accelerated_animation_enabled || !active_tree_->root_layer())
+ if (!settings_.accelerated_animation_enabled)
return;
+ bool activated = false;
if (animation_host_) {
if (animation_host_->ActivateAnimations())
- SetNeedsAnimate();
+ activated = true;
} else {
if (animation_registrar_->ActivateAnimations())
- SetNeedsAnimate();
+ activated = true;
+ }
+
+ if (activated) {
+ SetNeedsAnimate();
+ // Activating an animation changes layer draw properties, such as
+ // screen_space_transform_is_animating, or changes transforms etc. So when
+ // we see a new animation get activated, we need to update the draw
+ // properties on the active tree.
+ active_tree()->set_needs_update_draw_properties();
}
}
@@ -3313,8 +3256,6 @@ void LayerTreeHostImpl::SetDebugState(
const LayerTreeDebugState& new_debug_state) {
if (LayerTreeDebugState::Equal(debug_state_, new_debug_state))
return;
- if (debug_state_.continuous_painting != new_debug_state.continuous_painting)
- paint_time_counter_->ClearHistory();
debug_state_ = new_debug_state;
UpdateTileManagerMemoryPolicy(ActualManagedMemoryPolicy());
@@ -3447,6 +3388,16 @@ void LayerTreeHostImpl::NotifySwapPromiseMonitorsOfForwardingToMainThread() {
(*it)->OnForwardScrollUpdateToMainThreadOnImpl();
}
+void LayerTreeHostImpl::UpdateRootLayerStateForSynchronousInputHandler() {
+ if (!input_handler_client_)
+ return;
+ input_handler_client_->UpdateRootLayerStateForSynchronousInputHandler(
+ active_tree_->TotalScrollOffset(), active_tree_->TotalMaxScrollOffset(),
+ active_tree_->ScrollableSize(), active_tree_->current_page_scale_factor(),
+ active_tree_->min_page_scale_factor(),
+ active_tree_->max_page_scale_factor());
+}
+
void LayerTreeHostImpl::ScrollAnimationCreate(
LayerImpl* layer_impl,
const gfx::ScrollOffset& target_offset,
@@ -3566,6 +3517,18 @@ void LayerTreeHostImpl::SetTreeLayerScrollOffsetMutated(
layer->OnScrollOffsetAnimated(scroll_offset);
}
+void LayerTreeHostImpl::TreeLayerTransformIsPotentiallyAnimatingChanged(
+ int layer_id,
+ LayerTreeImpl* tree,
+ bool is_animating) {
+ if (!tree)
+ return;
+
+ LayerAnimationValueObserver* layer = tree->LayerById(layer_id);
+ if (layer)
+ layer->OnTransformIsPotentiallyAnimatingChanged(is_animating);
+}
+
void LayerTreeHostImpl::SetLayerFilterMutated(int layer_id,
LayerTreeType tree_type,
const FilterOperations& filters) {
@@ -3612,6 +3575,19 @@ void LayerTreeHostImpl::SetLayerScrollOffsetMutated(
}
}
+void LayerTreeHostImpl::LayerTransformIsPotentiallyAnimatingChanged(
+ int layer_id,
+ LayerTreeType tree_type,
+ bool is_animating) {
+ if (tree_type == LayerTreeType::ACTIVE) {
+ TreeLayerTransformIsPotentiallyAnimatingChanged(layer_id, active_tree(),
+ is_animating);
+ } else {
+ TreeLayerTransformIsPotentiallyAnimatingChanged(layer_id, pending_tree(),
+ is_animating);
+ }
+}
+
void LayerTreeHostImpl::ScrollOffsetAnimationFinished() {
ScrollEnd();
}
diff --git a/chromium/cc/trees/layer_tree_host_impl.h b/chromium/cc/trees/layer_tree_host_impl.h
index f66f5b1de83..f2d5dfaa305 100644
--- a/chromium/cc/trees/layer_tree_host_impl.h
+++ b/chromium/cc/trees/layer_tree_host_impl.h
@@ -21,7 +21,6 @@
#include "cc/debug/frame_timing_tracker.h"
#include "cc/debug/micro_benchmark_controller_impl.h"
#include "cc/input/input_handler.h"
-#include "cc/input/layer_scroll_offset_delegate.h"
#include "cc/input/top_controls_manager_client.h"
#include "cc/layers/layer_lists.h"
#include "cc/layers/render_pass_sink.h"
@@ -60,7 +59,6 @@ class LayerImpl;
class LayerTreeImpl;
class MemoryHistory;
class PageScaleAnimation;
-class PaintTimeCounter;
class PictureLayerImpl;
class RasterTilePriorityQueue;
class TileTaskWorkerPool;
@@ -168,14 +166,15 @@ class CC_EXPORT LayerTreeHostImpl
InputHandler::ScrollStatus ScrollAnimated(
const gfx::Point& viewport_point,
const gfx::Vector2dF& scroll_delta) override;
+ void ApplyScroll(LayerImpl* layer, ScrollState* scroll_state);
InputHandlerScrollResult ScrollBy(
const gfx::Point& viewport_point,
const gfx::Vector2dF& scroll_delta) override;
bool ScrollVerticallyByPage(const gfx::Point& viewport_point,
ScrollDirection direction) override;
- void SetRootLayerScrollOffsetDelegate(
- LayerScrollOffsetDelegate* root_layer_scroll_offset_delegate) override;
- void OnRootLayerDelegatedScrollOffsetChanged() override;
+ void RequestUpdateForSynchronousInputHandler() override;
+ void SetSynchronousInputHandlerRootScrollOffset(
+ const gfx::ScrollOffset& root_offset) override;
void ScrollEnd() override;
InputHandler::ScrollStatus FlingScrollBegin() override;
void MouseMoveAt(const gfx::Point& viewport_point) override;
@@ -188,8 +187,10 @@ class CC_EXPORT LayerTreeHostImpl
float page_scale,
base::TimeDelta duration);
void SetNeedsAnimateInput() override;
- bool IsCurrentlyScrollingLayerAt(const gfx::Point& viewport_point,
- InputHandler::ScrollInputType type) override;
+ bool IsCurrentlyScrollingRoot() const override;
+ bool IsCurrentlyScrollingLayerAt(
+ const gfx::Point& viewport_point,
+ InputHandler::ScrollInputType type) const override;
bool HaveWheelEventHandlersAt(const gfx::Point& viewport_point) override;
bool DoTouchEventsBlockScrollAt(const gfx::Point& viewport_port) override;
scoped_ptr<SwapPromiseMonitor> CreateLatencyInfoSwapPromiseMonitor(
@@ -226,7 +227,7 @@ class CC_EXPORT LayerTreeHostImpl
virtual void BeginMainFrameAborted(CommitEarlyOutReason reason);
virtual void BeginCommit();
virtual void CommitComplete();
- virtual void Animate(base::TimeTicks monotonic_time);
+ virtual void Animate();
virtual void UpdateAnimationState(bool start_ready_animations);
void ActivateAnimations();
void MainThreadHasStoppedFlinging();
@@ -245,6 +246,9 @@ class CC_EXPORT LayerTreeHostImpl
void SetTreeLayerScrollOffsetMutated(int layer_id,
LayerTreeImpl* tree,
const gfx::ScrollOffset& scroll_offset);
+ void TreeLayerTransformIsPotentiallyAnimatingChanged(int layer_id,
+ LayerTreeImpl* tree,
+ bool is_animating);
// LayerTreeMutatorsClient implementation.
bool IsLayerInTree(int layer_id, LayerTreeType tree_type) const override;
@@ -262,6 +266,9 @@ class CC_EXPORT LayerTreeHostImpl
int layer_id,
LayerTreeType tree_type,
const gfx::ScrollOffset& scroll_offset) override;
+ void LayerTransformIsPotentiallyAnimatingChanged(int layer_id,
+ LayerTreeType tree_type,
+ bool is_animating) override;
void ScrollOffsetAnimationFinished() override;
gfx::ScrollOffset GetScrollOffsetForAnimation(int layer_id) const override;
@@ -353,13 +360,15 @@ class CC_EXPORT LayerTreeHostImpl
// Implementation.
int id() const { return id_; }
bool CanDraw() const;
- OutputSurface* output_surface() const { return output_surface_.get(); }
+ OutputSurface* output_surface() const { return output_surface_; }
+ void ReleaseOutputSurface();
std::string LayerTreeAsJson() const;
void FinishAllRendering();
+ int RequestedMSAASampleCount() const;
- virtual bool InitializeRenderer(scoped_ptr<OutputSurface> output_surface);
+ virtual bool InitializeRenderer(OutputSurface* output_surface);
TileManager* tile_manager() { return tile_manager_.get(); }
void SetHasGpuRasterizationTrigger(bool flag) {
@@ -426,8 +435,6 @@ class CC_EXPORT LayerTreeHostImpl
virtual void SetVisible(bool visible);
bool visible() const { return visible_; }
- bool AnimationsAreVisible() { return visible() && CanDraw(); }
-
void SetNeedsCommit() { client_->SetNeedsCommitOnImplThread(); }
void SetNeedsAnimate();
void SetNeedsRedraw();
@@ -439,11 +446,6 @@ class CC_EXPORT LayerTreeHostImpl
void SetViewportSize(const gfx::Size& device_viewport_size);
gfx::Size device_viewport_size() const { return device_viewport_size_; }
- void SetDeviceScaleFactor(float device_scale_factor);
- float device_scale_factor() const { return device_scale_factor_; }
-
- void SetPageScaleOnActiveTree(float page_scale_factor);
-
const gfx::Transform& DrawTransform() const;
scoped_ptr<ScrollAndScaleSet> ProcessScrollDeltas();
@@ -455,9 +457,6 @@ class CC_EXPORT LayerTreeHostImpl
FrameRateCounter* fps_counter() {
return fps_counter_.get();
}
- PaintTimeCounter* paint_time_counter() {
- return paint_time_counter_.get();
- }
MemoryHistory* memory_history() {
return memory_history_.get();
}
@@ -552,8 +551,7 @@ class CC_EXPORT LayerTreeHostImpl
virtual void CreateResourceAndTileTaskWorkerPool(
scoped_ptr<TileTaskWorkerPool>* tile_task_worker_pool,
- scoped_ptr<ResourcePool>* resource_pool,
- scoped_ptr<ResourcePool>* staging_resource_pool);
+ scoped_ptr<ResourcePool>* resource_pool);
bool prepare_tiles_needed() const { return tile_priorities_dirty_; }
@@ -564,7 +562,7 @@ class CC_EXPORT LayerTreeHostImpl
gfx::Vector2dF ScrollLayer(LayerImpl* layer_impl,
const gfx::Vector2dF& delta,
const gfx::Point& viewport_point,
- bool is_wheel_scroll);
+ bool is_direct_manipulation);
// Record main frame timing information.
// |start_of_main_frame_args| is the BeginFrameArgs of the beginning of the
@@ -624,8 +622,6 @@ class CC_EXPORT LayerTreeHostImpl
void UpdateGpuRasterizationStatus();
- bool IsSynchronousSingleThreaded() const;
-
Viewport* viewport() { return viewport_.get(); }
// Scroll by preferring to move the outer viewport first, only moving the
@@ -639,7 +635,6 @@ class CC_EXPORT LayerTreeHostImpl
LayerImpl* scrolling_layer_impl,
InputHandler::ScrollInputType type);
- void AnimateInput(base::TimeTicks monotonic_time);
void AnimatePageScale(base::TimeTicks monotonic_time);
void AnimateScrollbars(base::TimeTicks monotonic_time);
void AnimateTopControls(base::TimeTicks monotonic_time);
@@ -676,6 +671,8 @@ class CC_EXPORT LayerTreeHostImpl
void NotifySwapPromiseMonitorsOfSetNeedsRedraw();
void NotifySwapPromiseMonitorsOfForwardingToMainThread();
+ void UpdateRootLayerStateForSynchronousInputHandler();
+
void ScrollAnimationCreate(LayerImpl* layer_impl,
const gfx::ScrollOffset& target_offset,
const gfx::ScrollOffset& current_offset);
@@ -697,7 +694,7 @@ class CC_EXPORT LayerTreeHostImpl
// request queue.
std::set<UIResourceId> evicted_ui_resources_;
- scoped_ptr<OutputSurface> output_surface_;
+ OutputSurface* output_surface_;
scoped_ptr<ResourceProvider> resource_provider_;
bool content_is_suitable_for_gpu_rasterization_;
@@ -708,7 +705,6 @@ class CC_EXPORT LayerTreeHostImpl
bool tree_resources_for_gpu_rasterization_dirty_;
scoped_ptr<TileTaskWorkerPool> tile_task_worker_pool_;
scoped_ptr<ResourcePool> resource_pool_;
- scoped_ptr<ResourcePool> staging_resource_pool_;
scoped_ptr<Renderer> renderer_;
GlobalStateThatImpactsTilePriority global_tile_state_;
@@ -726,7 +722,6 @@ class CC_EXPORT LayerTreeHostImpl
InputHandlerClient* input_handler_client_;
bool did_lock_scrolling_layer_;
- bool should_bubble_scrolls_;
bool wheel_scrolling_;
bool scroll_affects_scroll_handler_;
int scroll_layer_id_when_mouse_over_scrollbar_;
@@ -738,15 +733,12 @@ class CC_EXPORT LayerTreeHostImpl
bool tile_priorities_dirty_;
- // The optional delegate for the root layer scroll offset.
- LayerScrollOffsetDelegate* root_layer_scroll_offset_delegate_;
- LayerScrollOffsetDelegate::AnimationCallback root_layer_animation_callback_;
-
const LayerTreeSettings settings_;
LayerTreeDebugState debug_state_;
bool visible_;
ManagedMemoryPolicy cached_managed_memory_policy_;
+ const bool is_synchronous_single_threaded_;
scoped_ptr<TileManager> tile_manager_;
gfx::Vector2dF accumulated_root_overscroll_;
@@ -759,7 +751,6 @@ class CC_EXPORT LayerTreeHostImpl
scoped_ptr<PageScaleAnimation> page_scale_animation_;
scoped_ptr<FrameRateCounter> fps_counter_;
- scoped_ptr<PaintTimeCounter> paint_time_counter_;
scoped_ptr<MemoryHistory> memory_history_;
scoped_ptr<DebugRectHistory> debug_rect_history_;
@@ -775,10 +766,6 @@ class CC_EXPORT LayerTreeHostImpl
// overridden.
gfx::Size device_viewport_size_;
- // Conversion factor from CSS pixels to physical pixels when
- // pageScaleFactor=1.
- float device_scale_factor_;
-
// Optional top-level constraints that can be set by the OutputSurface.
// - external_transform_ applies a transform above the root layer
// - external_viewport_ is used DrawProperties, tile management and
diff --git a/chromium/cc/trees/layer_tree_host_impl_unittest.cc b/chromium/cc/trees/layer_tree_host_impl_unittest.cc
index d20e603fd0c..3d47528b9bc 100644
--- a/chromium/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/chromium/cc/trees/layer_tree_host_impl_unittest.cc
@@ -14,6 +14,7 @@
#include "base/location.h"
#include "base/thread_task_runner_handle.h"
#include "cc/animation/scrollbar_animation_controller_thinning.h"
+#include "cc/animation/transform_operations.h"
#include "cc/base/math_util.h"
#include "cc/input/page_scale_animation.h"
#include "cc/input/top_controls_manager.h"
@@ -42,18 +43,17 @@
#include "cc/quads/tile_draw_quad.h"
#include "cc/test/animation_test_common.h"
#include "cc/test/begin_frame_args_test.h"
+#include "cc/test/fake_display_list_raster_source.h"
#include "cc/test/fake_layer_tree_host_impl.h"
#include "cc/test/fake_output_surface.h"
#include "cc/test/fake_output_surface_client.h"
#include "cc/test/fake_picture_layer_impl.h"
-#include "cc/test/fake_picture_pile_impl.h"
#include "cc/test/fake_proxy.h"
#include "cc/test/fake_video_frame_provider.h"
#include "cc/test/geometry_test_utils.h"
#include "cc/test/gpu_rasterization_enabled_settings.h"
#include "cc/test/layer_test_common.h"
#include "cc/test/layer_tree_test.h"
-#include "cc/test/render_pass_test_common.h"
#include "cc/test/test_gpu_memory_buffer_manager.h"
#include "cc/test/test_shared_bitmap_manager.h"
#include "cc/test/test_task_graph_runner.h"
@@ -101,8 +101,8 @@ class LayerTreeHostImplTest : public testing::Test,
LayerTreeSettings settings;
settings.minimum_occlusion_tracking_size = gfx::Size();
settings.renderer_settings.texture_id_allocation_chunk_size = 1;
- settings.report_overscroll_only_for_scrollable_axes = true;
settings.gpu_rasterization_enabled = true;
+ settings.verify_property_trees = true;
return settings;
}
@@ -169,11 +169,15 @@ class LayerTreeHostImplTest : public testing::Test,
settings, this, &proxy_, &stats_instrumentation_,
&shared_bitmap_manager_, &gpu_memory_buffer_manager_,
&task_graph_runner_, 0);
- bool init = host_impl_->InitializeRenderer(output_surface.Pass());
+ output_surface_ = output_surface.Pass();
+ bool init = host_impl_->InitializeRenderer(output_surface_.get());
host_impl_->SetViewportSize(gfx::Size(10, 10));
+ host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 1.f);
// Set the BeginFrameArgs so that methods which use it are able to.
- host_impl_->WillBeginImplFrame(
- CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE));
+ host_impl_->WillBeginImplFrame(CreateBeginFrameArgsForTesting(
+ BEGINFRAME_FROM_HERE,
+ base::TimeTicks() + base::TimeDelta::FromMilliseconds(1)));
+ host_impl_->DidFinishImplFrame();
return init;
}
@@ -299,6 +303,7 @@ class LayerTreeHostImplTest : public testing::Test,
LayerImpl* SetupScrollAndContentsLayers(const gfx::Size& content_size) {
LayerImpl* scroll_layer = CreateScrollAndContentsLayers(
host_impl_->active_tree(), content_size);
+ host_impl_->active_tree()->BuildPropertyTreesForTesting();
host_impl_->active_tree()->DidBecomeActive();
return scroll_layer;
}
@@ -331,7 +336,6 @@ class LayerTreeHostImplTest : public testing::Test,
return content_layer;
}
- // TODO(wjmaclean) Add clip-layer pointer to parameters.
scoped_ptr<LayerImpl> CreateScrollableLayer(int id,
const gfx::Size& size,
LayerImpl* clip_layer) {
@@ -348,11 +352,23 @@ class LayerTreeHostImplTest : public testing::Test,
void DrawFrame() {
LayerTreeHostImpl::FrameData frame;
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
host_impl_->DidDrawAllLayers(frame);
}
+ void RebuildPropertyTrees() {
+ host_impl_->active_tree()->property_trees()->needs_rebuild = true;
+ host_impl_->active_tree()->BuildPropertyTreesForTesting();
+ }
+
+ DrawResult PrepareToDrawFrame(LayerTreeHostImpl::FrameData* frame) {
+ // We need to build property trees here before drawing the frame as they are
+ // not built on the impl thread.
+ RebuildPropertyTrees();
+ return host_impl_->PrepareToDraw(frame);
+ }
+
void pinch_zoom_pan_viewport_forces_commit_redraw(float device_scale_factor);
void pinch_zoom_pan_viewport_test(float device_scale_factor);
void pinch_zoom_pan_viewport_and_scroll_test(float device_scale_factor);
@@ -408,7 +424,7 @@ class LayerTreeHostImplTest : public testing::Test,
void DrawOneFrame() {
LayerTreeHostImpl::FrameData frame_data;
- host_impl_->PrepareToDraw(&frame_data);
+ PrepareToDrawFrame(&frame_data);
host_impl_->DidDrawAllLayers(frame_data);
}
@@ -419,6 +435,7 @@ class LayerTreeHostImplTest : public testing::Test,
TestSharedBitmapManager shared_bitmap_manager_;
TestGpuMemoryBufferManager gpu_memory_buffer_manager_;
TestTaskGraphRunner task_graph_runner_;
+ scoped_ptr<OutputSurface> output_surface_;
scoped_ptr<LayerTreeHostImpl> host_impl_;
FakeRenderingStatsInstrumentation stats_instrumentation_;
bool on_can_draw_state_changed_called_;
@@ -655,6 +672,7 @@ TEST_F(LayerTreeHostImplTest, ScrollBlocksOnTouchEventHandlers) {
child_layer->SetPosition(gfx::PointF(0, 20));
child_layer->SetBounds(gfx::Size(50, 50));
scroll->AddChild(child_layer.Pass());
+ RebuildPropertyTrees();
}
// Touch handler regions determine whether touch events block scroll.
@@ -737,6 +755,7 @@ TEST_F(LayerTreeHostImplTest, ScrollBlocksOnLayerTopology) {
scrollable_child_1->SetHaveScrollEventHandlers(true);
scrollable_child_clip_1->AddChild(scrollable_child_1.Pass());
root_child->AddChild(scrollable_child_clip_1.Pass());
+ RebuildPropertyTrees();
}
LayerImpl* child2 = 0;
@@ -751,6 +770,7 @@ TEST_F(LayerTreeHostImplTest, ScrollBlocksOnLayerTopology) {
scrollable_child_2->SetHaveScrollEventHandlers(true);
scrollable_child_clip_2->AddChild(scrollable_child_2.Pass());
root_child->AddChild(scrollable_child_clip_2.Pass());
+ RebuildPropertyTrees();
}
// Scroll-blocks-on on a layer affects scrolls that hit that layer.
@@ -1052,22 +1072,118 @@ TEST_F(LayerTreeHostImplTest, ScrollWithUserUnscrollableLayers) {
host_impl_->ScrollBy(scroll_position, scroll_delta);
host_impl_->ScrollEnd();
- EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer->CurrentScrollOffset());
+ EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), scroll_layer->CurrentScrollOffset());
EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->CurrentScrollOffset());
overflow->set_user_scrollable_vertical(false);
EXPECT_EQ(InputHandler::SCROLL_STARTED,
host_impl_->ScrollBegin(scroll_position, InputHandler::WHEEL));
- EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer->CurrentScrollOffset());
+ EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), scroll_layer->CurrentScrollOffset());
EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->CurrentScrollOffset());
host_impl_->ScrollBy(scroll_position, scroll_delta);
host_impl_->ScrollEnd();
- EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 10), scroll_layer->CurrentScrollOffset());
+ EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), scroll_layer->CurrentScrollOffset());
EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->CurrentScrollOffset());
}
+TEST_F(LayerTreeHostImplTest, AnimationSchedulingPendingTree) {
+ host_impl_->SetViewportSize(gfx::Size(50, 50));
+
+ host_impl_->CreatePendingTree();
+ host_impl_->pending_tree()->SetRootLayer(
+ LayerImpl::Create(host_impl_->pending_tree(), 1));
+ LayerImpl* root = host_impl_->pending_tree()->root_layer();
+ root->SetBounds(gfx::Size(50, 50));
+ root->SetHasRenderSurface(true);
+
+ root->AddChild(LayerImpl::Create(host_impl_->pending_tree(), 2));
+ LayerImpl* child = root->children()[0];
+ child->SetBounds(gfx::Size(10, 10));
+ child->draw_properties().visible_layer_rect = gfx::Rect(10, 10);
+ child->SetDrawsContent(true);
+ AddAnimatedTransformToLayer(child, 10.0, 3, 0);
+
+ EXPECT_FALSE(did_request_animate_);
+ EXPECT_FALSE(did_request_redraw_);
+ EXPECT_FALSE(did_request_commit_);
+
+ host_impl_->Animate();
+
+ // An animation exists on the pending layer. Doing Animate() requests another
+ // frame.
+ // In reality, animations without has_set_start_time() == true do not need to
+ // be continuously ticked on the pending tree, so it should not request
+ // another animation frame here. But we currently do so blindly if any
+ // animation exists.
+ EXPECT_TRUE(did_request_animate_);
+ // The pending tree with an animation does not need to draw after animating.
+ EXPECT_FALSE(did_request_redraw_);
+ EXPECT_FALSE(did_request_commit_);
+
+ did_request_animate_ = false;
+ did_request_redraw_ = false;
+ did_request_commit_ = false;
+
+ host_impl_->ActivateSyncTree();
+
+ // When the animation activates, we should request another animation frame
+ // to keep the animation moving.
+ EXPECT_TRUE(did_request_animate_);
+ // On activation we don't need to request a redraw for the animation,
+ // activating will draw on its own when it's ready.
+ EXPECT_FALSE(did_request_redraw_);
+ EXPECT_FALSE(did_request_commit_);
+}
+
+TEST_F(LayerTreeHostImplTest, AnimationSchedulingActiveTree) {
+ host_impl_->SetViewportSize(gfx::Size(50, 50));
+
+ host_impl_->active_tree()->SetRootLayer(
+ LayerImpl::Create(host_impl_->active_tree(), 1));
+ LayerImpl* root = host_impl_->active_tree()->root_layer();
+ root->SetBounds(gfx::Size(50, 50));
+ root->SetHasRenderSurface(true);
+
+ root->AddChild(LayerImpl::Create(host_impl_->active_tree(), 2));
+ LayerImpl* child = root->children()[0];
+ child->SetBounds(gfx::Size(10, 10));
+ child->draw_properties().visible_layer_rect = gfx::Rect(10, 10);
+ child->SetDrawsContent(true);
+
+ // Add a translate from 6,7 to 8,9.
+ TransformOperations start;
+ start.AppendTranslate(6.f, 7.f, 0.f);
+ TransformOperations end;
+ end.AppendTranslate(8.f, 9.f, 0.f);
+ AddAnimatedTransformToLayer(child, 4.0, start, end);
+
+ base::TimeTicks now = base::TimeTicks::Now();
+ host_impl_->WillBeginImplFrame(
+ CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now));
+
+ EXPECT_FALSE(did_request_animate_);
+ EXPECT_FALSE(did_request_redraw_);
+ EXPECT_FALSE(did_request_commit_);
+
+ host_impl_->ActivateAnimations();
+ did_request_animate_ = false;
+ did_request_redraw_ = false;
+ did_request_commit_ = false;
+
+ host_impl_->Animate();
+
+ // An animation exists on the active layer. Doing Animate() requests another
+ // frame after the current one.
+ EXPECT_TRUE(did_request_animate_);
+ // TODO(danakj): We also need to draw in the current frame if something
+ // animated, but this is currently handled by
+ // SchedulerStateMachine::WillAnimate.
+ EXPECT_FALSE(did_request_redraw_);
+ EXPECT_FALSE(did_request_commit_);
+}
+
TEST_F(LayerTreeHostImplTest, ImplPinchZoom) {
LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
host_impl_->SetViewportSize(gfx::Size(50, 50));
@@ -1084,7 +1200,7 @@ TEST_F(LayerTreeHostImplTest, ImplPinchZoom) {
{
host_impl_->active_tree()->PushPageScaleFromMainThread(
page_scale_factor, min_page_scale, max_page_scale);
- host_impl_->SetPageScaleOnActiveTree(page_scale_factor);
+ host_impl_->active_tree()->SetPageScaleOnActiveTree(page_scale_factor);
scroll_layer->SetScrollDelta(gfx::Vector2d());
float page_scale_delta = 2.f;
@@ -1112,7 +1228,7 @@ TEST_F(LayerTreeHostImplTest, ImplPinchZoom) {
{
host_impl_->active_tree()->PushPageScaleFromMainThread(
page_scale_factor, min_page_scale, max_page_scale);
- host_impl_->SetPageScaleOnActiveTree(page_scale_factor);
+ host_impl_->active_tree()->SetPageScaleOnActiveTree(page_scale_factor);
scroll_layer->SetScrollDelta(gfx::Vector2d());
float page_scale_delta = 2.f;
@@ -1136,11 +1252,11 @@ TEST_F(LayerTreeHostImplTest, ImplPinchZoom) {
}
}
-TEST_F(LayerTreeHostImplTest, ScrollDuringPinchScrollsInnerViewport) {
+TEST_F(LayerTreeHostImplTest, ViewportScrollOrder) {
LayerTreeSettings settings = DefaultSettings();
- settings.invert_viewport_scroll_order = true;
CreateHostImpl(settings,
CreateOutputSurface());
+ host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.25f, 4.f);
const gfx::Size content_size(1000, 1000);
const gfx::Size viewport_size(500, 500);
@@ -1153,19 +1269,102 @@ TEST_F(LayerTreeHostImplTest, ScrollDuringPinchScrollsInnerViewport) {
gfx::Vector2dF(500, 500),
outer_scroll_layer->MaxScrollOffset());
+ RebuildPropertyTrees();
host_impl_->ScrollBegin(gfx::Point(250, 250), InputHandler::GESTURE);
host_impl_->PinchGestureBegin();
- host_impl_->PinchGestureUpdate(2, gfx::Point(250, 250));
- host_impl_->ScrollBy(gfx::Point(250, 250), gfx::Vector2dF(10.f, 10.f));
+ host_impl_->PinchGestureUpdate(2.f, gfx::Point(0, 0));
host_impl_->PinchGestureEnd();
host_impl_->ScrollEnd();
+ // Sanity check - we're zoomed in, starting from the origin.
+ EXPECT_VECTOR_EQ(
+ gfx::Vector2dF(0, 0),
+ outer_scroll_layer->CurrentScrollOffset());
+ EXPECT_VECTOR_EQ(
+ gfx::Vector2dF(0, 0),
+ inner_scroll_layer->CurrentScrollOffset());
+
+ // Scroll down - only the inner viewport should scroll.
+ host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::GESTURE);
+ host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(100.f, 100.f));
+ host_impl_->ScrollEnd();
+
+ EXPECT_VECTOR_EQ(
+ gfx::Vector2dF(50, 50),
+ inner_scroll_layer->CurrentScrollOffset());
+ EXPECT_VECTOR_EQ(
+ gfx::Vector2dF(0, 0),
+ outer_scroll_layer->CurrentScrollOffset());
+
+ // Scroll down - outer viewport should start scrolling after the inner is at
+ // its maximum.
+ host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::GESTURE);
+ host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(1000.f, 1000.f));
+ host_impl_->ScrollEnd();
+
+ EXPECT_VECTOR_EQ(
+ gfx::Vector2dF(250, 250),
+ inner_scroll_layer->CurrentScrollOffset());
+ EXPECT_VECTOR_EQ(
+ gfx::Vector2dF(300, 300),
+ outer_scroll_layer->CurrentScrollOffset());
+}
+
+// Tests that scrolls during a pinch gesture (i.e. "two-finger" scrolls) work
+// as expected. That is, scrolling during a pinch should bubble from the inner
+// to the outer viewport.
+TEST_F(LayerTreeHostImplTest, ScrollDuringPinchGesture) {
+ LayerTreeSettings settings = DefaultSettings();
+ CreateHostImpl(settings,
+ CreateOutputSurface());
+ host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 2.f);
+
+ const gfx::Size content_size(1000, 1000);
+ const gfx::Size viewport_size(500, 500);
+ CreateBasicVirtualViewportLayers(viewport_size, content_size);
+
+ LayerImpl* outer_scroll_layer = host_impl_->OuterViewportScrollLayer();
+ LayerImpl* inner_scroll_layer = host_impl_->InnerViewportScrollLayer();
+
+ EXPECT_VECTOR_EQ(
+ gfx::Vector2dF(500, 500),
+ outer_scroll_layer->MaxScrollOffset());
+
+ RebuildPropertyTrees();
+ host_impl_->ScrollBegin(gfx::Point(250, 250), InputHandler::GESTURE);
+ host_impl_->PinchGestureBegin();
+
+ host_impl_->PinchGestureUpdate(2, gfx::Point(250, 250));
+ EXPECT_VECTOR_EQ(
+ gfx::Vector2dF(0, 0),
+ outer_scroll_layer->CurrentScrollOffset());
+ EXPECT_VECTOR_EQ(
+ gfx::Vector2dF(125, 125),
+ inner_scroll_layer->CurrentScrollOffset());
+
+ // Needed so that the pinch is accounted for in draw properties.
+ DrawFrame();
+
+ host_impl_->ScrollBy(gfx::Point(250, 250), gfx::Vector2dF(10.f, 10.f));
EXPECT_VECTOR_EQ(
gfx::Vector2dF(0, 0),
outer_scroll_layer->CurrentScrollOffset());
EXPECT_VECTOR_EQ(
gfx::Vector2dF(130, 130),
inner_scroll_layer->CurrentScrollOffset());
+
+ DrawFrame();
+
+ host_impl_->ScrollBy(gfx::Point(250, 250), gfx::Vector2dF(400.f, 400.f));
+ EXPECT_VECTOR_EQ(
+ gfx::Vector2dF(80, 80),
+ outer_scroll_layer->CurrentScrollOffset());
+ EXPECT_VECTOR_EQ(
+ gfx::Vector2dF(250, 250),
+ inner_scroll_layer->CurrentScrollOffset());
+
+ host_impl_->PinchGestureEnd();
+ host_impl_->ScrollEnd();
}
// Tests the "snapping" of pinch-zoom gestures to the screen edge. That is, when
@@ -1173,9 +1372,9 @@ TEST_F(LayerTreeHostImplTest, ScrollDuringPinchScrollsInnerViewport) {
// should assume the user means to scroll into the edge of the screen.
TEST_F(LayerTreeHostImplTest, PinchZoomSnapsToScreenEdge) {
LayerTreeSettings settings = DefaultSettings();
- settings.invert_viewport_scroll_order = true;
CreateHostImpl(settings,
CreateOutputSurface());
+ host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 2.f);
const gfx::Size content_size(1000, 1000);
const gfx::Size viewport_size(500, 500);
@@ -1187,6 +1386,7 @@ TEST_F(LayerTreeHostImplTest, PinchZoomSnapsToScreenEdge) {
// Pinch in within the margins. The scroll should stay exactly locked to the
// bottom and right.
+ RebuildPropertyTrees();
host_impl_->ScrollBegin(anchor, InputHandler::GESTURE);
host_impl_->PinchGestureBegin();
host_impl_->PinchGestureUpdate(2, anchor);
@@ -1264,11 +1464,12 @@ TEST_F(LayerTreeHostImplTest, ImplPinchZoomWheelBubbleBetweenViewports) {
// Zoom into the page by a 2X factor
float min_page_scale = 1.f, max_page_scale = 4.f;
float page_scale_factor = 2.f;
+ RebuildPropertyTrees();
host_impl_->active_tree()->PushPageScaleFromMainThread(
page_scale_factor, min_page_scale, max_page_scale);
- host_impl_->SetPageScaleOnActiveTree(page_scale_factor);
+ host_impl_->active_tree()->SetPageScaleOnActiveTree(page_scale_factor);
- // Scroll by a small amount, there should be no bubbling up to the inner
+ // Scroll by a small amount, there should be no bubbling to the outer
// viewport.
host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL);
host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(10.f, 20.f));
@@ -1276,28 +1477,28 @@ TEST_F(LayerTreeHostImplTest, ImplPinchZoomWheelBubbleBetweenViewports) {
EXPECT_VECTOR_EQ(
gfx::Vector2dF(5, 10),
- outer_scroll_layer->CurrentScrollOffset());
+ inner_scroll_layer->CurrentScrollOffset());
EXPECT_VECTOR_EQ(
gfx::Vector2dF(),
- inner_scroll_layer->CurrentScrollOffset());
+ outer_scroll_layer->CurrentScrollOffset());
- // Scroll by the outer viewport's max scroll extent, there the remainder
- // should bubble up to the inner viewport.
+ // Scroll by the inner viewport's max scroll extent, the remainder
+ // should bubble up to the outer viewport.
host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL);
- host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(200.f, 200.f));
+ host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(100.f, 100.f));
host_impl_->ScrollEnd();
EXPECT_VECTOR_EQ(
- gfx::Vector2dF(100, 100),
- outer_scroll_layer->CurrentScrollOffset());
+ gfx::Vector2dF(50, 50),
+ inner_scroll_layer->CurrentScrollOffset());
EXPECT_VECTOR_EQ(
gfx::Vector2dF(5, 10),
- inner_scroll_layer->CurrentScrollOffset());
+ outer_scroll_layer->CurrentScrollOffset());
- // Scroll by the inner viewport's max scroll extent, it should all go to the
- // inner viewport.
+ // Scroll by the outer viewport's max scroll extent, it should all go to the
+ // outer viewport.
host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL);
- host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(90.f, 80.f));
+ host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(190.f, 180.f));
host_impl_->ScrollEnd();
EXPECT_VECTOR_EQ(
@@ -1310,7 +1511,8 @@ TEST_F(LayerTreeHostImplTest, ImplPinchZoomWheelBubbleBetweenViewports) {
TEST_F(LayerTreeHostImplTest, ScrollWithSwapPromises) {
ui::LatencyInfo latency_info;
- latency_info.trace_id = 1234;
+ latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0,
+ 1234);
scoped_ptr<SwapPromise> swap_promise(
new LatencyInfoSwapPromise(latency_info));
@@ -1323,19 +1525,18 @@ TEST_F(LayerTreeHostImplTest, ScrollWithSwapPromises) {
scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
EXPECT_EQ(1u, scroll_info->swap_promises.size());
- EXPECT_EQ(latency_info.trace_id, scroll_info->swap_promises[0]->TraceId());
+ EXPECT_EQ(latency_info.trace_id(), scroll_info->swap_promises[0]->TraceId());
}
-// Test that scrolls targeting a layer with a non-null scroll_parent() bubble
-// up to the scroll_parent, rather than the stacking parent.
-TEST_F(LayerTreeHostImplTest, ScrollBubblesToScrollParent) {
+// Test that scrolls targeting a layer with a non-null scroll_parent() don't
+// bubble up.
+TEST_F(LayerTreeHostImplTest, ScrollDoesntBubble) {
LayerImpl* viewport_scroll =
SetupScrollAndContentsLayers(gfx::Size(100, 100));
host_impl_->SetViewportSize(gfx::Size(50, 50));
// Set up two scrolling children of the root, one of which is a scroll parent
- // to the other. Scrolls bubbling from the child should bubble to the parent,
- // not the viewport.
+ // to the other. Scrolls shouldn't bubbling from the child.
LayerImpl *parent;
LayerImpl *child;
LayerImpl *child_clip;
@@ -1361,20 +1562,23 @@ TEST_F(LayerTreeHostImplTest, ScrollBubblesToScrollParent) {
viewport_scroll->AddChild(scroll_child_clip.Pass());
child_clip->SetScrollParent(parent);
+ scoped_ptr<std::set<LayerImpl*>> scroll_children(new std::set<LayerImpl*>);
+ scroll_children->insert(child_clip);
+ parent->SetScrollChildren(scroll_children.release());
DrawFrame();
{
host_impl_->ScrollBegin(gfx::Point(21, 21), InputHandler::GESTURE);
host_impl_->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(5, 5));
- host_impl_->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(2, 1));
+ host_impl_->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(100, 100));
host_impl_->ScrollEnd();
// The child should be fully scrolled by the first ScrollBy.
EXPECT_VECTOR_EQ(gfx::Vector2dF(5, 5), child->CurrentScrollOffset());
- // The scroll_parent should receive the bubbled up second ScrollBy.
- EXPECT_VECTOR_EQ(gfx::Vector2dF(2, 1), parent->CurrentScrollOffset());
+ // The scroll_parent shouldn't receive the second ScrollBy.
+ EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), parent->CurrentScrollOffset());
// The viewport shouldn't have been scrolled at all.
EXPECT_VECTOR_EQ(
@@ -1389,14 +1593,16 @@ TEST_F(LayerTreeHostImplTest, ScrollBubblesToScrollParent) {
host_impl_->ScrollBegin(gfx::Point(21, 21), InputHandler::GESTURE);
host_impl_->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(3, 4));
host_impl_->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(2, 1));
+ host_impl_->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(2, 1));
+ host_impl_->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(2, 1));
host_impl_->ScrollEnd();
- // The first ScrollBy should scroll the parent to its extent.
+ // The ScrollBy's should scroll the parent to its extent.
EXPECT_VECTOR_EQ(gfx::Vector2dF(5, 5), parent->CurrentScrollOffset());
- // The viewport should now be next in bubbling order.
+ // The viewport shouldn't receive any scroll delta.
EXPECT_VECTOR_EQ(
- gfx::Vector2dF(2, 1),
+ gfx::Vector2dF(0, 0),
host_impl_->InnerViewportScrollLayer()->CurrentScrollOffset());
EXPECT_VECTOR_EQ(
gfx::Vector2dF(0, 0),
@@ -1534,6 +1740,10 @@ TEST_F(LayerTreeHostImplTest, PinchGesture) {
host_impl_->PinchGestureBegin();
host_impl_->PinchGestureUpdate(2.f, gfx::Point(0, 0));
host_impl_->PinchGestureUpdate(1.f, gfx::Point(0, 0));
+
+ // Needed so layer transform includes page scale.
+ DrawFrame();
+
host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2d(10, 10));
host_impl_->PinchGestureUpdate(1.f, gfx::Point(10, 10));
host_impl_->PinchGestureEnd();
@@ -1543,7 +1753,7 @@ TEST_F(LayerTreeHostImplTest, PinchGesture) {
host_impl_->ProcessScrollDeltas();
EXPECT_EQ(scroll_info->page_scale_delta, 2.f);
EXPECT_TRUE(ScrollInfoContains(*scroll_info, scroll_layer->id(),
- gfx::Vector2d(20, 20)));
+ gfx::Vector2d(10, 10)));
}
}
@@ -1563,6 +1773,9 @@ TEST_F(LayerTreeHostImplTest, PageScaleAnimation) {
base::TimeTicks halfway_through_animation = start_time + duration / 2;
base::TimeTicks end_time = start_time + duration;
+ BeginFrameArgs begin_frame_args =
+ CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
+
// Non-anchor zoom-in
{
host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
@@ -1583,22 +1796,31 @@ TEST_F(LayerTreeHostImplTest, PageScaleAnimation) {
did_request_redraw_ = false;
did_request_animate_ = false;
- host_impl_->Animate(start_time);
+ begin_frame_args.frame_time = start_time;
+ host_impl_->WillBeginImplFrame(begin_frame_args);
+ host_impl_->Animate();
EXPECT_TRUE(did_request_redraw_);
EXPECT_TRUE(did_request_animate_);
+ host_impl_->DidFinishImplFrame();
did_request_redraw_ = false;
did_request_animate_ = false;
- host_impl_->Animate(halfway_through_animation);
+ begin_frame_args.frame_time = halfway_through_animation;
+ host_impl_->WillBeginImplFrame(begin_frame_args);
+ host_impl_->Animate();
EXPECT_TRUE(did_request_redraw_);
EXPECT_TRUE(did_request_animate_);
+ host_impl_->DidFinishImplFrame();
did_request_redraw_ = false;
did_request_animate_ = false;
did_request_commit_ = false;
- host_impl_->Animate(end_time);
+ begin_frame_args.frame_time = end_time;
+ host_impl_->WillBeginImplFrame(begin_frame_args);
+ host_impl_->Animate();
EXPECT_TRUE(did_request_commit_);
EXPECT_FALSE(did_request_animate_);
+ host_impl_->DidFinishImplFrame();
scoped_ptr<ScrollAndScaleSet> scroll_info =
host_impl_->ProcessScrollDeltas();
@@ -1607,6 +1829,10 @@ TEST_F(LayerTreeHostImplTest, PageScaleAnimation) {
gfx::Vector2d(-50, -50)));
}
+ start_time += base::TimeDelta::FromSeconds(10);
+ halfway_through_animation += base::TimeDelta::FromSeconds(10);
+ end_time += base::TimeDelta::FromSeconds(10);
+
// Anchor zoom-out
{
host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
@@ -1627,17 +1853,23 @@ TEST_F(LayerTreeHostImplTest, PageScaleAnimation) {
did_request_redraw_ = false;
did_request_animate_ = false;
- host_impl_->Animate(start_time);
+ begin_frame_args.frame_time = start_time;
+ host_impl_->WillBeginImplFrame(begin_frame_args);
+ host_impl_->Animate();
EXPECT_TRUE(did_request_redraw_);
EXPECT_TRUE(did_request_animate_);
+ host_impl_->DidFinishImplFrame();
did_request_redraw_ = false;
did_request_commit_ = false;
did_request_animate_ = false;
- host_impl_->Animate(end_time);
+ begin_frame_args.frame_time = end_time;
+ host_impl_->WillBeginImplFrame(begin_frame_args);
+ host_impl_->Animate();
EXPECT_TRUE(did_request_redraw_);
EXPECT_FALSE(did_request_animate_);
EXPECT_TRUE(did_request_commit_);
+ host_impl_->DidFinishImplFrame();
scoped_ptr<ScrollAndScaleSet> scroll_info =
host_impl_->ProcessScrollDeltas();
@@ -1664,6 +1896,9 @@ TEST_F(LayerTreeHostImplTest, PageScaleAnimationNoOp) {
base::TimeTicks halfway_through_animation = start_time + duration / 2;
base::TimeTicks end_time = start_time + duration;
+ BeginFrameArgs begin_frame_args =
+ CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
+
// Anchor zoom with unchanged page scale should not change scroll or scale.
{
host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
@@ -1677,11 +1912,22 @@ TEST_F(LayerTreeHostImplTest, PageScaleAnimationNoOp) {
1.f,
duration)));
host_impl_->ActivateSyncTree();
- host_impl_->Animate(start_time);
- host_impl_->Animate(halfway_through_animation);
+ begin_frame_args.frame_time = start_time;
+ host_impl_->WillBeginImplFrame(begin_frame_args);
+ host_impl_->Animate();
+ host_impl_->DidFinishImplFrame();
+
+ begin_frame_args.frame_time = halfway_through_animation;
+ host_impl_->WillBeginImplFrame(begin_frame_args);
+ host_impl_->Animate();
EXPECT_TRUE(did_request_redraw_);
- host_impl_->Animate(end_time);
+ host_impl_->DidFinishImplFrame();
+
+ begin_frame_args.frame_time = end_time;
+ host_impl_->WillBeginImplFrame(begin_frame_args);
+ host_impl_->Animate();
EXPECT_TRUE(did_request_commit_);
+ host_impl_->DidFinishImplFrame();
scoped_ptr<ScrollAndScaleSet> scroll_info =
host_impl_->ProcessScrollDeltas();
@@ -1692,6 +1938,7 @@ TEST_F(LayerTreeHostImplTest, PageScaleAnimationNoOp) {
TEST_F(LayerTreeHostImplTest, PageScaleAnimationTransferedOnSyncTreeActivate) {
host_impl_->CreatePendingTree();
+ host_impl_->pending_tree()->PushPageScaleFromMainThread(1.f, 1.f, 1.f);
CreateScrollAndContentsLayers(
host_impl_->pending_tree(),
gfx::Size(100, 100));
@@ -1715,6 +1962,9 @@ TEST_F(LayerTreeHostImplTest, PageScaleAnimationTransferedOnSyncTreeActivate) {
base::TimeTicks end_time = start_time + duration;
float target_scale = 2.f;
+ BeginFrameArgs begin_frame_args =
+ CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
+
scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
// Make sure TakePageScaleAnimation works properly.
@@ -1741,9 +1991,12 @@ TEST_F(LayerTreeHostImplTest, PageScaleAnimationTransferedOnSyncTreeActivate) {
false,
target_scale,
duration)));
- host_impl_->Animate(halfway_through_animation);
+ begin_frame_args.frame_time = halfway_through_animation;
+ host_impl_->WillBeginImplFrame(begin_frame_args);
+ host_impl_->Animate();
EXPECT_FALSE(did_request_animate_);
EXPECT_FALSE(did_request_redraw_);
+ host_impl_->DidFinishImplFrame();
// Activate the sync tree. This should cause the animation to become enabled.
// It should also clear the pointer on the sync tree.
@@ -1753,34 +2006,51 @@ TEST_F(LayerTreeHostImplTest, PageScaleAnimationTransferedOnSyncTreeActivate) {
EXPECT_FALSE(did_request_redraw_);
EXPECT_TRUE(did_request_animate_);
+ start_time += base::TimeDelta::FromSeconds(10);
+ third_through_animation += base::TimeDelta::FromSeconds(10);
+ halfway_through_animation += base::TimeDelta::FromSeconds(10);
+ end_time += base::TimeDelta::FromSeconds(10);
+
// From here on, make sure the animation runs as normal.
did_request_redraw_ = false;
did_request_animate_ = false;
- host_impl_->Animate(start_time);
+ begin_frame_args.frame_time = start_time;
+ host_impl_->WillBeginImplFrame(begin_frame_args);
+ host_impl_->Animate();
EXPECT_TRUE(did_request_redraw_);
EXPECT_TRUE(did_request_animate_);
+ host_impl_->DidFinishImplFrame();
did_request_redraw_ = false;
did_request_animate_ = false;
- host_impl_->Animate(third_through_animation);
+ begin_frame_args.frame_time = third_through_animation;
+ host_impl_->WillBeginImplFrame(begin_frame_args);
+ host_impl_->Animate();
EXPECT_TRUE(did_request_redraw_);
EXPECT_TRUE(did_request_animate_);
+ host_impl_->DidFinishImplFrame();
// Another activation shouldn't have any effect on the animation.
host_impl_->ActivateSyncTree();
did_request_redraw_ = false;
did_request_animate_ = false;
- host_impl_->Animate(halfway_through_animation);
+ begin_frame_args.frame_time = halfway_through_animation;
+ host_impl_->WillBeginImplFrame(begin_frame_args);
+ host_impl_->Animate();
EXPECT_TRUE(did_request_redraw_);
EXPECT_TRUE(did_request_animate_);
+ host_impl_->DidFinishImplFrame();
did_request_redraw_ = false;
did_request_animate_ = false;
did_request_commit_ = false;
- host_impl_->Animate(end_time);
+ begin_frame_args.frame_time = end_time;
+ host_impl_->WillBeginImplFrame(begin_frame_args);
+ host_impl_->Animate();
EXPECT_TRUE(did_request_commit_);
EXPECT_FALSE(did_request_animate_);
+ host_impl_->DidFinishImplFrame();
scoped_ptr<ScrollAndScaleSet> scroll_info =
host_impl_->ProcessScrollDeltas();
@@ -1803,6 +2073,9 @@ TEST_F(LayerTreeHostImplTest, PageScaleAnimationCompletedNotification) {
base::TimeTicks halfway_through_animation = start_time + duration / 2;
base::TimeTicks end_time = start_time + duration;
+ BeginFrameArgs begin_frame_args =
+ CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
+
host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
@@ -1811,14 +2084,23 @@ TEST_F(LayerTreeHostImplTest, PageScaleAnimationCompletedNotification) {
scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
gfx::Vector2d(), false, 2.f, duration)));
host_impl_->ActivateSyncTree();
- host_impl_->Animate(start_time);
+ begin_frame_args.frame_time = start_time;
+ host_impl_->WillBeginImplFrame(begin_frame_args);
+ host_impl_->Animate();
EXPECT_FALSE(did_complete_page_scale_animation_);
+ host_impl_->DidFinishImplFrame();
- host_impl_->Animate(halfway_through_animation);
+ begin_frame_args.frame_time = halfway_through_animation;
+ host_impl_->WillBeginImplFrame(begin_frame_args);
+ host_impl_->Animate();
EXPECT_FALSE(did_complete_page_scale_animation_);
+ host_impl_->DidFinishImplFrame();
- host_impl_->Animate(end_time);
+ begin_frame_args.frame_time = end_time;
+ host_impl_->WillBeginImplFrame(begin_frame_args);
+ host_impl_->Animate();
EXPECT_TRUE(did_complete_page_scale_animation_);
+ host_impl_->DidFinishImplFrame();
}
class LayerTreeHostImplOverridePhysicalTime : public LayerTreeHostImpl {
@@ -1855,7 +2137,6 @@ class LayerTreeHostImplOverridePhysicalTime : public LayerTreeHostImpl {
class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest {
protected:
void SetupLayers(LayerTreeSettings settings) {
- gfx::Size viewport_size(10, 10);
gfx::Size content_size(100, 100);
LayerTreeHostImplOverridePhysicalTime* host_impl_override_time =
@@ -1863,40 +2144,24 @@ class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest {
settings, this, &proxy_, &shared_bitmap_manager_,
&task_graph_runner_, &stats_instrumentation_);
host_impl_ = make_scoped_ptr(host_impl_override_time);
- host_impl_->InitializeRenderer(CreateOutputSurface());
- host_impl_->SetViewportSize(viewport_size);
-
- scoped_ptr<LayerImpl> root =
- LayerImpl::Create(host_impl_->active_tree(), 1);
- root->SetBounds(viewport_size);
+ output_surface_ = CreateOutputSurface();
+ host_impl_->InitializeRenderer(output_surface_.get());
- scoped_ptr<LayerImpl> scroll =
- LayerImpl::Create(host_impl_->active_tree(), 2);
- scroll->SetScrollClipLayer(root->id());
- scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
- root->SetBounds(viewport_size);
- scroll->SetBounds(content_size);
- scroll->SetIsContainerForFixedPositionLayers(true);
-
- scoped_ptr<LayerImpl> contents =
- LayerImpl::Create(host_impl_->active_tree(), 3);
- contents->SetDrawsContent(true);
- contents->SetBounds(content_size);
+ SetupScrollAndContentsLayers(content_size);
+ host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 4.f);
+ host_impl_->SetViewportSize(
+ gfx::Size(content_size.width() / 2, content_size.height() / 2));
scoped_ptr<SolidColorScrollbarLayerImpl> scrollbar =
- SolidColorScrollbarLayerImpl::Create(host_impl_->active_tree(), 4,
+ SolidColorScrollbarLayerImpl::Create(host_impl_->active_tree(), 400,
VERTICAL, 10, 0, false, true);
EXPECT_FLOAT_EQ(0.f, scrollbar->opacity());
- scroll->AddChild(contents.Pass());
- root->AddChild(scroll.Pass());
- root->SetHasRenderSurface(true);
- scrollbar->SetScrollLayerAndClipLayerByIds(2, 1);
+ LayerImpl* scroll = host_impl_->InnerViewportScrollLayer();
+ LayerImpl* root = scroll->parent()->parent();
+ scrollbar->SetScrollLayerAndClipLayerByIds(scroll->id(), root->id());
root->AddChild(scrollbar.Pass());
- host_impl_->active_tree()->SetRootLayer(root.Pass());
- host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
- Layer::INVALID_ID);
host_impl_->active_tree()->DidBecomeActive();
DrawFrame();
}
@@ -1950,13 +2215,17 @@ class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest {
EXPECT_FALSE(did_request_redraw_);
// After the scrollbar animation begins, we should start getting redraws.
- host_impl_->Animate(fake_now);
+ BeginFrameArgs begin_frame_args =
+ CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, fake_now);
+ host_impl_->WillBeginImplFrame(begin_frame_args);
+ host_impl_->Animate();
EXPECT_TRUE(did_request_animate_);
did_request_animate_ = false;
EXPECT_TRUE(did_request_redraw_);
did_request_redraw_ = false;
EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
EXPECT_TRUE(animation_task_.Equals(base::Closure()));
+ host_impl_->DidFinishImplFrame();
// Setting the scroll offset outside a scroll should also cause the
// scrollbar to appear and to schedule a scrollbar animation.
@@ -1987,7 +2256,7 @@ class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest {
// Changing page scale triggers scrollbar animation.
host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 4.f);
- host_impl_->SetPageScaleOnActiveTree(1.1f);
+ host_impl_->active_tree()->SetPageScaleOnActiveTree(1.1f);
EXPECT_FALSE(did_request_animate_);
EXPECT_FALSE(did_request_redraw_);
EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
@@ -2006,6 +2275,64 @@ TEST_F(LayerTreeHostImplTestScrollbarAnimation, Thinning) {
RunTest(LayerTreeSettings::THINNING);
}
+class LayerTreeHostImplTestScrollbarOpacity : public LayerTreeHostImplTest {
+ protected:
+ void RunTest(LayerTreeSettings::ScrollbarAnimator animator) {
+ LayerTreeSettings settings;
+ settings.scrollbar_animator = animator;
+ settings.scrollbar_fade_delay_ms = 20;
+ settings.scrollbar_fade_duration_ms = 20;
+ settings.verify_property_trees = true;
+ gfx::Size content_size(100, 100);
+
+ CreateHostImpl(settings, CreateOutputSurface());
+ host_impl_->CreatePendingTree();
+ CreateScrollAndContentsLayers(host_impl_->pending_tree(), content_size);
+ scoped_ptr<SolidColorScrollbarLayerImpl> scrollbar =
+ SolidColorScrollbarLayerImpl::Create(host_impl_->pending_tree(), 400,
+ VERTICAL, 10, 0, false, true);
+ LayerImpl* scroll = host_impl_->pending_tree()->InnerViewportScrollLayer();
+ LayerImpl* root = scroll->parent()->parent();
+ scrollbar->SetScrollLayerAndClipLayerByIds(scroll->id(), root->id());
+ root->AddChild(scrollbar.Pass());
+ host_impl_->pending_tree()->PushPageScaleFromMainThread(1.f, 1.f, 1.f);
+ host_impl_->pending_tree()->BuildPropertyTreesForTesting();
+ host_impl_->ActivateSyncTree();
+
+ LayerImpl* scrollbar_layer = host_impl_->active_tree()->LayerById(400);
+
+ EffectNode* active_tree_node =
+ host_impl_->active_tree()->property_trees()->effect_tree.Node(
+ scrollbar_layer->effect_tree_index());
+ EXPECT_FLOAT_EQ(scrollbar_layer->opacity(), active_tree_node->data.opacity);
+
+ host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL);
+ host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 5));
+ host_impl_->ScrollEnd();
+ host_impl_->CreatePendingTree();
+ EffectNode* pending_tree_node =
+ host_impl_->pending_tree()->property_trees()->effect_tree.Node(
+ scrollbar_layer->effect_tree_index());
+ EXPECT_FLOAT_EQ(1.f, active_tree_node->data.opacity);
+ EXPECT_FLOAT_EQ(1.f, scrollbar_layer->opacity());
+ EXPECT_FLOAT_EQ(0.f, pending_tree_node->data.opacity);
+ host_impl_->ActivateSyncTree();
+ active_tree_node =
+ host_impl_->active_tree()->property_trees()->effect_tree.Node(
+ scrollbar_layer->effect_tree_index());
+ EXPECT_FLOAT_EQ(1.f, active_tree_node->data.opacity);
+ EXPECT_FLOAT_EQ(1.f, scrollbar_layer->opacity());
+ }
+};
+
+TEST_F(LayerTreeHostImplTestScrollbarOpacity, LinearFade) {
+ RunTest(LayerTreeSettings::LINEAR_FADE);
+}
+
+TEST_F(LayerTreeHostImplTestScrollbarOpacity, Thinning) {
+ RunTest(LayerTreeSettings::THINNING);
+}
+
void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale(
float device_scale_factor) {
LayerTreeSettings settings;
@@ -2014,12 +2341,12 @@ void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale(
settings.scrollbar_animator = LayerTreeSettings::THINNING;
gfx::Size viewport_size(300, 200);
- gfx::Size device_viewport_size = gfx::ToFlooredSize(
- gfx::ScaleSize(viewport_size, device_scale_factor));
+ gfx::Size device_viewport_size =
+ gfx::ScaleToFlooredSize(viewport_size, device_scale_factor);
gfx::Size content_size(1000, 1000);
CreateHostImpl(settings, CreateOutputSurface());
- host_impl_->SetDeviceScaleFactor(device_scale_factor);
+ host_impl_->active_tree()->SetDeviceScaleFactor(device_scale_factor);
host_impl_->SetViewportSize(device_viewport_size);
scoped_ptr<LayerImpl> root =
@@ -2149,6 +2476,39 @@ TEST_F(LayerTreeHostImplTest, CompositorFrameMetadata) {
EXPECT_TRUE(metadata.root_overflow_y_hidden);
}
+ // Re-enable scrollability and verify that overflows are no longer hidden.
+ {
+ host_impl_->active_tree()
+ ->OuterViewportScrollLayer()
+ ->set_user_scrollable_horizontal(true);
+ host_impl_->active_tree()
+ ->OuterViewportScrollLayer()
+ ->set_user_scrollable_vertical(true);
+ CompositorFrameMetadata metadata =
+ host_impl_->MakeCompositorFrameMetadata();
+ EXPECT_FALSE(metadata.root_overflow_x_hidden);
+ EXPECT_FALSE(metadata.root_overflow_y_hidden);
+ }
+
+ // Root "overflow: hidden" properties should also be reflected on the
+ // inner viewport scroll layer.
+ {
+ host_impl_->active_tree()
+ ->InnerViewportScrollLayer()
+ ->set_user_scrollable_horizontal(false);
+ CompositorFrameMetadata metadata =
+ host_impl_->MakeCompositorFrameMetadata();
+ EXPECT_TRUE(metadata.root_overflow_x_hidden);
+ EXPECT_FALSE(metadata.root_overflow_y_hidden);
+
+ host_impl_->active_tree()
+ ->InnerViewportScrollLayer()
+ ->set_user_scrollable_vertical(false);
+ metadata = host_impl_->MakeCompositorFrameMetadata();
+ EXPECT_TRUE(metadata.root_overflow_x_hidden);
+ EXPECT_TRUE(metadata.root_overflow_y_hidden);
+ }
+
// Page scale should update metadata correctly (shrinking only the viewport).
host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
host_impl_->PinchGestureBegin();
@@ -2169,7 +2529,7 @@ TEST_F(LayerTreeHostImplTest, CompositorFrameMetadata) {
// Likewise if set from the main thread.
host_impl_->ProcessScrollDeltas();
host_impl_->active_tree()->PushPageScaleFromMainThread(4.f, 0.5f, 4.f);
- host_impl_->SetPageScaleOnActiveTree(4.f);
+ host_impl_->active_tree()->SetPageScaleOnActiveTree(4.f);
{
CompositorFrameMetadata metadata =
host_impl_->MakeCompositorFrameMetadata();
@@ -2262,7 +2622,7 @@ TEST_F(LayerTreeHostImplTest, WillDrawReturningFalseDoesNotCall) {
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
host_impl_->DidDrawAllLayers(frame);
@@ -2279,7 +2639,7 @@ TEST_F(LayerTreeHostImplTest, WillDrawReturningFalseDoesNotCall) {
layer->set_will_draw_returns_false();
layer->ClearDidDrawCheck();
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
host_impl_->DidDrawAllLayers(frame);
@@ -2310,7 +2670,8 @@ TEST_F(LayerTreeHostImplTest, DidDrawNotCalledOnHiddenLayer) {
EXPECT_FALSE(layer->will_draw_called());
EXPECT_FALSE(layer->did_draw_called());
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ host_impl_->active_tree()->BuildPropertyTreesForTesting();
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
host_impl_->DidDrawAllLayers(frame);
@@ -2325,7 +2686,7 @@ TEST_F(LayerTreeHostImplTest, DidDrawNotCalledOnHiddenLayer) {
EXPECT_FALSE(layer->will_draw_called());
EXPECT_FALSE(layer->did_draw_called());
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
host_impl_->DidDrawAllLayers(frame);
@@ -2364,7 +2725,7 @@ TEST_F(LayerTreeHostImplTest, WillDrawNotCalledOnOccludedLayer) {
EXPECT_FALSE(top_layer->will_draw_called());
EXPECT_FALSE(top_layer->did_draw_called());
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
host_impl_->DidDrawAllLayers(frame);
@@ -2399,7 +2760,7 @@ TEST_F(LayerTreeHostImplTest, DidDrawCalledOnAllLayers) {
LayerTreeHostImpl::FrameData frame;
FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
host_impl_->active_tree()->root_layer());
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
host_impl_->DidDrawAllLayers(frame);
@@ -2549,7 +2910,7 @@ TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsAndFails) {
root->SetHasRenderSurface(true);
LayerTreeHostImpl::FrameData frame;
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
host_impl_->DidDrawAllLayers(frame);
host_impl_->SwapBuffers(frame);
@@ -2597,7 +2958,7 @@ TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsAndFails) {
host_impl_->SetRequiresHighResToDraw();
LayerTreeHostImpl::FrameData frame;
- EXPECT_EQ(testcase.expected_result, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(testcase.expected_result, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
host_impl_->DidDrawAllLayers(frame);
host_impl_->SwapBuffers(frame);
@@ -2636,7 +2997,7 @@ TEST_F(LayerTreeHostImplTest,
root->SetHasRenderSurface(true);
LayerTreeHostImpl::FrameData frame;
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
host_impl_->DidDrawAllLayers(frame);
host_impl_->SwapBuffers(frame);
@@ -2684,7 +3045,7 @@ TEST_F(LayerTreeHostImplTest,
host_impl_->SetRequiresHighResToDraw();
LayerTreeHostImpl::FrameData frame;
- EXPECT_EQ(testcase.expected_result, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(testcase.expected_result, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
host_impl_->DidDrawAllLayers(frame);
host_impl_->SwapBuffers(frame);
@@ -2707,6 +3068,7 @@ TEST_F(LayerTreeHostImplTest, ScrollRootIgnored) {
TEST_F(LayerTreeHostImplTest, ClampingAfterActivation) {
host_impl_->CreatePendingTree();
+ host_impl_->pending_tree()->PushPageScaleFromMainThread(1.f, 1.f, 1.f);
CreateScrollAndContentsLayers(host_impl_->pending_tree(),
gfx::Size(100, 100));
host_impl_->ActivateSyncTree();
@@ -2724,7 +3086,6 @@ TEST_F(LayerTreeHostImplTest, ClampingAfterActivation) {
EXPECT_EQ(active_outer_layer->CurrentScrollOffset(), gfx::ScrollOffset(0, 0));
}
-// TODO(bokan): Convert these tests to create inner and outer viewports.
class LayerTreeHostImplTopControlsTest : public LayerTreeHostImplTest {
public:
LayerTreeHostImplTopControlsTest()
@@ -2744,63 +3105,11 @@ class LayerTreeHostImplTopControlsTest : public LayerTreeHostImplTest {
if (init) {
host_impl_->active_tree()->set_top_controls_height(top_controls_height_);
host_impl_->active_tree()->SetCurrentTopControlsShownRatio(1.f);
+ host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 1.f);
}
return init;
}
- void SetupTopControlsAndScrollLayer() {
- scoped_ptr<LayerImpl> root =
- LayerImpl::Create(host_impl_->active_tree(), 1);
- scoped_ptr<LayerImpl> root_clip =
- LayerImpl::Create(host_impl_->active_tree(), 2);
- root_clip->SetBounds(clip_size_);
- root->SetScrollClipLayer(root_clip->id());
- root->SetBounds(layer_size_);
- root->SetPosition(gfx::PointF());
- root->SetDrawsContent(false);
- root->SetIsContainerForFixedPositionLayers(true);
- int inner_viewport_scroll_layer_id = root->id();
- int page_scale_layer_id = root_clip->id();
- root_clip->SetHasRenderSurface(true);
- root_clip->AddChild(root.Pass());
- root_clip->SetHasRenderSurface(true);
- host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
- host_impl_->active_tree()->SetViewportLayersFromIds(
- Layer::INVALID_ID, page_scale_layer_id, inner_viewport_scroll_layer_id,
- Layer::INVALID_ID);
- // Set a viewport size that is large enough to contain both the top controls
- // and some content.
- host_impl_->SetViewportSize(viewport_size_);
- host_impl_->sync_tree()->set_top_controls_shrink_blink_size(true);
-
- host_impl_->DidChangeTopControlsPosition();
-
- host_impl_->CreatePendingTree();
- host_impl_->sync_tree()->set_top_controls_height(top_controls_height_);
- root =
- LayerImpl::Create(host_impl_->sync_tree(), 1);
- root_clip =
- LayerImpl::Create(host_impl_->sync_tree(), 2);
- root_clip->SetBounds(clip_size_);
- root->SetScrollClipLayer(root_clip->id());
- root->SetBounds(layer_size_);
- root->SetPosition(gfx::PointF());
- root->SetDrawsContent(false);
- root->SetIsContainerForFixedPositionLayers(true);
- inner_viewport_scroll_layer_id = root->id();
- page_scale_layer_id = root_clip->id();
- root_clip->AddChild(root.Pass());
- host_impl_->sync_tree()->SetRootLayer(root_clip.Pass());
- host_impl_->sync_tree()->SetViewportLayersFromIds(
- Layer::INVALID_ID, page_scale_layer_id, inner_viewport_scroll_layer_id,
- Layer::INVALID_ID);
- // Set a viewport size that is large enough to contain both the top controls
- // and some content.
- host_impl_->SetViewportSize(viewport_size_);
- host_impl_->sync_tree()->set_top_controls_shrink_blink_size(true);
- host_impl_->DidChangeTopControlsPosition();
- }
-
void SetupTopControlsAndScrollLayerWithVirtualViewport(
const gfx::Size& inner_viewport_size,
const gfx::Size& outer_viewport_size,
@@ -2864,6 +3173,73 @@ class LayerTreeHostImplTopControlsTest : public LayerTreeHostImplTest {
LayerTreeSettings settings_;
}; // class LayerTreeHostImplTopControlsTest
+// Tests that, on a page with content the same size as the viewport, hiding
+// the top controls also increases the ScrollableSize (i.e. the content size).
+// Since the viewport got larger, the effective scrollable "content" also did.
+// This ensures, for one thing, that the overscroll glow is shown in the right
+// place.
+TEST_F(LayerTreeHostImplTopControlsTest,
+ HidingTopControlsExpandsScrollableSize) {
+ SetupTopControlsAndScrollLayerWithVirtualViewport(
+ gfx::Size(50, 50), gfx::Size(50, 50), gfx::Size(50, 50));
+
+ LayerTreeImpl* active_tree = host_impl_->active_tree();
+
+ // Create a content layer beneath the outer viewport scroll layer.
+ int id = host_impl_->OuterViewportScrollLayer()->id();
+ host_impl_->OuterViewportScrollLayer()->AddChild(
+ LayerImpl::Create(host_impl_->active_tree(), id + 2));
+ LayerImpl* content = active_tree->OuterViewportScrollLayer()->children()[0];
+ content->SetBounds(gfx::Size(50, 50));
+
+ DrawFrame();
+
+ LayerImpl* inner_container = active_tree->InnerViewportContainerLayer();
+ LayerImpl* outer_container = active_tree->OuterViewportContainerLayer();
+
+ // The top controls should start off showing so the viewport should be shrunk.
+ ASSERT_EQ(gfx::Size(50, 50), inner_container->bounds());
+ ASSERT_EQ(gfx::Size(50, 50), outer_container->bounds());
+
+ EXPECT_EQ(gfx::SizeF(50, 50), active_tree->ScrollableSize());
+
+ EXPECT_EQ(InputHandler::SCROLL_STARTED,
+ host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
+
+ host_impl_->top_controls_manager()->ScrollBegin();
+
+ // Hide the top controls by a bit, the scrollable size should increase but the
+ // actual content bounds shouldn't.
+ {
+ host_impl_->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f, 25.f));
+ ASSERT_EQ(gfx::Size(50, 75), inner_container->bounds());
+ ASSERT_EQ(gfx::Size(50, 75), outer_container->bounds());
+ EXPECT_EQ(gfx::SizeF(50, 75), active_tree->ScrollableSize());
+ EXPECT_EQ(gfx::SizeF(50, 50), content->BoundsForScrolling());
+ }
+
+ // Fully hide the top controls.
+ {
+ host_impl_->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f, 25.f));
+ ASSERT_EQ(gfx::Size(50, 100), inner_container->bounds());
+ ASSERT_EQ(gfx::Size(50, 100), outer_container->bounds());
+ EXPECT_EQ(gfx::SizeF(50, 100), active_tree->ScrollableSize());
+ EXPECT_EQ(gfx::SizeF(50, 50), content->BoundsForScrolling());
+ }
+
+ // Scrolling additionally shouldn't have any effect.
+ {
+ host_impl_->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f, 25.f));
+ ASSERT_EQ(gfx::Size(50, 100), inner_container->bounds());
+ ASSERT_EQ(gfx::Size(50, 100), outer_container->bounds());
+ EXPECT_EQ(gfx::SizeF(50, 100), active_tree->ScrollableSize());
+ EXPECT_EQ(gfx::SizeF(50, 50), content->BoundsForScrolling());
+ }
+
+ host_impl_->top_controls_manager()->ScrollEnd();
+ host_impl_->ScrollEnd();
+}
+
TEST_F(LayerTreeHostImplTopControlsTest, ScrollTopControlsByFractionalAmount) {
SetupTopControlsAndScrollLayerWithVirtualViewport(
gfx::Size(10, 10), gfx::Size(10, 10), gfx::Size(10, 10));
@@ -2947,12 +3323,12 @@ TEST_F(LayerTreeHostImplTopControlsTest,
// Now when we continue scrolling, make sure the outer viewport gets scrolled
// since it wasn't scrollable when the scroll began.
host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -20.f));
- EXPECT_EQ(15.f, outer_scroll->CurrentScrollOffset().y());
- EXPECT_EQ(25.f, inner_scroll->CurrentScrollOffset().y());
+ EXPECT_EQ(25.f, outer_scroll->CurrentScrollOffset().y());
+ EXPECT_EQ(15.f, inner_scroll->CurrentScrollOffset().y());
host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -30.f));
- EXPECT_EQ(0.f, outer_scroll->CurrentScrollOffset().y());
- EXPECT_EQ(25.f, inner_scroll->CurrentScrollOffset().y());
+ EXPECT_EQ(25.f, outer_scroll->CurrentScrollOffset().y());
+ EXPECT_EQ(0.f, inner_scroll->CurrentScrollOffset().y());
host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -50.f));
host_impl_->ScrollEnd();
@@ -2967,6 +3343,7 @@ TEST_F(LayerTreeHostImplTopControlsTest, FixedContainerDelta) {
SetupTopControlsAndScrollLayerWithVirtualViewport(
gfx::Size(100, 100), gfx::Size(100, 100), gfx::Size(100, 100));
DrawFrame();
+ host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 2.f);
float page_scale = 1.5f;
LayerImpl* outer_viewport_scroll_layer =
@@ -2986,8 +3363,8 @@ TEST_F(LayerTreeHostImplTopControlsTest, FixedContainerDelta) {
host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
EXPECT_FLOAT_EQ(top_controls_height_ - top_controls_scroll_delta.y(),
host_impl_->top_controls_manager()->ContentTopOffset());
- EXPECT_VECTOR_EQ(top_controls_scroll_delta,
- outer_viewport_scroll_layer->FixedContainerSizeDelta());
+ EXPECT_FLOAT_EQ(top_controls_scroll_delta.y(),
+ outer_viewport_scroll_layer->FixedContainerSizeDelta().y());
host_impl_->ScrollEnd();
// Scroll past the maximum extent. The delta shouldn't be greater than the
@@ -3012,6 +3389,24 @@ TEST_F(LayerTreeHostImplTopControlsTest, FixedContainerDelta) {
host_impl_->top_controls_manager()->ScrollEnd();
}
+// Test that if only the top controls are scrolled, we shouldn't request a
+// commit.
+TEST_F(LayerTreeHostImplTopControlsTest, TopControlsDontTriggerCommit) {
+ SetupTopControlsAndScrollLayerWithVirtualViewport(
+ gfx::Size(100, 50), gfx::Size(100, 100), gfx::Size(100, 100));
+ DrawFrame();
+
+ // Show top controls
+ EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
+
+ // Scroll 25px to hide top controls
+ gfx::Vector2dF scroll_delta(0.f, 25.f);
+ EXPECT_EQ(InputHandler::SCROLL_STARTED,
+ host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
+ host_impl_->ScrollBy(gfx::Point(), scroll_delta);
+ EXPECT_FALSE(did_request_commit_);
+}
+
// Test that if a scrollable sublayer doesn't consume the scroll,
// top controls should hide when scrolling down.
TEST_F(LayerTreeHostImplTopControlsTest, TopControlsScrollableSublayer) {
@@ -3062,7 +3457,8 @@ TEST_F(LayerTreeHostImplTopControlsTest, TopControlsScrollableSublayer) {
// TreeImpl correctly affects the top controls manager and viewport bounds.
TEST_F(LayerTreeHostImplTopControlsTest, PositionTopControlsExplicitly) {
CreateHostImpl(settings_, CreateOutputSurface());
- SetupTopControlsAndScrollLayer();
+ SetupTopControlsAndScrollLayerWithVirtualViewport(
+ layer_size_, layer_size_, layer_size_);
DrawFrame();
host_impl_->active_tree()->SetCurrentTopControlsShownRatio(0.f);
@@ -3081,8 +3477,9 @@ TEST_F(LayerTreeHostImplTopControlsTest, PositionTopControlsExplicitly) {
host_impl_->DidChangeTopControlsPosition();
// Now that top controls have moved, expect the clip to resize.
- LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
- EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
+ LayerImpl* inner_clip_ptr =
+ host_impl_->InnerViewportScrollLayer()->parent()->parent();
+ EXPECT_EQ(viewport_size_, inner_clip_ptr->bounds());
}
// Test that the top_controls delta and sent delta are appropriately
@@ -3090,7 +3487,8 @@ TEST_F(LayerTreeHostImplTopControlsTest, PositionTopControlsExplicitly) {
// change after the activation.
TEST_F(LayerTreeHostImplTopControlsTest, ApplyDeltaOnTreeActivation) {
CreateHostImpl(settings_, CreateOutputSurface());
- SetupTopControlsAndScrollLayer();
+ SetupTopControlsAndScrollLayerWithVirtualViewport(
+ layer_size_, layer_size_, layer_size_);
DrawFrame();
host_impl_->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
@@ -3106,15 +3504,16 @@ TEST_F(LayerTreeHostImplTopControlsTest, ApplyDeltaOnTreeActivation) {
top_controls_height_);
host_impl_->DidChangeTopControlsPosition();
- LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
- EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
+ LayerImpl* inner_clip_ptr =
+ host_impl_->InnerViewportScrollLayer()->parent()->parent();
+ EXPECT_EQ(viewport_size_, inner_clip_ptr->bounds());
EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
host_impl_->ActivateSyncTree();
- root_clip_ptr = host_impl_->active_tree()->root_layer();
+ inner_clip_ptr = host_impl_->InnerViewportScrollLayer()->parent()->parent();
EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
- EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
+ EXPECT_EQ(viewport_size_, inner_clip_ptr->bounds());
EXPECT_FLOAT_EQ(
-15.f, host_impl_->active_tree()->top_controls_shown_ratio()->Delta() *
@@ -3131,7 +3530,8 @@ TEST_F(LayerTreeHostImplTopControlsTest, ApplyDeltaOnTreeActivation) {
// the compositor to accommodate the top controls.
TEST_F(LayerTreeHostImplTopControlsTest, TopControlsLayoutHeightChanged) {
CreateHostImpl(settings_, CreateOutputSurface());
- SetupTopControlsAndScrollLayer();
+ SetupTopControlsAndScrollLayerWithVirtualViewport(
+ layer_size_, layer_size_, layer_size_);
DrawFrame();
host_impl_->sync_tree()->PushTopControlsFromMainThread(1.f);
@@ -3143,24 +3543,26 @@ TEST_F(LayerTreeHostImplTopControlsTest, TopControlsLayoutHeightChanged) {
host_impl_->active_tree()->SetCurrentTopControlsShownRatio(0.f);
host_impl_->DidChangeTopControlsPosition();
- LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
- EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
+ LayerImpl* inner_clip_ptr =
+ host_impl_->InnerViewportScrollLayer()->parent()->parent();
+ EXPECT_EQ(viewport_size_, inner_clip_ptr->bounds());
EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
host_impl_->sync_tree()->root_layer()->SetBounds(
- gfx::Size(root_clip_ptr->bounds().width(),
- root_clip_ptr->bounds().height() - 50.f));
+ gfx::Size(inner_clip_ptr->bounds().width(),
+ inner_clip_ptr->bounds().height() - 50.f));
host_impl_->ActivateSyncTree();
- root_clip_ptr = host_impl_->active_tree()->root_layer();
+ inner_clip_ptr =
+ host_impl_->InnerViewportScrollLayer()->parent()->parent();
EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
// The total bounds should remain unchanged since the bounds delta should
// account for the difference between the layout height and the current
// top controls offset.
- EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
- EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f, 50.f), root_clip_ptr->bounds_delta());
+ EXPECT_EQ(viewport_size_, inner_clip_ptr->bounds());
+ EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f, 50.f), inner_clip_ptr->bounds_delta());
host_impl_->active_tree()->SetCurrentTopControlsShownRatio(1.f);
host_impl_->DidChangeTopControlsPosition();
@@ -3168,9 +3570,9 @@ TEST_F(LayerTreeHostImplTopControlsTest, TopControlsLayoutHeightChanged) {
EXPECT_EQ(1.f, host_impl_->top_controls_manager()->TopControlsShownRatio());
EXPECT_EQ(50.f, host_impl_->top_controls_manager()->TopControlsHeight());
EXPECT_EQ(50.f, host_impl_->top_controls_manager()->ContentTopOffset());
- EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f, 0.f), root_clip_ptr->bounds_delta());
+ EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f, 0.f), inner_clip_ptr->bounds_delta());
EXPECT_EQ(gfx::Size(viewport_size_.width(), viewport_size_.height() - 50.f),
- root_clip_ptr->bounds());
+ inner_clip_ptr->bounds());
}
// Test that showing/hiding the top controls when the viewport is fully scrolled
@@ -3243,6 +3645,7 @@ TEST_F(LayerTreeHostImplTopControlsTest, TopControlsViewportOffsetClamping) {
TEST_F(LayerTreeHostImplTopControlsTest, TopControlsAspectRatio) {
SetupTopControlsAndScrollLayerWithVirtualViewport(
gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
+ host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 2.f);
DrawFrame();
EXPECT_FLOAT_EQ(top_controls_height_,
@@ -3264,12 +3667,14 @@ TEST_F(LayerTreeHostImplTopControlsTest, TopControlsAspectRatio) {
host_impl_->active_tree()->OuterViewportContainerLayer();
LayerImpl* inner_container =
host_impl_->active_tree()->InnerViewportContainerLayer();
- EXPECT_EQ(gfx::Size(100, 100+25), inner_container->BoundsForScrolling());
+ EXPECT_EQ(gfx::SizeF(100.f, 100.f + 25.f),
+ inner_container->BoundsForScrolling());
// Outer viewport should match inner's aspect ratio. The bounds are ceiled.
float aspect_ratio = inner_container->BoundsForScrolling().width() /
inner_container->BoundsForScrolling().height();
- gfx::Size expected = gfx::ToCeiledSize(gfx::SizeF(200, 200 / aspect_ratio));
+ gfx::SizeF expected =
+ gfx::SizeF(gfx::ToCeiledSize(gfx::SizeF(200, 200 / aspect_ratio)));
EXPECT_EQ(expected, outer_container->BoundsForScrolling());
EXPECT_EQ(expected,
host_impl_->InnerViewportScrollLayer()->BoundsForScrolling());
@@ -3290,7 +3695,8 @@ TEST_F(LayerTreeHostImplTopControlsTest, TopControlsScrollOuterViewport) {
EXPECT_EQ(InputHandler::SCROLL_STARTED,
host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
host_impl_->ScrollBy(gfx::Point(), scroll_delta);
- EXPECT_EQ(host_impl_->OuterViewportScrollLayer(),
+
+ EXPECT_EQ(host_impl_->InnerViewportScrollLayer(),
host_impl_->CurrentlyScrollingLayer());
host_impl_->ScrollEnd();
@@ -3304,7 +3710,7 @@ TEST_F(LayerTreeHostImplTopControlsTest, TopControlsScrollOuterViewport) {
host_impl_->ScrollBy(gfx::Point(), scroll_delta);
EXPECT_EQ(0, host_impl_->top_controls_manager()->ContentTopOffset());
- EXPECT_EQ(host_impl_->OuterViewportScrollLayer(),
+ EXPECT_EQ(host_impl_->InnerViewportScrollLayer(),
host_impl_->CurrentlyScrollingLayer());
host_impl_->ScrollEnd();
@@ -3331,7 +3737,8 @@ TEST_F(LayerTreeHostImplTopControlsTest, TopControlsScrollOuterViewport) {
TEST_F(LayerTreeHostImplTopControlsTest,
ScrollNonScrollableRootWithTopControls) {
CreateHostImpl(settings_, CreateOutputSurface());
- SetupTopControlsAndScrollLayer();
+ SetupTopControlsAndScrollLayerWithVirtualViewport(
+ layer_size_, layer_size_, layer_size_);
DrawFrame();
EXPECT_EQ(InputHandler::SCROLL_STARTED,
@@ -3342,8 +3749,9 @@ TEST_F(LayerTreeHostImplTopControlsTest,
host_impl_->top_controls_manager()->ScrollEnd();
EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
// Now that top controls have moved, expect the clip to resize.
- LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
- EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
+ LayerImpl* inner_clip_ptr =
+ host_impl_->InnerViewportScrollLayer()->parent()->parent();
+ EXPECT_EQ(viewport_size_, inner_clip_ptr->bounds());
host_impl_->ScrollEnd();
@@ -3359,7 +3767,7 @@ TEST_F(LayerTreeHostImplTopControlsTest,
// Now that top controls have moved, expect the clip to resize.
EXPECT_EQ(gfx::Size(viewport_size_.width(),
viewport_size_.height() + scroll_increment_y),
- root_clip_ptr->bounds());
+ inner_clip_ptr->bounds());
host_impl_->top_controls_manager()->ScrollBy(
gfx::Vector2dF(0.f, scroll_increment_y));
@@ -3367,7 +3775,7 @@ TEST_F(LayerTreeHostImplTopControlsTest,
EXPECT_FLOAT_EQ(-2 * scroll_increment_y,
host_impl_->top_controls_manager()->ContentTopOffset());
// Now that top controls have moved, expect the clip to resize.
- EXPECT_EQ(clip_size_, root_clip_ptr->bounds());
+ EXPECT_EQ(clip_size_, inner_clip_ptr->bounds());
host_impl_->ScrollEnd();
@@ -3506,29 +3914,22 @@ TEST_F(LayerTreeHostImplTest, ScrollBlockedByContentLayer) {
}
TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnMainThread) {
- gfx::Size surface_size(20, 20);
- gfx::Size viewport_size(10, 10);
+ gfx::Size viewport_size(20, 20);
float page_scale = 2.f;
- scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
- scoped_ptr<LayerImpl> root_clip =
- LayerImpl::Create(host_impl_->active_tree(), 2);
- scoped_ptr<LayerImpl> root_scrolling =
- CreateScrollableLayer(3, surface_size, root_clip.get());
- EXPECT_EQ(viewport_size, root_clip->bounds());
- root_scrolling->SetIsContainerForFixedPositionLayers(true);
- root_clip->AddChild(root_scrolling.Pass());
- root->AddChild(root_clip.Pass());
- root->SetHasRenderSurface(true);
- host_impl_->active_tree()->SetRootLayer(root.Pass());
- // The behaviour in this test assumes the page scale is applied at a layer
- // above the clip layer.
- host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 3,
- Layer::INVALID_ID);
- host_impl_->active_tree()->DidBecomeActive();
- host_impl_->SetViewportSize(viewport_size);
+
+ SetupScrollAndContentsLayers(viewport_size);
+
+ // Setup the layers so that the outer viewport is scrollable.
+ host_impl_->active_tree()->InnerViewportScrollLayer()->parent()->SetBounds(
+ viewport_size);
+ host_impl_->active_tree()->OuterViewportScrollLayer()->SetBounds(
+ gfx::Size(40, 40));
+ host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 2.f);
DrawFrame();
LayerImpl* root_scroll =
+ host_impl_->active_tree()->OuterViewportScrollLayer();
+ LayerImpl* inner_scroll =
host_impl_->active_tree()->InnerViewportScrollLayer();
EXPECT_EQ(viewport_size, root_scroll->scroll_clip_layer()->bounds());
@@ -3541,11 +3942,10 @@ TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnMainThread) {
host_impl_->ScrollEnd();
// Set new page scale from main thread.
- host_impl_->active_tree()->PushPageScaleFromMainThread(page_scale, page_scale,
- page_scale);
+ host_impl_->active_tree()->PushPageScaleFromMainThread(page_scale, 1.f, 2.f);
scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
- EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), root_scroll->id(),
+ EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), inner_scroll->id(),
expected_scroll_delta));
// The scroll range should also have been updated.
@@ -3557,30 +3957,22 @@ TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnMainThread) {
}
TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnImplThread) {
- gfx::Size surface_size(20, 20);
- gfx::Size viewport_size(10, 10);
+ gfx::Size viewport_size(20, 20);
float page_scale = 2.f;
- scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
- scoped_ptr<LayerImpl> root_clip =
- LayerImpl::Create(host_impl_->active_tree(), 2);
- scoped_ptr<LayerImpl> root_scrolling =
- CreateScrollableLayer(3, surface_size, root_clip.get());
- EXPECT_EQ(viewport_size, root_clip->bounds());
- root_scrolling->SetIsContainerForFixedPositionLayers(true);
- root_clip->AddChild(root_scrolling.Pass());
- root->AddChild(root_clip.Pass());
- root->SetHasRenderSurface(true);
- host_impl_->active_tree()->SetRootLayer(root.Pass());
- // The behaviour in this test assumes the page scale is applied at a layer
- // above the clip layer.
- host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 3,
- Layer::INVALID_ID);
- host_impl_->active_tree()->DidBecomeActive();
- host_impl_->SetViewportSize(viewport_size);
- host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, page_scale);
+
+ SetupScrollAndContentsLayers(viewport_size);
+
+ // Setup the layers so that the outer viewport is scrollable.
+ host_impl_->active_tree()->InnerViewportScrollLayer()->parent()->SetBounds(
+ viewport_size);
+ host_impl_->active_tree()->OuterViewportScrollLayer()->SetBounds(
+ gfx::Size(40, 40));
+ host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 2.f);
DrawFrame();
LayerImpl* root_scroll =
+ host_impl_->active_tree()->OuterViewportScrollLayer();
+ LayerImpl* inner_scroll =
host_impl_->active_tree()->InnerViewportScrollLayer();
EXPECT_EQ(viewport_size, root_scroll->scroll_clip_layer()->bounds());
@@ -3602,7 +3994,7 @@ TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnImplThread) {
// The scroll delta is not scaled because the main thread did not scale.
scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
- EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), root_scroll->id(),
+ EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), inner_scroll->id(),
expected_scroll_delta));
// The scroll range should also have been updated.
@@ -3613,6 +4005,7 @@ TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnImplThread) {
}
TEST_F(LayerTreeHostImplTest, PageScaleDeltaAppliedToRootScrollLayerOnly) {
+ host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 2.f);
gfx::Size surface_size(10, 10);
float default_page_scale = 1.f;
gfx::Transform default_page_scale_matrix;
@@ -3636,6 +4029,7 @@ TEST_F(LayerTreeHostImplTest, PageScaleDeltaAppliedToRootScrollLayerOnly) {
LayerImpl* grand_child = child->children()[0];
// Set new page scale on impl thread by pinching.
+ RebuildPropertyTrees();
host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
host_impl_->PinchGestureBegin();
host_impl_->PinchGestureUpdate(new_page_scale, gfx::Point());
@@ -3646,7 +4040,7 @@ TEST_F(LayerTreeHostImplTest, PageScaleDeltaAppliedToRootScrollLayerOnly) {
// Make sure all the layers are drawn with the page scale delta applied, i.e.,
// the page scale delta on the root layer is applied hierarchically.
LayerTreeHostImpl::FrameData frame;
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
host_impl_->DidDrawAllLayers(frame);
@@ -3663,32 +4057,19 @@ TEST_F(LayerTreeHostImplTest, PageScaleDeltaAppliedToRootScrollLayerOnly) {
}
TEST_F(LayerTreeHostImplTest, ScrollChildAndChangePageScaleOnMainThread) {
- gfx::Size surface_size(30, 30);
- scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
- root->SetBounds(gfx::Size(5, 5));
- root->SetHasRenderSurface(true);
- scoped_ptr<LayerImpl> root_scrolling =
- LayerImpl::Create(host_impl_->active_tree(), 2);
- root_scrolling->SetBounds(surface_size);
- root_scrolling->SetScrollClipLayer(root->id());
- root_scrolling->SetIsContainerForFixedPositionLayers(true);
- LayerImpl* root_scrolling_ptr = root_scrolling.get();
- root->AddChild(root_scrolling.Pass());
- int child_scroll_layer_id = 3;
- scoped_ptr<LayerImpl> child_scrolling = CreateScrollableLayer(
- child_scroll_layer_id, surface_size, root_scrolling_ptr);
- LayerImpl* child = child_scrolling.get();
- root_scrolling_ptr->AddChild(child_scrolling.Pass());
- host_impl_->active_tree()->SetRootLayer(root.Pass());
- host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
- Layer::INVALID_ID);
- host_impl_->active_tree()->DidBecomeActive();
- host_impl_->SetViewportSize(surface_size);
+ SetupScrollAndContentsLayers(gfx::Size(30, 30));
+
+ LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
+ LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
+
+ // Make the outer scroll layer scrollable.
+ outer_scroll->SetBounds(gfx::Size(50, 50));
+
DrawFrame();
gfx::Vector2d scroll_delta(0, 10);
gfx::Vector2d expected_scroll_delta(scroll_delta);
- gfx::ScrollOffset expected_max_scroll(child->MaxScrollOffset());
+ gfx::ScrollOffset expected_max_scroll(outer_scroll->MaxScrollOffset());
EXPECT_EQ(InputHandler::SCROLL_STARTED,
host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
host_impl_->ScrollBy(gfx::Point(), scroll_delta);
@@ -3701,11 +4082,11 @@ TEST_F(LayerTreeHostImplTest, ScrollChildAndChangePageScaleOnMainThread) {
DrawOneFrame();
scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
- EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), child_scroll_layer_id,
+ EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), inner_scroll->id(),
expected_scroll_delta));
// The scroll range should not have changed.
- EXPECT_EQ(child->MaxScrollOffset(), expected_max_scroll);
+ EXPECT_EQ(outer_scroll->MaxScrollOffset(), expected_max_scroll);
// The page scale delta remains constant because the impl thread did not
// scale.
@@ -3714,8 +4095,7 @@ TEST_F(LayerTreeHostImplTest, ScrollChildAndChangePageScaleOnMainThread) {
TEST_F(LayerTreeHostImplTest, ScrollChildBeyondLimit) {
// Scroll a child layer beyond its maximum scroll range and make sure the
- // parent layer is scrolled on the axis on which the child was unable to
- // scroll.
+ // parent layer isn't scrolled.
gfx::Size surface_size(10, 10);
gfx::Size content_size(20, 20);
scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
@@ -3754,9 +4134,8 @@ TEST_F(LayerTreeHostImplTest, ScrollChildBeyondLimit) {
EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), grand_child->id(),
gfx::Vector2d(0, -5)));
- // The child should have only scrolled on the other axis.
- EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), child->id(),
- gfx::Vector2d(-3, 0)));
+ // The child should not have scrolled.
+ ExpectNone(*scroll_info.get(), child->id());
}
}
@@ -3857,7 +4236,7 @@ TEST_F(LayerTreeHostImplTest, ScrollWithoutBubbling) {
// Scrolling should be adjusted from viewport space.
host_impl_->active_tree()->PushPageScaleFromMainThread(2.f, 2.f, 2.f);
- host_impl_->SetPageScaleOnActiveTree(2.f);
+ host_impl_->active_tree()->SetPageScaleOnActiveTree(2.f);
scroll_delta = gfx::Vector2d(0, -2);
EXPECT_EQ(InputHandler::SCROLL_STARTED,
@@ -3950,6 +4329,7 @@ TEST_F(LayerTreeHostImplTest, ScrollBeforeRedraw) {
host_impl_->active_tree()->DidBecomeActive();
// Scrolling should still work even though we did not draw yet.
+ RebuildPropertyTrees();
EXPECT_EQ(InputHandler::SCROLL_STARTED,
host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
}
@@ -4055,8 +4435,7 @@ TEST_F(LayerTreeHostImplTest, ScrollNonAxisAlignedRotatedLayer) {
host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
host_impl_->ScrollEnd();
- // The child layer should have scrolled down in its local coordinates an
- // amount proportional to the angle between it and the input scroll delta.
+ // The child layer shouldn't have scrolled.
gfx::Vector2d expected_scroll_delta(
0, -gesture_scroll_delta.x() *
std::sin(MathUtil::Deg2Rad(child_layer_angle)));
@@ -4065,14 +4444,8 @@ TEST_F(LayerTreeHostImplTest, ScrollNonAxisAlignedRotatedLayer) {
EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), child_layer_id,
expected_scroll_delta));
- // The root scroll layer should have scrolled more, since the input scroll
- // delta was mostly orthogonal to the child layer's vertical scroll axis.
- gfx::Vector2d expected_root_scroll_delta(
- gesture_scroll_delta.x() *
- std::pow(std::cos(MathUtil::Deg2Rad(child_layer_angle)), 2),
- 0);
- EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), scroll_layer->id(),
- expected_root_scroll_delta));
+ // The root scroll layer shouldn't have scrolled.
+ ExpectNone(*scroll_info.get(), scroll_layer->id());
}
}
@@ -4159,7 +4532,7 @@ TEST_F(LayerTreeHostImplTest, ScrollScaledLayer) {
int scale = 2;
gfx::Transform scale_transform;
scale_transform.Scale(scale, scale);
- scroll_layer->SetTransform(scale_transform);
+ scroll_layer->parent()->SetTransform(scale_transform);
gfx::Size surface_size(50, 50);
host_impl_->SetViewportSize(surface_size);
@@ -4199,7 +4572,7 @@ TEST_F(LayerTreeHostImplTest, ScrollViewportRounding) {
SetupScrollAndContentsLayers(gfx::Size(width, height));
host_impl_->active_tree()->InnerViewportContainerLayer()->SetBounds(
gfx::Size(width * scale - 1, height * scale));
- host_impl_->SetDeviceScaleFactor(scale);
+ host_impl_->active_tree()->SetDeviceScaleFactor(scale);
host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
LayerImpl* inner_viewport_scroll_layer =
@@ -4208,32 +4581,26 @@ TEST_F(LayerTreeHostImplTest, ScrollViewportRounding) {
inner_viewport_scroll_layer->MaxScrollOffset());
}
-class TestScrollOffsetDelegate : public LayerScrollOffsetDelegate {
+class TestInputHandlerClient : public InputHandlerClient {
public:
- TestScrollOffsetDelegate()
+ TestInputHandlerClient()
: page_scale_factor_(0.f),
min_page_scale_factor_(-1.f),
- max_page_scale_factor_(-1.f),
- needs_animate_(false) {}
-
- ~TestScrollOffsetDelegate() override {}
-
- gfx::ScrollOffset GetTotalScrollOffset() override {
- return getter_return_value_;
- }
-
- bool IsExternalScrollActive() const override { return false; }
-
- void SetNeedsAnimate(const AnimationCallback&) override {
- needs_animate_ = true;
- }
-
- void UpdateRootLayerState(const gfx::ScrollOffset& total_scroll_offset,
- const gfx::ScrollOffset& max_scroll_offset,
- const gfx::SizeF& scrollable_size,
- float page_scale_factor,
- float min_page_scale_factor,
- float max_page_scale_factor) override {
+ max_page_scale_factor_(-1.f) {}
+ ~TestInputHandlerClient() override {}
+
+ // InputHandlerClient implementation.
+ void WillShutdown() override {}
+ void Animate(base::TimeTicks time) override {}
+ void MainThreadHasStoppedFlinging() override {}
+ void ReconcileElasticOverscrollAndRootScroll() override {}
+ void UpdateRootLayerStateForSynchronousInputHandler(
+ const gfx::ScrollOffset& total_scroll_offset,
+ const gfx::ScrollOffset& max_scroll_offset,
+ const gfx::SizeF& scrollable_size,
+ float page_scale_factor,
+ float min_page_scale_factor,
+ float max_page_scale_factor) override {
DCHECK(total_scroll_offset.x() <= max_scroll_offset.x());
DCHECK(total_scroll_offset.y() <= max_scroll_offset.y());
last_set_scroll_offset_ = total_scroll_offset;
@@ -4242,24 +4609,12 @@ class TestScrollOffsetDelegate : public LayerScrollOffsetDelegate {
page_scale_factor_ = page_scale_factor;
min_page_scale_factor_ = min_page_scale_factor;
max_page_scale_factor_ = max_page_scale_factor;
-
- set_getter_return_value(last_set_scroll_offset_);
- }
-
- bool GetAndResetNeedsAnimate() {
- bool needs_animate = needs_animate_;
- needs_animate_ = false;
- return needs_animate;
}
gfx::ScrollOffset last_set_scroll_offset() {
return last_set_scroll_offset_;
}
- void set_getter_return_value(const gfx::ScrollOffset& value) {
- getter_return_value_ = value;
- }
-
gfx::ScrollOffset max_scroll_offset() const {
return max_scroll_offset_;
}
@@ -4282,53 +4637,64 @@ class TestScrollOffsetDelegate : public LayerScrollOffsetDelegate {
private:
gfx::ScrollOffset last_set_scroll_offset_;
- gfx::ScrollOffset getter_return_value_;
gfx::ScrollOffset max_scroll_offset_;
gfx::SizeF scrollable_size_;
float page_scale_factor_;
float min_page_scale_factor_;
float max_page_scale_factor_;
- bool needs_animate_;
};
-// TODO(jdduke): Test root fling animation.
TEST_F(LayerTreeHostImplTest, RootLayerScrollOffsetDelegation) {
- TestScrollOffsetDelegate scroll_delegate;
+ TestInputHandlerClient scroll_watcher;
host_impl_->SetViewportSize(gfx::Size(10, 20));
LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
LayerImpl* clip_layer = scroll_layer->parent()->parent();
clip_layer->SetBounds(gfx::Size(10, 20));
- // Setting the delegate results in the current scroll offset being set.
+ host_impl_->BindToClient(&scroll_watcher);
+
gfx::Vector2dF initial_scroll_delta(10.f, 10.f);
scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
scroll_layer->SetScrollDelta(initial_scroll_delta);
- host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
- EXPECT_EQ(initial_scroll_delta.ToString(),
- scroll_delegate.last_set_scroll_offset().ToString());
+
+ EXPECT_EQ(gfx::ScrollOffset(), scroll_watcher.last_set_scroll_offset());
+
+ // Requesting an update results in the current scroll offset being set.
+ host_impl_->RequestUpdateForSynchronousInputHandler();
+ EXPECT_EQ(gfx::ScrollOffset(initial_scroll_delta),
+ scroll_watcher.last_set_scroll_offset());
// Setting the delegate results in the scrollable_size, max_scroll_offset,
// page_scale_factor and {min|max}_page_scale_factor being set.
- EXPECT_EQ(gfx::SizeF(100, 100), scroll_delegate.scrollable_size());
- EXPECT_EQ(gfx::ScrollOffset(90, 80), scroll_delegate.max_scroll_offset());
- EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
- EXPECT_EQ(0.f, scroll_delegate.min_page_scale_factor());
- EXPECT_EQ(0.f, scroll_delegate.max_page_scale_factor());
+ EXPECT_EQ(gfx::SizeF(100, 100), scroll_watcher.scrollable_size());
+ EXPECT_EQ(gfx::ScrollOffset(90, 80), scroll_watcher.max_scroll_offset());
+ EXPECT_EQ(1.f, scroll_watcher.page_scale_factor());
+ EXPECT_EQ(1.f, scroll_watcher.min_page_scale_factor());
+ EXPECT_EQ(1.f, scroll_watcher.max_page_scale_factor());
- // Updating page scale immediately updates the delegate.
+ // Put a page scale on the tree.
host_impl_->active_tree()->PushPageScaleFromMainThread(2.f, 0.5f, 4.f);
- EXPECT_EQ(2.f, scroll_delegate.page_scale_factor());
- EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
- EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
- host_impl_->SetPageScaleOnActiveTree(2.f * 1.5f);
- EXPECT_EQ(3.f, scroll_delegate.page_scale_factor());
- EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
- EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
- host_impl_->SetPageScaleOnActiveTree(2.f);
+ EXPECT_EQ(1.f, scroll_watcher.page_scale_factor());
+ EXPECT_EQ(1.f, scroll_watcher.min_page_scale_factor());
+ EXPECT_EQ(1.f, scroll_watcher.max_page_scale_factor());
+ // Activation will update the delegate.
+ host_impl_->ActivateSyncTree();
+ EXPECT_EQ(2.f, scroll_watcher.page_scale_factor());
+ EXPECT_EQ(.5f, scroll_watcher.min_page_scale_factor());
+ EXPECT_EQ(4.f, scroll_watcher.max_page_scale_factor());
+
+ // Reset the page scale for the rest of the test.
host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
- EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
- EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
- EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
+ EXPECT_EQ(2.f, scroll_watcher.page_scale_factor());
+ EXPECT_EQ(.5f, scroll_watcher.min_page_scale_factor());
+ EXPECT_EQ(4.f, scroll_watcher.max_page_scale_factor());
+
+ // Animating page scale can change the root offset, so it should update the
+ // delegate.
+ host_impl_->Animate();
+ EXPECT_EQ(1.f, scroll_watcher.page_scale_factor());
+ EXPECT_EQ(.5f, scroll_watcher.min_page_scale_factor());
+ EXPECT_EQ(4.f, scroll_watcher.max_page_scale_factor());
// The pinch gesture doesn't put the delegate into a state where the scroll
// offset is outside of the scroll range. (this is verified by DCHECKs in the
@@ -4340,46 +4706,37 @@ TEST_F(LayerTreeHostImplTest, RootLayerScrollOffsetDelegation) {
host_impl_->PinchGestureEnd();
host_impl_->ScrollEnd();
- // Scrolling should be relative to the offset as returned by the delegate.
+ // Scrolling should be relative to the offset as given by the delegate.
gfx::Vector2dF scroll_delta(0.f, 10.f);
gfx::ScrollOffset current_offset(7.f, 8.f);
- scroll_delegate.set_getter_return_value(current_offset);
EXPECT_EQ(InputHandler::SCROLL_STARTED,
host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
- host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
+ host_impl_->SetSynchronousInputHandlerRootScrollOffset(current_offset);
host_impl_->ScrollBy(gfx::Point(), scroll_delta);
EXPECT_EQ(ScrollOffsetWithDelta(current_offset, scroll_delta),
- scroll_delegate.last_set_scroll_offset());
+ scroll_watcher.last_set_scroll_offset());
current_offset = gfx::ScrollOffset(42.f, 41.f);
- scroll_delegate.set_getter_return_value(current_offset);
- host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
+ host_impl_->SetSynchronousInputHandlerRootScrollOffset(current_offset);
host_impl_->ScrollBy(gfx::Point(), scroll_delta);
EXPECT_EQ(current_offset + gfx::ScrollOffset(scroll_delta),
- scroll_delegate.last_set_scroll_offset());
+ scroll_watcher.last_set_scroll_offset());
host_impl_->ScrollEnd();
- scroll_delegate.set_getter_return_value(gfx::ScrollOffset());
- host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
+ host_impl_->SetSynchronousInputHandlerRootScrollOffset(gfx::ScrollOffset());
// Forces a full tree synchronization and ensures that the scroll delegate
// sees the correct size of the new tree.
gfx::Size new_size(42, 24);
host_impl_->CreatePendingTree();
+ host_impl_->pending_tree()->PushPageScaleFromMainThread(1.f, 1.f, 1.f);
CreateScrollAndContentsLayers(host_impl_->pending_tree(), new_size);
host_impl_->ActivateSyncTree();
- EXPECT_EQ(new_size, scroll_delegate.scrollable_size());
+ EXPECT_EQ(gfx::SizeF(new_size), scroll_watcher.scrollable_size());
- // Un-setting the delegate should propagate the delegate's current offset to
- // the root scrollable layer.
- current_offset = gfx::ScrollOffset(13.f, 12.f);
- scroll_delegate.set_getter_return_value(current_offset);
- host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
- host_impl_->SetRootLayerScrollOffsetDelegate(NULL);
-
- EXPECT_EQ(current_offset.ToString(),
- scroll_layer->CurrentScrollOffset().ToString());
+ // Tear down the LayerTreeHostImpl before the InputHandlerClient.
+ host_impl_.reset();
}
void CheckLayerScrollDelta(LayerImpl* layer, gfx::Vector2dF scroll_delta) {
@@ -4394,12 +4751,10 @@ void CheckLayerScrollDelta(LayerImpl* layer, gfx::Vector2dF scroll_delta) {
TEST_F(LayerTreeHostImplTest,
ExternalRootLayerScrollOffsetDelegationReflectedInNextDraw) {
- TestScrollOffsetDelegate scroll_delegate;
host_impl_->SetViewportSize(gfx::Size(10, 20));
LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
LayerImpl* clip_layer = scroll_layer->parent()->parent();
clip_layer->SetBounds(gfx::Size(10, 20));
- host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
// Draw first frame to clear any pending draws and check scroll.
DrawFrame();
@@ -4408,18 +4763,15 @@ TEST_F(LayerTreeHostImplTest,
// Set external scroll delta on delegate and notify LayerTreeHost.
gfx::ScrollOffset scroll_offset(10.f, 10.f);
- scroll_delegate.set_getter_return_value(scroll_offset);
- host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
+ host_impl_->SetSynchronousInputHandlerRootScrollOffset(scroll_offset);
// Check scroll delta reflected in layer.
LayerTreeHostImpl::FrameData frame;
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
host_impl_->DidDrawAllLayers(frame);
EXPECT_FALSE(frame.has_no_damage);
CheckLayerScrollDelta(scroll_layer, ScrollOffsetToVector2dF(scroll_offset));
-
- host_impl_->SetRootLayerScrollOffsetDelegate(NULL);
}
TEST_F(LayerTreeHostImplTest, OverscrollRoot) {
@@ -4612,27 +4964,7 @@ TEST_F(LayerTreeHostImplTest, OverscrollChildEventBubbling) {
// should be applied to one of its ancestors if possible. Overscroll should
// be reflected only when it has bubbled up to the root scrolling layer.
InputHandlerScrollResult scroll_result;
- gfx::Size surface_size(10, 10);
- gfx::Size content_size(20, 20);
- scoped_ptr<LayerImpl> root_clip =
- LayerImpl::Create(host_impl_->active_tree(), 3);
- root_clip->SetHasRenderSurface(true);
-
- scoped_ptr<LayerImpl> root =
- CreateScrollableLayer(1, content_size, root_clip.get());
- root->SetIsContainerForFixedPositionLayers(true);
- scoped_ptr<LayerImpl> child =
- CreateScrollableLayer(2, content_size, root_clip.get());
-
- child->SetScrollClipLayer(Layer::INVALID_ID);
- root->AddChild(child.Pass());
- root_clip->AddChild(root.Pass());
-
- host_impl_->SetViewportSize(surface_size);
- host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
- host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 1,
- Layer::INVALID_ID);
- host_impl_->active_tree()->DidBecomeActive();
+ SetupScrollAndContentsLayers(gfx::Size(20, 20));
DrawFrame();
{
gfx::Vector2d scroll_delta(0, 8);
@@ -4676,74 +5008,10 @@ TEST_F(LayerTreeHostImplTest, OverscrollAlways) {
EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
}
-TEST_F(LayerTreeHostImplTest, NoOverscrollOnFractionalDeviceScale) {
- InputHandlerScrollResult scroll_result;
- gfx::Size surface_size(980, 1439);
- gfx::Size content_size(980, 1438);
- float device_scale_factor = 1.5f;
- scoped_ptr<LayerImpl> root_clip =
- LayerImpl::Create(host_impl_->active_tree(), 3);
- root_clip->SetHasRenderSurface(true);
-
- scoped_ptr<LayerImpl> root =
- CreateScrollableLayer(1, content_size, root_clip.get());
- root->SetIsContainerForFixedPositionLayers(true);
- scoped_ptr<LayerImpl> child =
- CreateScrollableLayer(2, content_size, root_clip.get());
- root->scroll_clip_layer()->SetBounds(gfx::Size(320, 469));
- host_impl_->active_tree()->PushPageScaleFromMainThread(0.326531f, 0.326531f,
- 5.f);
- host_impl_->SetPageScaleOnActiveTree(0.326531f);
- child->SetScrollClipLayer(Layer::INVALID_ID);
- root->AddChild(child.Pass());
- root_clip->AddChild(root.Pass());
-
- host_impl_->SetViewportSize(surface_size);
- host_impl_->SetDeviceScaleFactor(device_scale_factor);
- host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
- host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 1,
- Layer::INVALID_ID);
- host_impl_->active_tree()->DidBecomeActive();
- DrawFrame();
- {
- // Horizontal & Vertical GlowEffect should not be applied when
- // content size is less then view port size. For Example Horizontal &
- // vertical GlowEffect should not be applied in about:blank page.
- EXPECT_EQ(InputHandler::SCROLL_STARTED,
- host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL));
- scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -1));
- EXPECT_FALSE(scroll_result.did_scroll);
- EXPECT_FALSE(scroll_result.did_overscroll_root);
- EXPECT_EQ(gfx::Vector2dF().ToString(),
- host_impl_->accumulated_root_overscroll().ToString());
-
- host_impl_->ScrollEnd();
- }
-}
-
TEST_F(LayerTreeHostImplTest, NoOverscrollWhenNotAtEdge) {
InputHandlerScrollResult scroll_result;
- gfx::Size surface_size(100, 100);
- gfx::Size content_size(200, 200);
- scoped_ptr<LayerImpl> root_clip =
- LayerImpl::Create(host_impl_->active_tree(), 3);
- root_clip->SetHasRenderSurface(true);
-
- scoped_ptr<LayerImpl> root =
- CreateScrollableLayer(1, content_size, root_clip.get());
- root->SetIsContainerForFixedPositionLayers(true);
- scoped_ptr<LayerImpl> child =
- CreateScrollableLayer(2, content_size, root_clip.get());
-
- child->SetScrollClipLayer(Layer::INVALID_ID);
- root->AddChild(child.Pass());
- root_clip->AddChild(root.Pass());
+ SetupScrollAndContentsLayers(gfx::Size(200, 200));
- host_impl_->SetViewportSize(surface_size);
- host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
- host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 1,
- Layer::INVALID_ID);
- host_impl_->active_tree()->DidBecomeActive();
DrawFrame();
{
// Edge glow effect should be applicable only upon reaching Edges
@@ -4904,7 +5172,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
layer1->SetContentsOpaque(true);
layer1->SetExpectation(false, false);
layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
EXPECT_TRUE(layer1->quads_appended());
host_impl_->DidDrawAllLayers(frame);
@@ -4913,7 +5181,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
layer1->SetContentsOpaque(false);
layer1->SetExpectation(true, false);
layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
EXPECT_TRUE(layer1->quads_appended());
host_impl_->DidDrawAllLayers(frame);
@@ -4923,7 +5191,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
layer1->SetOpacity(0.5f);
layer1->SetExpectation(true, false);
layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
EXPECT_TRUE(layer1->quads_appended());
host_impl_->DidDrawAllLayers(frame);
@@ -4933,7 +5201,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
layer1->SetOpacity(0.5f);
layer1->SetExpectation(true, false);
layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
EXPECT_TRUE(layer1->quads_appended());
host_impl_->DidDrawAllLayers(frame);
@@ -4955,7 +5223,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
layer2->SetOpacity(1.f);
layer2->SetExpectation(false, false);
layer2->SetUpdateRect(gfx::Rect(layer1->bounds()));
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
EXPECT_TRUE(layer1->quads_appended());
EXPECT_TRUE(layer2->quads_appended());
@@ -4968,7 +5236,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
layer2->SetExpectation(false, false);
layer2->SetUpdateRect(gfx::Rect(layer1->bounds()));
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
EXPECT_TRUE(layer1->quads_appended());
EXPECT_TRUE(layer2->quads_appended());
@@ -4982,7 +5250,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
layer2->SetExpectation(false, false);
layer2->SetUpdateRect(gfx::Rect(layer1->bounds()));
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
EXPECT_TRUE(layer1->quads_appended());
EXPECT_TRUE(layer2->quads_appended());
@@ -5002,7 +5270,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
layer2->SetUpdateRect(gfx::Rect(layer1->bounds()));
FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
host_impl_->active_tree()->root_layer());
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
EXPECT_TRUE(layer1->quads_appended());
EXPECT_TRUE(layer2->quads_appended());
@@ -5019,7 +5287,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
layer2->SetOpacity(0.5f);
layer2->SetExpectation(true, false);
layer2->SetUpdateRect(gfx::Rect(layer1->bounds()));
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
EXPECT_TRUE(layer1->quads_appended());
EXPECT_TRUE(layer2->quads_appended());
@@ -5034,7 +5302,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
layer2->SetOpacity(1.f);
layer2->SetExpectation(true, false);
layer2->SetUpdateRect(gfx::Rect(layer1->bounds()));
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
EXPECT_TRUE(layer1->quads_appended());
EXPECT_TRUE(layer2->quads_appended());
@@ -5050,7 +5318,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
layer2->SetOpacity(1.f);
layer2->SetExpectation(false, false);
layer2->SetUpdateRect(gfx::Rect(layer1->bounds()));
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
EXPECT_TRUE(layer1->quads_appended());
EXPECT_TRUE(layer2->quads_appended());
@@ -5063,7 +5331,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
layer1->SetExpectation(true, false);
layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
EXPECT_TRUE(layer1->quads_appended());
host_impl_->DidDrawAllLayers(frame);
@@ -5075,7 +5343,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
layer1->SetExpectation(true, false);
layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
EXPECT_TRUE(layer1->quads_appended());
host_impl_->DidDrawAllLayers(frame);
@@ -5087,7 +5355,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
layer1->SetExpectation(true, false);
layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
EXPECT_TRUE(layer1->quads_appended());
host_impl_->DidDrawAllLayers(frame);
@@ -5100,7 +5368,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
layer1->SetExpectation(false, false);
layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
EXPECT_TRUE(layer1->quads_appended());
host_impl_->DidDrawAllLayers(frame);
@@ -5144,7 +5412,7 @@ class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest {
child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
LayerTreeHostImpl::FrameData frame;
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
ASSERT_EQ(1u, frame.render_passes.size());
EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
@@ -5164,7 +5432,7 @@ class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest {
child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
LayerTreeHostImpl::FrameData frame;
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
ASSERT_EQ(1u, frame.render_passes.size());
EXPECT_EQ(1u, CountGutterQuads(frame.render_passes[0]->quad_list));
@@ -5184,7 +5452,7 @@ class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest {
child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
LayerTreeHostImpl::FrameData frame;
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
ASSERT_EQ(1u, frame.render_passes.size());
EXPECT_EQ(4u, CountGutterQuads(frame.render_passes[0]->quad_list));
@@ -5205,7 +5473,7 @@ class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest {
child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
LayerTreeHostImpl::FrameData frame;
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
ASSERT_EQ(1u, frame.render_passes.size());
EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
@@ -5244,8 +5512,9 @@ class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest {
if (quad->material != DrawQuad::TEXTURE_CONTENT)
continue;
const TextureDrawQuad* texture_quad = TextureDrawQuad::MaterialCast(quad);
- gfx::SizeF gutter_texture_size_pixels = gfx::ScaleSize(
- gutter_texture_size_, host_impl_->device_scale_factor());
+ gfx::SizeF gutter_texture_size_pixels =
+ gfx::ScaleSize(gfx::SizeF(gutter_texture_size_),
+ host_impl_->active_tree()->device_scale_factor());
EXPECT_EQ(texture_quad->uv_top_left.x(),
texture_quad->rect.x() / gutter_texture_size_pixels.width());
EXPECT_EQ(texture_quad->uv_top_left.y(),
@@ -5260,8 +5529,8 @@ class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest {
}
gfx::Size DipSizeToPixelSize(const gfx::Size& size) {
- return gfx::ToRoundedSize(
- gfx::ScaleSize(size, host_impl_->device_scale_factor()));
+ return gfx::ScaleToRoundedSize(
+ size, host_impl_->active_tree()->device_scale_factor());
}
DrawQuad::Material gutter_quad_material_;
@@ -5291,7 +5560,7 @@ TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCoveredScaled) {
bool always_draw = false;
CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
- host_impl_->SetDeviceScaleFactor(2.f);
+ host_impl_->active_tree()->SetDeviceScaleFactor(2.f);
host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
SetupActiveTreeLayers();
TestLayerCoversFullViewport();
@@ -5374,8 +5643,8 @@ TEST_F(LayerTreeHostImplTest, ReshapeNotCalledUntilDraw) {
LayerTreeHostImpl::FrameData frame;
host_impl_->SetViewportSize(gfx::Size(10, 10));
- host_impl_->SetDeviceScaleFactor(1.f);
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ host_impl_->active_tree()->SetDeviceScaleFactor(1.f);
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
EXPECT_TRUE(provider->TestContext3d()->reshape_called());
EXPECT_EQ(provider->TestContext3d()->width(), 10);
@@ -5385,7 +5654,7 @@ TEST_F(LayerTreeHostImplTest, ReshapeNotCalledUntilDraw) {
provider->TestContext3d()->clear_reshape_called();
host_impl_->SetViewportSize(gfx::Size(20, 30));
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
EXPECT_TRUE(provider->TestContext3d()->reshape_called());
EXPECT_EQ(provider->TestContext3d()->width(), 20);
@@ -5394,8 +5663,8 @@ TEST_F(LayerTreeHostImplTest, ReshapeNotCalledUntilDraw) {
host_impl_->DidDrawAllLayers(frame);
provider->TestContext3d()->clear_reshape_called();
- host_impl_->SetDeviceScaleFactor(2.f);
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ host_impl_->active_tree()->SetDeviceScaleFactor(2.f);
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
EXPECT_TRUE(provider->TestContext3d()->reshape_called());
EXPECT_EQ(provider->TestContext3d()->width(), 20);
@@ -5425,7 +5694,7 @@ TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) {
LayerTreeHostImpl::Create(
settings, this, &proxy_, &stats_instrumentation_,
&shared_bitmap_manager_, NULL, &task_graph_runner_, 0);
- layer_tree_host_impl->InitializeRenderer(output_surface.Pass());
+ layer_tree_host_impl->InitializeRenderer(output_surface.get());
layer_tree_host_impl->WillBeginImplFrame(
CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE));
layer_tree_host_impl->SetViewportSize(gfx::Size(500, 500));
@@ -5502,7 +5771,7 @@ TEST_F(LayerTreeHostImplTest, RootLayerDoesntCreateExtraSurface) {
LayerTreeHostImpl::FrameData frame;
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
EXPECT_EQ(1u, frame.render_surface_layer_list->size());
EXPECT_EQ(1u, frame.render_passes.size());
host_impl_->DidDrawAllLayers(frame);
@@ -5638,7 +5907,7 @@ TEST_F(LayerTreeHostImplTest, NoPartialSwap) {
harness.MustSetNoScissor();
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
host_impl_->DidDrawAllLayers(frame);
}
@@ -5651,7 +5920,7 @@ TEST_F(LayerTreeHostImplTest, NoPartialSwap) {
harness.MustSetScissor(0, 0, 10, 10);
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
host_impl_->DidDrawAllLayers(frame);
}
@@ -5673,7 +5942,7 @@ TEST_F(LayerTreeHostImplTest, PartialSwap) {
harness.MustDrawSolidQuad();
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
host_impl_->DidDrawAllLayers(frame);
}
@@ -5688,7 +5957,7 @@ TEST_F(LayerTreeHostImplTest, PartialSwap) {
harness.MustDrawSolidQuad();
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
host_impl_->DidDrawAllLayers(frame);
}
@@ -5701,19 +5970,14 @@ static scoped_ptr<LayerTreeHostImpl> SetupLayersForOpacity(
Proxy* proxy,
SharedBitmapManager* manager,
TaskGraphRunner* task_graph_runner,
- RenderingStatsInstrumentation* stats_instrumentation) {
- scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
- scoped_ptr<OutputSurface> output_surface(
- FakeOutputSurface::Create3d(provider));
- provider->BindToCurrentThread();
- provider->TestContext3d()->set_have_post_sub_buffer(true);
-
+ RenderingStatsInstrumentation* stats_instrumentation,
+ OutputSurface* output_surface) {
LayerTreeSettings settings;
settings.renderer_settings.partial_swap_enabled = partial_swap;
scoped_ptr<LayerTreeHostImpl> my_host_impl =
LayerTreeHostImpl::Create(settings, client, proxy, stats_instrumentation,
manager, nullptr, task_graph_runner, 0);
- my_host_impl->InitializeRenderer(output_surface.Pass());
+ my_host_impl->InitializeRenderer(output_surface);
my_host_impl->WillBeginImplFrame(
CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE));
my_host_impl->SetViewportSize(gfx::Size(100, 100));
@@ -5776,9 +6040,14 @@ static scoped_ptr<LayerTreeHostImpl> SetupLayersForOpacity(
TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorPartialSwap) {
TestSharedBitmapManager shared_bitmap_manager;
TestTaskGraphRunner task_graph_runner;
- scoped_ptr<LayerTreeHostImpl> my_host_impl =
- SetupLayersForOpacity(true, this, &proxy_, &shared_bitmap_manager,
- &task_graph_runner, &stats_instrumentation_);
+ scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
+ provider->BindToCurrentThread();
+ provider->TestContext3d()->set_have_post_sub_buffer(true);
+ scoped_ptr<OutputSurface> output_surface(
+ FakeOutputSurface::Create3d(provider));
+ scoped_ptr<LayerTreeHostImpl> my_host_impl = SetupLayersForOpacity(
+ true, this, &proxy_, &shared_bitmap_manager, &task_graph_runner,
+ &stats_instrumentation_, output_surface.get());
{
LayerTreeHostImpl::FrameData frame;
EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame));
@@ -5800,9 +6069,14 @@ TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorPartialSwap) {
TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorNoPartialSwap) {
TestSharedBitmapManager shared_bitmap_manager;
TestTaskGraphRunner task_graph_runner;
- scoped_ptr<LayerTreeHostImpl> my_host_impl =
- SetupLayersForOpacity(false, this, &proxy_, &shared_bitmap_manager,
- &task_graph_runner, &stats_instrumentation_);
+ scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
+ provider->BindToCurrentThread();
+ provider->TestContext3d()->set_have_post_sub_buffer(true);
+ scoped_ptr<OutputSurface> output_surface(
+ FakeOutputSurface::Create3d(provider));
+ scoped_ptr<LayerTreeHostImpl> my_host_impl = SetupLayersForOpacity(
+ false, this, &proxy_, &shared_bitmap_manager, &task_graph_runner,
+ &stats_instrumentation_, output_surface.get());
{
LayerTreeHostImpl::FrameData frame;
EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame));
@@ -5857,7 +6131,7 @@ TEST_F(LayerTreeHostImplTest, LayersFreeTextures) {
EXPECT_EQ(0u, context3d->NumTextures());
LayerTreeHostImpl::FrameData frame;
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
host_impl_->DidDrawAllLayers(frame);
host_impl_->SwapBuffers(frame);
@@ -5900,7 +6174,7 @@ TEST_F(LayerTreeHostImplTest, HasTransparentBackground) {
EXPECT_CALL(*mock_context, drawElements(_, _, _, _))
.Times(1);
LayerTreeHostImpl::FrameData frame;
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
host_impl_->DidDrawAllLayers(frame);
Mock::VerifyAndClearExpectations(&mock_context);
@@ -5908,7 +6182,7 @@ TEST_F(LayerTreeHostImplTest, HasTransparentBackground) {
// Verify no quads are drawn when transparent background is set.
host_impl_->active_tree()->set_has_transparent_background(true);
host_impl_->SetFullRootLayerDamage();
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
host_impl_->DidDrawAllLayers(frame);
Mock::VerifyAndClearExpectations(&mock_context);
@@ -5921,11 +6195,11 @@ class LayerTreeHostImplTestWithDelegatingRenderer
return FakeOutputSurface::CreateDelegating3d();
}
- void DrawFrameAndTestDamage(const gfx::RectF& expected_damage) {
+ void DrawFrameAndTestDamage(const gfx::Rect& expected_damage) {
bool expect_to_draw = !expected_damage.IsEmpty();
LayerTreeHostImpl::FrameData frame;
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
if (!expect_to_draw) {
// With no damage, we don't draw, and no quads are created.
@@ -5942,12 +6216,12 @@ class LayerTreeHostImplTestWithDelegatingRenderer
ASSERT_EQ(2u, root_render_pass->quad_list.size());
LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
- gfx::RectF expected_child_visible_rect(child->bounds());
+ gfx::Rect expected_child_visible_rect(child->bounds());
EXPECT_EQ(expected_child_visible_rect,
root_render_pass->quad_list.front()->visible_rect);
LayerImpl* root = host_impl_->active_tree()->root_layer();
- gfx::RectF expected_root_visible_rect(root->bounds());
+ gfx::Rect expected_root_visible_rect(root->bounds());
EXPECT_EQ(expected_root_visible_rect,
root_render_pass->quad_list.ElementAt(1)->visible_rect);
}
@@ -6025,13 +6299,13 @@ TEST_F(LayerTreeHostImplTest, FarAwayQuadsDontNeedAA) {
// Due to precision issues (especially on Android), sometimes far
// away quads can end up thinking they need AA.
float device_scale_factor = 4.f / 3.f;
- host_impl_->SetDeviceScaleFactor(device_scale_factor);
gfx::Size root_size(2000, 1000);
gfx::Size device_viewport_size =
- gfx::ToCeiledSize(gfx::ScaleSize(root_size, device_scale_factor));
+ gfx::ScaleToCeiledSize(root_size, device_scale_factor);
host_impl_->SetViewportSize(device_viewport_size);
host_impl_->CreatePendingTree();
+ host_impl_->pending_tree()->SetDeviceScaleFactor(device_scale_factor);
host_impl_->pending_tree()->PushPageScaleFromMainThread(1.f, 1.f / 16.f,
16.f);
@@ -6048,13 +6322,12 @@ TEST_F(LayerTreeHostImplTest, FarAwayQuadsDontNeedAA) {
root->AddChild(scoped_scrolling_layer.Pass());
gfx::Size content_layer_bounds(100000, 100);
- gfx::Size pile_tile_size(3000, 3000);
- scoped_refptr<FakePicturePileImpl> pile(FakePicturePileImpl::CreateFilledPile(
- pile_tile_size, content_layer_bounds));
+ scoped_refptr<FakeDisplayListRasterSource> raster_source(
+ FakeDisplayListRasterSource::CreateFilled(content_layer_bounds));
scoped_ptr<FakePictureLayerImpl> scoped_content_layer =
FakePictureLayerImpl::CreateWithRasterSource(host_impl_->pending_tree(),
- 3, pile);
+ 3, raster_source);
LayerImpl* content_layer = scoped_content_layer.get();
scrolling_layer->AddChild(scoped_content_layer.Pass());
content_layer->SetBounds(content_layer_bounds);
@@ -6066,6 +6339,7 @@ TEST_F(LayerTreeHostImplTest, FarAwayQuadsDontNeedAA) {
scrolling_layer->SetScrollClipLayer(root->id());
scrolling_layer->PushScrollOffsetFromMainThread(scroll_offset);
+ host_impl_->pending_tree()->BuildPropertyTreesForTesting();
host_impl_->ActivateSyncTree();
bool update_lcd_text = false;
@@ -6073,7 +6347,7 @@ TEST_F(LayerTreeHostImplTest, FarAwayQuadsDontNeedAA) {
ASSERT_EQ(1u, host_impl_->active_tree()->RenderSurfaceLayerList().size());
LayerTreeHostImpl::FrameData frame;
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
ASSERT_EQ(1u, frame.render_passes.size());
ASSERT_LE(1u, frame.render_passes[0]->quad_list.size());
@@ -6082,7 +6356,8 @@ TEST_F(LayerTreeHostImplTest, FarAwayQuadsDontNeedAA) {
bool clipped = false, force_aa = false;
gfx::QuadF device_layer_quad = MathUtil::MapQuad(
quad->shared_quad_state->quad_to_target_transform,
- gfx::QuadF(quad->shared_quad_state->visible_quad_layer_rect), &clipped);
+ gfx::QuadF(gfx::RectF(quad->shared_quad_state->visible_quad_layer_rect)),
+ &clipped);
EXPECT_FALSE(clipped);
bool antialiased =
GLRendererWithSetupQuadForAntialiasing::ShouldAntialiasQuad(
@@ -6110,7 +6385,7 @@ TEST_F(CompositorFrameMetadataTest, CompositorFrameAckCountsAsSwapComplete) {
SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
host_impl_->DidDrawAllLayers(frame);
}
@@ -6128,9 +6403,9 @@ class CountingSoftwareDevice : public SoftwareOutputDevice {
++frames_began_;
return SoftwareOutputDevice::BeginPaint(damage_rect);
}
- void EndPaint(SoftwareFrameData* frame_data) override {
+ void EndPaint() override {
+ SoftwareOutputDevice::EndPaint();
++frames_ended_;
- SoftwareOutputDevice::EndPaint(frame_data);
}
int frames_began_, frames_ended_;
@@ -6204,7 +6479,7 @@ TEST_F(LayerTreeHostImplTest,
SetupRootLayerImpl(root_layer.Pass());
LayerTreeHostImpl::FrameData frame;
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
host_impl_->DidDrawAllLayers(frame);
@@ -6220,9 +6495,9 @@ TEST_F(LayerTreeHostImplTest, DefaultMemoryAllocation) {
settings, this, &proxy_, &stats_instrumentation_, &shared_bitmap_manager_,
&gpu_memory_buffer_manager_, &task_graph_runner_, 0);
- scoped_ptr<OutputSurface> output_surface(
- FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create()));
- host_impl_->InitializeRenderer(output_surface.Pass());
+ output_surface_ =
+ FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create());
+ host_impl_->InitializeRenderer(output_surface_.get());
EXPECT_LT(0ul, host_impl_->memory_allocation_limit_bytes());
}
@@ -6283,7 +6558,8 @@ class LayerTreeHostImplTestPrepareTiles : public LayerTreeHostImplTest {
new FakeLayerTreeHostImpl(LayerTreeSettings(), &proxy_,
&shared_bitmap_manager_, &task_graph_runner_);
host_impl_.reset(fake_host_impl_);
- host_impl_->InitializeRenderer(CreateOutputSurface());
+ output_surface_ = CreateOutputSurface();
+ host_impl_->InitializeRenderer(output_surface_.get());
host_impl_->SetViewportSize(gfx::Size(10, 10));
}
@@ -6381,10 +6657,12 @@ TEST_F(LayerTreeHostImplTest, ShutdownReleasesContext) {
requests.push_back(CopyOutputRequest::CreateRequest(
base::Bind(&ShutdownReleasesContext_Callback)));
- host_impl_->active_tree()->root_layer()->PassCopyRequests(&requests);
+ LayerImpl* root = host_impl_->active_tree()->root_layer();
+ root->PassCopyRequests(&requests);
+ root->set_num_layer_or_descendant_with_copy_request(1);
LayerTreeHostImpl::FrameData frame;
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
host_impl_->DidDrawAllLayers(frame);
@@ -6447,7 +6725,7 @@ TEST_F(LayerTreeHostImplTest, TouchFlingShouldNotBubble) {
}
}
-TEST_F(LayerTreeHostImplTest, TouchFlingShouldLockToFirstScrolledLayer) {
+TEST_F(LayerTreeHostImplTest, TouchFlingShouldContinueScrollingCurrentLayer) {
// Scroll a child layer beyond its maximum scroll range and make sure the
// the scroll doesn't bubble up to the parent layer.
gfx::Size surface_size(10, 10);
@@ -6489,40 +6767,35 @@ TEST_F(LayerTreeHostImplTest, TouchFlingShouldLockToFirstScrolledLayer) {
ScrollInfoContains(*scroll_info, grand_child->id(), scroll_delta));
EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
- // The child should have received the bubbled delta, but the locked
- // scrolling layer should remain set as the grand child.
- EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
+ // The locked scrolling layer should remain set as the grand child.
+ EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
scroll_info = host_impl_->ProcessScrollDeltas();
- ASSERT_EQ(2u, scroll_info->scrolls.size());
+ ASSERT_EQ(1u, scroll_info->scrolls.size());
EXPECT_TRUE(
ScrollInfoContains(*scroll_info, grand_child->id(), scroll_delta));
- EXPECT_TRUE(ScrollInfoContains(*scroll_info, child->id(), scroll_delta));
+ ExpectNone(*scroll_info, child->id());
EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
- // The first |ScrollBy| after the fling should re-lock the scrolling
- // layer to the first layer that scrolled, which is the child.
EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
- EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
- EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
+ EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
+ EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
- // The child should have scrolled up to its limit.
+ // The child should not have scrolled.
scroll_info = host_impl_->ProcessScrollDeltas();
- ASSERT_EQ(2u, scroll_info->scrolls.size());
+ ASSERT_EQ(1u, scroll_info->scrolls.size());
EXPECT_TRUE(
ScrollInfoContains(*scroll_info, grand_child->id(), scroll_delta));
- EXPECT_TRUE(ScrollInfoContains(*scroll_info, child->id(),
- scroll_delta + scroll_delta));
+ ExpectNone(*scroll_info, child->id());
// As the locked layer is at it's limit, no further scrolling can occur.
EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
- EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
+ EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
host_impl_->ScrollEnd();
}
}
-TEST_F(LayerTreeHostImplTest, WheelFlingShouldBubble) {
- // When flinging via wheel, the root should eventually scroll (we should
- // bubble).
+TEST_F(LayerTreeHostImplTest, WheelFlingShouldntBubble) {
+ // When flinging via wheel, we shouldn't bubble.
gfx::Size surface_size(10, 10);
gfx::Size content_size(20, 20);
scoped_ptr<LayerImpl> root_clip =
@@ -6556,10 +6829,9 @@ TEST_F(LayerTreeHostImplTest, WheelFlingShouldBubble) {
scoped_ptr<ScrollAndScaleSet> scroll_info =
host_impl_->ProcessScrollDeltas();
- // The root should have scrolled.
- ASSERT_EQ(2u, scroll_info->scrolls.size());
- EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), root_scroll_id,
- gfx::Vector2d(0, 10)));
+ // The root shouldn't have scrolled.
+ ASSERT_EQ(1u, scroll_info->scrolls.size());
+ ExpectNone(*scroll_info.get(), root_scroll_id);
}
}
@@ -6776,12 +7048,12 @@ TEST_F(LayerTreeHostImplTest, LatencyInfoPassedToCompositorFrameMetadata) {
ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, 0);
scoped_ptr<SwapPromise> swap_promise(
new LatencyInfoSwapPromise(latency_info));
- host_impl_->active_tree()->QueueSwapPromise(swap_promise.Pass());
+ host_impl_->active_tree()->QueuePinnedSwapPromise(swap_promise.Pass());
host_impl_->SetNeedsRedraw();
gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
LayerTreeHostImpl::FrameData frame;
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
host_impl_->DidDrawAllLayers(frame);
EXPECT_TRUE(host_impl_->SwapBuffers(frame));
@@ -6828,7 +7100,7 @@ TEST_F(LayerTreeHostImplTest, SelectionBoundsPassedToCompositorFrameMetadata) {
gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
LayerTreeHostImpl::FrameData frame;
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
host_impl_->DrawLayers(&frame);
host_impl_->DidDrawAllLayers(frame);
EXPECT_TRUE(host_impl_->SwapBuffers(frame));
@@ -6981,8 +7253,12 @@ const int LayerTreeHostImplWithTopControlsTest::top_controls_height_ = 50;
TEST_F(LayerTreeHostImplWithTopControlsTest, NoIdleAnimations) {
SetupScrollAndContentsLayers(gfx::Size(100, 100))
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 10));
- host_impl_->Animate(base::TimeTicks());
+ BeginFrameArgs begin_frame_args =
+ CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
+ host_impl_->WillBeginImplFrame(begin_frame_args);
+ host_impl_->Animate();
EXPECT_FALSE(did_request_redraw_);
+ host_impl_->DidFinishImplFrame();
}
TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsHeightIsCommitted) {
@@ -7019,6 +7295,7 @@ TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationScheduling) {
}
TEST_F(LayerTreeHostImplWithTopControlsTest, ScrollHandledByTopControls) {
+ InputHandlerScrollResult result;
LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
host_impl_->SetViewportSize(gfx::Size(100, 100));
host_impl_->top_controls_manager()->UpdateTopControlsState(
@@ -7034,8 +7311,9 @@ TEST_F(LayerTreeHostImplWithTopControlsTest, ScrollHandledByTopControls) {
// Scroll just the top controls and verify that the scroll succeeds.
const float residue = 10;
float offset = top_controls_height_ - residue;
- EXPECT_TRUE(
- host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
+ result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset));
+ EXPECT_EQ(result.unused_scroll_delta, gfx::Vector2d(0, 0));
+ EXPECT_TRUE(result.did_scroll);
EXPECT_FLOAT_EQ(-offset,
host_impl_->top_controls_manager()->ControlsTopOffset());
EXPECT_EQ(gfx::Vector2dF().ToString(),
@@ -7044,8 +7322,9 @@ TEST_F(LayerTreeHostImplWithTopControlsTest, ScrollHandledByTopControls) {
// Scroll across the boundary
const float content_scroll = 20;
offset = residue + content_scroll;
- EXPECT_TRUE(
- host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
+ result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset));
+ EXPECT_TRUE(result.did_scroll);
+ EXPECT_EQ(result.unused_scroll_delta, gfx::Vector2d(0, 0));
EXPECT_EQ(-top_controls_height_,
host_impl_->top_controls_manager()->ControlsTopOffset());
EXPECT_EQ(gfx::Vector2dF(0, content_scroll).ToString(),
@@ -7053,8 +7332,9 @@ TEST_F(LayerTreeHostImplWithTopControlsTest, ScrollHandledByTopControls) {
// Now scroll back to the top of the content
offset = -content_scroll;
- EXPECT_TRUE(
- host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
+ result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset));
+ EXPECT_TRUE(result.did_scroll);
+ EXPECT_EQ(result.unused_scroll_delta, gfx::Vector2d(0, 0));
EXPECT_EQ(-top_controls_height_,
host_impl_->top_controls_manager()->ControlsTopOffset());
EXPECT_EQ(gfx::Vector2dF().ToString(),
@@ -7062,15 +7342,17 @@ TEST_F(LayerTreeHostImplWithTopControlsTest, ScrollHandledByTopControls) {
// And scroll the top controls completely into view
offset = -top_controls_height_;
- EXPECT_TRUE(
- host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
+ result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset));
+ EXPECT_TRUE(result.did_scroll);
+ EXPECT_EQ(result.unused_scroll_delta, gfx::Vector2d(0, 0));
EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
EXPECT_EQ(gfx::Vector2dF().ToString(),
scroll_layer->CurrentScrollOffset().ToString());
// And attempt to scroll past the end
- EXPECT_FALSE(
- host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
+ result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset));
+ EXPECT_FALSE(result.did_scroll);
+ EXPECT_EQ(result.unused_scroll_delta, gfx::Vector2d(0, -50));
EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
EXPECT_EQ(gfx::Vector2dF().ToString(),
scroll_layer->CurrentScrollOffset().ToString());
@@ -7078,6 +7360,37 @@ TEST_F(LayerTreeHostImplWithTopControlsTest, ScrollHandledByTopControls) {
host_impl_->ScrollEnd();
}
+TEST_F(LayerTreeHostImplWithTopControlsTest, WheelUnhandledByTopControls) {
+ SetupScrollAndContentsLayers(gfx::Size(100, 200));
+ host_impl_->SetViewportSize(gfx::Size(50, 100));
+ host_impl_->active_tree()->set_top_controls_shrink_blink_size(true);
+ host_impl_->top_controls_manager()->UpdateTopControlsState(BOTH, SHOWN,
+ false);
+ DrawFrame();
+
+ LayerImpl* viewport_layer = host_impl_->InnerViewportScrollLayer();
+
+ EXPECT_EQ(InputHandler::SCROLL_STARTED,
+ host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
+ EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
+ EXPECT_VECTOR_EQ(gfx::Vector2dF(), viewport_layer->CurrentScrollOffset());
+
+ // Wheel scrolls should not affect the top controls, and should pass
+ // directly through to the viewport.
+ const float delta = top_controls_height_;
+ EXPECT_TRUE(
+ host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, delta)).did_scroll);
+ EXPECT_FLOAT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
+ EXPECT_VECTOR_EQ(gfx::Vector2dF(0, delta),
+ viewport_layer->CurrentScrollOffset());
+
+ EXPECT_TRUE(
+ host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, delta)).did_scroll);
+ EXPECT_FLOAT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
+ EXPECT_VECTOR_EQ(gfx::Vector2dF(0, delta * 2),
+ viewport_layer->CurrentScrollOffset());
+}
+
TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationAtOrigin) {
LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
host_impl_->SetViewportSize(gfx::Size(100, 200));
@@ -7114,7 +7427,8 @@ TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationAtOrigin) {
// The top controls should properly animate until finished, despite the scroll
// offset being at the origin.
- base::TimeTicks animation_time = base::TimeTicks::Now();
+ BeginFrameArgs begin_frame_args = CreateBeginFrameArgsForTesting(
+ BEGINFRAME_FROM_HERE, base::TimeTicks::Now());
while (did_request_animate_) {
did_request_redraw_ = false;
did_request_animate_ = false;
@@ -7123,8 +7437,9 @@ TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationAtOrigin) {
float old_offset =
host_impl_->top_controls_manager()->ControlsTopOffset();
- animation_time += base::TimeDelta::FromMilliseconds(5);
- host_impl_->Animate(animation_time);
+ begin_frame_args.frame_time += base::TimeDelta::FromMilliseconds(5);
+ host_impl_->WillBeginImplFrame(begin_frame_args);
+ host_impl_->Animate();
EXPECT_EQ(gfx::Vector2dF().ToString(),
scroll_layer->CurrentScrollOffset().ToString());
@@ -7142,6 +7457,7 @@ TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationAtOrigin) {
EXPECT_TRUE(host_impl_->top_controls_manager()->animation());
EXPECT_TRUE(did_request_animate_);
}
+ host_impl_->DidFinishImplFrame();
}
EXPECT_FALSE(host_impl_->top_controls_manager()->animation());
}
@@ -7184,7 +7500,8 @@ TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationAfterScroll) {
EXPECT_FALSE(did_request_commit_);
// Animate the top controls to the limit.
- base::TimeTicks animation_time = base::TimeTicks::Now();
+ BeginFrameArgs begin_frame_args = CreateBeginFrameArgsForTesting(
+ BEGINFRAME_FROM_HERE, base::TimeTicks::Now());
while (did_request_animate_) {
did_request_redraw_ = false;
did_request_animate_ = false;
@@ -7193,8 +7510,9 @@ TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationAfterScroll) {
float old_offset =
host_impl_->top_controls_manager()->ControlsTopOffset();
- animation_time += base::TimeDelta::FromMilliseconds(5);
- host_impl_->Animate(animation_time);
+ begin_frame_args.frame_time += base::TimeDelta::FromMilliseconds(5);
+ host_impl_->WillBeginImplFrame(begin_frame_args);
+ host_impl_->Animate();
float new_offset =
host_impl_->top_controls_manager()->ControlsTopOffset();
@@ -7203,6 +7521,7 @@ TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationAfterScroll) {
EXPECT_TRUE(did_request_redraw_);
EXPECT_TRUE(did_request_commit_);
}
+ host_impl_->DidFinishImplFrame();
}
EXPECT_FALSE(host_impl_->top_controls_manager()->animation());
EXPECT_EQ(-top_controls_height_,
@@ -7248,7 +7567,8 @@ TEST_F(LayerTreeHostImplWithTopControlsTest,
EXPECT_FALSE(did_request_commit_);
// Animate the top controls to the limit.
- base::TimeTicks animation_time = base::TimeTicks::Now();
+ BeginFrameArgs begin_frame_args = CreateBeginFrameArgsForTesting(
+ BEGINFRAME_FROM_HERE, base::TimeTicks::Now());
while (did_request_animate_) {
did_request_redraw_ = false;
did_request_animate_ = false;
@@ -7256,8 +7576,9 @@ TEST_F(LayerTreeHostImplWithTopControlsTest,
float old_offset = host_impl_->top_controls_manager()->ControlsTopOffset();
- animation_time += base::TimeDelta::FromMilliseconds(5);
- host_impl_->Animate(animation_time);
+ begin_frame_args.frame_time += base::TimeDelta::FromMilliseconds(5);
+ host_impl_->WillBeginImplFrame(begin_frame_args);
+ host_impl_->Animate();
float new_offset = host_impl_->top_controls_manager()->ControlsTopOffset();
@@ -7265,6 +7586,7 @@ TEST_F(LayerTreeHostImplWithTopControlsTest,
EXPECT_TRUE(did_request_redraw_);
EXPECT_TRUE(did_request_commit_);
}
+ host_impl_->DidFinishImplFrame();
}
EXPECT_FALSE(host_impl_->top_controls_manager()->animation());
EXPECT_EQ(-top_controls_height_,
@@ -7273,7 +7595,7 @@ TEST_F(LayerTreeHostImplWithTopControlsTest,
TEST_F(LayerTreeHostImplWithTopControlsTest,
TopControlsScrollDeltaInOverScroll) {
- // test varifies that the overscroll delta should not have accumulated in
+ // Verifies that the overscroll delta should not have accumulated in
// the top controls if we do a hide and show without releasing finger.
LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
@@ -7402,9 +7724,6 @@ TEST_F(LayerTreeHostImplVirtualViewportTest, ScrollBothInnerAndOuterLayer) {
SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
- TestScrollOffsetDelegate scroll_delegate;
- host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
-
LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
DrawFrame();
@@ -7416,8 +7735,7 @@ TEST_F(LayerTreeHostImplVirtualViewportTest, ScrollBothInnerAndOuterLayer) {
gfx::ScrollOffset current_offset(70.f, 100.f);
- scroll_delegate.set_getter_return_value(current_offset);
- host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
+ host_impl_->SetSynchronousInputHandlerRootScrollOffset(current_offset);
EXPECT_EQ(gfx::ScrollOffset(25.f, 40.f), inner_scroll->MaxScrollOffset());
EXPECT_EQ(gfx::ScrollOffset(50.f, 80.f), outer_scroll->MaxScrollOffset());
@@ -7431,9 +7749,9 @@ TEST_F(LayerTreeHostImplVirtualViewportTest, ScrollBothInnerAndOuterLayer) {
}
TEST_F(LayerTreeHostImplVirtualViewportTest, FlingScrollBubblesToInner) {
- gfx::Size content_size = gfx::Size(100, 160);
- gfx::Size outer_viewport = gfx::Size(50, 80);
- gfx::Size inner_viewport = gfx::Size(25, 40);
+ gfx::Size content_size = gfx::Size(200, 320);
+ gfx::Size outer_viewport = gfx::Size(100, 160);
+ gfx::Size inner_viewport = gfx::Size(50, 80);
SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
@@ -7446,17 +7764,19 @@ TEST_F(LayerTreeHostImplVirtualViewportTest, FlingScrollBubblesToInner) {
EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
- // Make sure the fling goes to the outer viewport first
+ // Scrolling the viewport always sets the outer scroll layer as the
+ // currently scrolling layer.
EXPECT_EQ(InputHandler::SCROLL_STARTED,
host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
- EXPECT_EQ(outer_scroll, host_impl_->CurrentlyScrollingLayer());
+ EXPECT_EQ(inner_scroll, host_impl_->CurrentlyScrollingLayer());
EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
- EXPECT_EQ(outer_scroll, host_impl_->CurrentlyScrollingLayer());
+ EXPECT_EQ(inner_scroll, host_impl_->CurrentlyScrollingLayer());
- gfx::Vector2d scroll_delta(inner_viewport.width(), inner_viewport.height());
+ gfx::Vector2d scroll_delta(inner_viewport.width() / 2.f,
+ inner_viewport.height() / 2.f);
host_impl_->ScrollBy(gfx::Point(), scroll_delta);
- outer_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
- EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), outer_scroll);
+ inner_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
+ EXPECT_EQ(inner_scroll, host_impl_->CurrentlyScrollingLayer());
host_impl_->ScrollEnd();
EXPECT_EQ(nullptr, host_impl_->CurrentlyScrollingLayer());
@@ -7464,20 +7784,20 @@ TEST_F(LayerTreeHostImplVirtualViewportTest, FlingScrollBubblesToInner) {
EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
- // Fling past the outer viewport boundry, make sure inner viewport scrolls.
+ // Fling past the inner viewport boundry, make sure outer viewport scrolls.
EXPECT_EQ(InputHandler::SCROLL_STARTED,
host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
- EXPECT_EQ(outer_scroll, host_impl_->CurrentlyScrollingLayer());
+ EXPECT_EQ(inner_scroll, host_impl_->CurrentlyScrollingLayer());
EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
- EXPECT_EQ(outer_scroll, host_impl_->CurrentlyScrollingLayer());
+ EXPECT_EQ(inner_scroll, host_impl_->CurrentlyScrollingLayer());
host_impl_->ScrollBy(gfx::Point(), scroll_delta);
- outer_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
- EXPECT_EQ(outer_scroll, host_impl_->CurrentlyScrollingLayer());
+ inner_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
+ EXPECT_EQ(inner_scroll, host_impl_->CurrentlyScrollingLayer());
host_impl_->ScrollBy(gfx::Point(), scroll_delta);
- inner_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
- EXPECT_EQ(outer_scroll, host_impl_->CurrentlyScrollingLayer());
+ outer_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
+ EXPECT_EQ(inner_scroll, host_impl_->CurrentlyScrollingLayer());
host_impl_->ScrollEnd();
EXPECT_EQ(nullptr, host_impl_->CurrentlyScrollingLayer());
@@ -7489,9 +7809,9 @@ TEST_F(LayerTreeHostImplVirtualViewportTest, FlingScrollBubblesToInner) {
TEST_F(LayerTreeHostImplVirtualViewportTest,
DiagonalScrollBubblesPerfectlyToInner) {
- gfx::Size content_size = gfx::Size(100, 160);
- gfx::Size outer_viewport = gfx::Size(50, 80);
- gfx::Size inner_viewport = gfx::Size(25, 40);
+ gfx::Size content_size = gfx::Size(200, 320);
+ gfx::Size outer_viewport = gfx::Size(100, 160);
+ gfx::Size inner_viewport = gfx::Size(50, 80);
SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
@@ -7504,7 +7824,7 @@ TEST_F(LayerTreeHostImplVirtualViewportTest,
EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
- // Make sure the scroll goes to the outer viewport first.
+ // Make sure the scroll goes to the inner viewport first.
EXPECT_EQ(InputHandler::SCROLL_STARTED,
host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
@@ -7512,9 +7832,10 @@ TEST_F(LayerTreeHostImplVirtualViewportTest,
InputHandler::GESTURE));
// Scroll near the edge of the outer viewport.
- gfx::Vector2d scroll_delta(inner_viewport.width(), inner_viewport.height());
+ gfx::Vector2d scroll_delta(inner_viewport.width() / 2.f,
+ inner_viewport.height() / 2.f);
host_impl_->ScrollBy(gfx::Point(), scroll_delta);
- outer_expected += scroll_delta;
+ inner_expected += scroll_delta;
EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
InputHandler::GESTURE));
@@ -7539,7 +7860,7 @@ TEST_F(LayerTreeHostImplVirtualViewportTest,
}
TEST_F(LayerTreeHostImplVirtualViewportTest,
- TouchFlingCanLockToViewportLayerAfterBubbling) {
+ TouchFlingDoesntSwitchScrollingLayer) {
gfx::Size content_size = gfx::Size(100, 160);
gfx::Size outer_viewport = gfx::Size(50, 80);
gfx::Size inner_viewport = gfx::Size(25, 40);
@@ -7572,25 +7893,23 @@ TEST_F(LayerTreeHostImplVirtualViewportTest,
ScrollInfoContains(*scroll_info, child_scroll->id(), scroll_delta));
EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child_scroll);
- // The first |ScrollBy| after the fling should re-lock the scrolling
- // layer to the first layer that scrolled, the inner viewport scroll layer.
+ // The fling have no effect on the currently scrolling layer.
EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
- EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
- EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), inner_scroll);
+ EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
+ EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child_scroll);
EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
InputHandler::GESTURE));
- // The inner viewport should have scrolled up to its limit.
+ // The inner viewport shouldn't have scrolled.
scroll_info = host_impl_->ProcessScrollDeltas();
- ASSERT_EQ(2u, scroll_info->scrolls.size());
+ ASSERT_EQ(1u, scroll_info->scrolls.size());
EXPECT_TRUE(
ScrollInfoContains(*scroll_info, child_scroll->id(), scroll_delta));
- EXPECT_TRUE(
- ScrollInfoContains(*scroll_info, inner_scroll->id(), scroll_delta));
+ ExpectNone(*scroll_info, inner_scroll->id());
// As the locked layer is at its limit, no further scrolling can occur.
EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
- EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), inner_scroll);
+ EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child_scroll);
host_impl_->ScrollEnd();
EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(
gfx::Point(), InputHandler::GESTURE));
@@ -7625,6 +7944,32 @@ TEST_F(LayerTreeHostImplVirtualViewportTest,
host_impl_->ScrollEnd();
}
+TEST_F(LayerTreeHostImplVirtualViewportTest,
+ NoOverscrollWhenInnerViewportCantScroll) {
+ InputHandlerScrollResult scroll_result;
+ gfx::Size content_size = gfx::Size(100, 160);
+ gfx::Size outer_viewport = gfx::Size(50, 80);
+ gfx::Size inner_viewport = gfx::Size(25, 40);
+ SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
+ DrawFrame();
+
+ // Make inner viewport unscrollable.
+ LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
+ inner_scroll->set_user_scrollable_horizontal(false);
+ inner_scroll->set_user_scrollable_vertical(false);
+
+ // Ensure inner viewport doesn't react to scrolls (test it's unscrollable).
+ EXPECT_VECTOR_EQ(gfx::Vector2dF(), inner_scroll->CurrentScrollOffset());
+ EXPECT_EQ(InputHandler::SCROLL_STARTED,
+ host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
+ scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 100));
+ EXPECT_VECTOR_EQ(gfx::Vector2dF(), inner_scroll->CurrentScrollOffset());
+
+ // When inner viewport is unscrollable, a fling gives zero overscroll.
+ EXPECT_FALSE(scroll_result.did_overscroll_root);
+ EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
+}
+
class LayerTreeHostImplWithImplicitLimitsTest : public LayerTreeHostImplTest {
public:
void SetUp() override {
@@ -7684,17 +8029,26 @@ TEST_F(LayerTreeHostImplTest, ScrollAnimated) {
base::TimeTicks start_time =
base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
+ BeginFrameArgs begin_frame_args =
+ CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
+
EXPECT_EQ(InputHandler::SCROLL_STARTED,
host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
LayerImpl* scrolling_layer = host_impl_->CurrentlyScrollingLayer();
- host_impl_->Animate(start_time);
+ begin_frame_args.frame_time = start_time;
+ host_impl_->WillBeginImplFrame(begin_frame_args);
+ host_impl_->Animate();
host_impl_->UpdateAnimationState(true);
EXPECT_EQ(gfx::ScrollOffset(), scrolling_layer->CurrentScrollOffset());
+ host_impl_->DidFinishImplFrame();
- host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(50));
+ begin_frame_args.frame_time =
+ start_time + base::TimeDelta::FromMilliseconds(50);
+ host_impl_->WillBeginImplFrame(begin_frame_args);
+ host_impl_->Animate();
host_impl_->UpdateAnimationState(true);
float y = scrolling_layer->CurrentScrollOffset().y();
@@ -7703,20 +8057,29 @@ TEST_F(LayerTreeHostImplTest, ScrollAnimated) {
// Update target.
EXPECT_EQ(InputHandler::SCROLL_STARTED,
host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
+ host_impl_->DidFinishImplFrame();
- host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(200));
+ begin_frame_args.frame_time =
+ start_time + base::TimeDelta::FromMilliseconds(200);
+ host_impl_->WillBeginImplFrame(begin_frame_args);
+ host_impl_->Animate();
host_impl_->UpdateAnimationState(true);
y = scrolling_layer->CurrentScrollOffset().y();
EXPECT_TRUE(y > 50 && y < 100);
EXPECT_EQ(scrolling_layer, host_impl_->CurrentlyScrollingLayer());
+ host_impl_->DidFinishImplFrame();
- host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(250));
+ begin_frame_args.frame_time =
+ start_time + base::TimeDelta::FromMilliseconds(250);
+ host_impl_->WillBeginImplFrame(begin_frame_args);
+ host_impl_->Animate();
host_impl_->UpdateAnimationState(true);
EXPECT_VECTOR_EQ(gfx::ScrollOffset(0, 100),
scrolling_layer->CurrentScrollOffset());
EXPECT_EQ(NULL, host_impl_->CurrentlyScrollingLayer());
+ host_impl_->DidFinishImplFrame();
}
// Evolved from LayerTreeHostImplTest.ScrollAnimated.
@@ -7727,17 +8090,26 @@ TEST_F(LayerTreeHostImplTimelinesTest, ScrollAnimated) {
base::TimeTicks start_time =
base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
+ BeginFrameArgs begin_frame_args =
+ CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
+
EXPECT_EQ(InputHandler::SCROLL_STARTED,
host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
LayerImpl* scrolling_layer = host_impl_->CurrentlyScrollingLayer();
- host_impl_->Animate(start_time);
+ begin_frame_args.frame_time = start_time;
+ host_impl_->WillBeginImplFrame(begin_frame_args);
+ host_impl_->Animate();
host_impl_->UpdateAnimationState(true);
EXPECT_EQ(gfx::ScrollOffset(), scrolling_layer->CurrentScrollOffset());
+ host_impl_->DidFinishImplFrame();
- host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(50));
+ begin_frame_args.frame_time =
+ start_time + base::TimeDelta::FromMilliseconds(50);
+ host_impl_->WillBeginImplFrame(begin_frame_args);
+ host_impl_->Animate();
host_impl_->UpdateAnimationState(true);
float y = scrolling_layer->CurrentScrollOffset().y();
@@ -7746,37 +8118,46 @@ TEST_F(LayerTreeHostImplTimelinesTest, ScrollAnimated) {
// Update target.
EXPECT_EQ(InputHandler::SCROLL_STARTED,
host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
+ host_impl_->DidFinishImplFrame();
- host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(200));
+ begin_frame_args.frame_time =
+ start_time + base::TimeDelta::FromMilliseconds(200);
+ host_impl_->WillBeginImplFrame(begin_frame_args);
+ host_impl_->Animate();
host_impl_->UpdateAnimationState(true);
y = scrolling_layer->CurrentScrollOffset().y();
EXPECT_TRUE(y > 50 && y < 100);
EXPECT_EQ(scrolling_layer, host_impl_->CurrentlyScrollingLayer());
+ host_impl_->DidFinishImplFrame();
- host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(250));
+ begin_frame_args.frame_time =
+ start_time + base::TimeDelta::FromMilliseconds(250);
+ host_impl_->WillBeginImplFrame(begin_frame_args);
+ host_impl_->Animate();
host_impl_->UpdateAnimationState(true);
EXPECT_VECTOR_EQ(gfx::ScrollOffset(0, 100),
scrolling_layer->CurrentScrollOffset());
EXPECT_EQ(NULL, host_impl_->CurrentlyScrollingLayer());
+ host_impl_->DidFinishImplFrame();
}
TEST_F(LayerTreeHostImplTest, InvalidLayerNotAddedToRasterQueue) {
host_impl_->CreatePendingTree();
Region empty_invalidation;
- scoped_refptr<RasterSource> pile_with_tiles(
- FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
- gfx::Size(10, 10)));
+ scoped_refptr<RasterSource> raster_source_with_tiles(
+ FakeDisplayListRasterSource::CreateFilled(gfx::Size(10, 10)));
scoped_ptr<FakePictureLayerImpl> layer =
FakePictureLayerImpl::Create(host_impl_->pending_tree(), 11);
layer->SetBounds(gfx::Size(10, 10));
layer->set_gpu_raster_max_texture_size(host_impl_->device_viewport_size());
layer->SetDrawsContent(true);
- layer->tilings()->AddTiling(1.0f, pile_with_tiles);
- layer->UpdateRasterSource(pile_with_tiles, &empty_invalidation, nullptr);
+ layer->tilings()->AddTiling(1.0f, raster_source_with_tiles);
+ layer->UpdateRasterSource(raster_source_with_tiles, &empty_invalidation,
+ nullptr);
layer->tilings()->tiling_at(0)->set_resolution(
TileResolution::HIGH_RESOLUTION);
layer->tilings()->tiling_at(0)->CreateAllTilesForTesting();
@@ -7862,7 +8243,7 @@ TEST_F(LayerTreeHostImplTest, WheelScrollWithPageScaleFactorOnInnerLayer) {
{
host_impl_->active_tree()->PushPageScaleFromMainThread(
page_scale_factor, min_page_scale, max_page_scale);
- host_impl_->SetPageScaleOnActiveTree(page_scale_factor);
+ host_impl_->active_tree()->SetPageScaleOnActiveTree(page_scale_factor);
scroll_layer->SetScrollDelta(gfx::Vector2d());
float page_scale_delta = 2.f;
@@ -8054,8 +8435,6 @@ class FakeVideoFrameController : public VideoFrameController {
};
TEST_F(LayerTreeHostImplTest, AddVideoFrameControllerInsideFrame) {
- host_impl_->DidFinishImplFrame();
-
BeginFrameArgs begin_frame_args =
CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
FakeVideoFrameController controller;
@@ -8079,8 +8458,6 @@ TEST_F(LayerTreeHostImplTest, AddVideoFrameControllerInsideFrame) {
}
TEST_F(LayerTreeHostImplTest, AddVideoFrameControllerOutsideFrame) {
- host_impl_->DidFinishImplFrame();
-
BeginFrameArgs begin_frame_args =
CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
FakeVideoFrameController controller;
@@ -8169,7 +8546,8 @@ class MockReclaimResourcesOutputSurface : public FakeOutputSurface {
public:
static scoped_ptr<MockReclaimResourcesOutputSurface> Create3d() {
return make_scoped_ptr(new MockReclaimResourcesOutputSurface(
- TestContextProvider::Create(), TestContextProvider::Create(), false));
+ TestContextProvider::Create(), TestContextProvider::CreateWorker(),
+ false));
}
MOCK_METHOD0(ForceReclaimResources, void());
diff --git a/chromium/cc/trees/layer_tree_host_perftest.cc b/chromium/cc/trees/layer_tree_host_perftest.cc
index eb8183fadf2..845b1305e59 100644
--- a/chromium/cc/trees/layer_tree_host_perftest.cc
+++ b/chromium/cc/trees/layer_tree_host_perftest.cc
@@ -44,7 +44,8 @@ class LayerTreeHostPerfTest : public LayerTreeTest {
}
void InitializeSettings(LayerTreeSettings* settings) override {
- settings->renderer_settings.disable_gpu_vsync = true;
+ settings->wait_for_beginframe_interval = false;
+ settings->renderer_settings.disable_display_vsync = true;
}
void BeginTest() override {
diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc b/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc
index e2715e3907c..688c9fbc1ca 100644
--- a/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc
+++ b/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc
@@ -6,6 +6,8 @@
#include "cc/layers/solid_color_layer.h"
#include "cc/test/layer_tree_pixel_resource_test.h"
#include "cc/test/pixel_comparator.h"
+#include "third_party/skia/include/core/SkImage.h"
+#include "third_party/skia/include/core/SkSurface.h"
#if !defined(OS_ANDROID)
@@ -127,21 +129,23 @@ class LayerTreeHostBlendingPixelTest : public LayerTreeHostPixelResourceTest {
// Draw the backdrop with horizontal lanes.
const int kLaneWidth = width;
const int kLaneHeight = height / kCSSTestColorsCount;
- SkBitmap backing_store;
- backing_store.allocN32Pixels(width, height);
- SkCanvas canvas(backing_store);
- canvas.clear(SK_ColorTRANSPARENT);
+ skia::RefPtr<SkSurface> backing_store =
+ skia::AdoptRef(SkSurface::NewRasterN32Premul(width, height));
+ SkCanvas* canvas = backing_store->getCanvas();
+ canvas->clear(SK_ColorTRANSPARENT);
for (int i = 0; i < kCSSTestColorsCount; ++i) {
SkPaint paint;
paint.setColor(kCSSTestColors[i]);
- canvas.drawRect(
+ canvas->drawRect(
SkRect::MakeXYWH(0, i * kLaneHeight, kLaneWidth, kLaneHeight), paint);
}
scoped_refptr<PictureImageLayer> layer =
PictureImageLayer::Create(layer_settings());
layer->SetIsDrawable(true);
layer->SetBounds(gfx::Size(width, height));
- layer->SetBitmap(backing_store);
+ skia::RefPtr<const SkImage> image =
+ skia::AdoptRef(backing_store->newImageSnapshot());
+ layer->SetImage(image.Pass());
return layer;
}
@@ -154,18 +158,19 @@ class LayerTreeHostBlendingPixelTest : public LayerTreeHostPixelResourceTest {
mask->SetIsMask(true);
mask->SetBounds(bounds);
- SkBitmap bitmap;
- bitmap.allocN32Pixels(bounds.width(), bounds.height());
- SkCanvas canvas(bitmap);
+ skia::RefPtr<SkSurface> surface = skia::AdoptRef(
+ SkSurface::NewRasterN32Premul(bounds.width(), bounds.height()));
+ SkCanvas* canvas = surface->getCanvas();
SkPaint paint;
paint.setColor(SK_ColorWHITE);
- canvas.clear(SK_ColorTRANSPARENT);
- canvas.drawRect(SkRect::MakeXYWH(kMaskOffset,
- kMaskOffset,
- bounds.width() - kMaskOffset * 2,
- bounds.height() - kMaskOffset * 2),
- paint);
- mask->SetBitmap(bitmap);
+ canvas->clear(SK_ColorTRANSPARENT);
+ canvas->drawRect(SkRect::MakeXYWH(kMaskOffset, kMaskOffset,
+ bounds.width() - kMaskOffset * 2,
+ bounds.height() - kMaskOffset * 2),
+ paint);
+ skia::RefPtr<const SkImage> image =
+ skia::AdoptRef(surface->newImageSnapshot());
+ mask->SetImage(image.Pass());
layer->SetMaskLayer(mask.get());
}
@@ -272,7 +277,7 @@ class LayerTreeHostBlendingPixelTest : public LayerTreeHostPixelResourceTest {
};
TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithRoot_GL) {
- RunBlendingWithRootPixelTestType(GL_ASYNC_UPLOAD_2D_DRAW);
+ RunBlendingWithRootPixelTestType(GL_ZERO_COPY_RECT_DRAW);
}
TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithRoot_Software) {
@@ -284,7 +289,7 @@ TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithBackgroundFilter) {
const int kLaneHeight = kLaneWidth;
const int kRootWidth = (kBlendModesCount + 2) * kLaneWidth;
const int kRootHeight = 2 * kLaneWidth + kLaneHeight;
- InitializeFromTestCase(GL_ASYNC_UPLOAD_2D_DRAW);
+ InitializeFromTestCase(GL_ZERO_COPY_RECT_DRAW);
scoped_refptr<SolidColorLayer> background =
CreateSolidColorLayer(gfx::Rect(kRootWidth, kRootHeight), kCSSOrange);
@@ -309,7 +314,7 @@ TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithBackgroundFilter) {
}
TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithTransparent_GL) {
- RunBlendingWithTransparentPixelTestType(GL_ASYNC_UPLOAD_2D_DRAW);
+ RunBlendingWithTransparentPixelTestType(GL_ZERO_COPY_RECT_DRAW);
}
TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithTransparent_Software) {
@@ -318,7 +323,7 @@ TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithTransparent_Software) {
// Tests for render passes
TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithRenderPass_GL) {
- RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW,
+ RunBlendingWithRenderPass(GL_ZERO_COPY_RECT_DRAW,
FILE_PATH_LITERAL("blending_render_pass.png"), 0);
}
@@ -328,7 +333,7 @@ TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithRenderPass_Software) {
}
TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithRenderPassAA_GL) {
- RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW,
+ RunBlendingWithRenderPass(GL_ZERO_COPY_RECT_DRAW,
FILE_PATH_LITERAL("blending_render_pass.png"),
kUseAntialiasing);
}
@@ -340,7 +345,7 @@ TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithRenderPassAA_Software) {
}
TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithRenderPassWithMask_GL) {
- RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW,
+ RunBlendingWithRenderPass(GL_ZERO_COPY_RECT_DRAW,
FILE_PATH_LITERAL("blending_render_pass_mask.png"),
kUseMasks);
}
@@ -352,7 +357,7 @@ TEST_F(LayerTreeHostBlendingPixelTest,
}
TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithRenderPassWithMaskAA_GL) {
- RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW,
+ RunBlendingWithRenderPass(GL_ZERO_COPY_RECT_DRAW,
FILE_PATH_LITERAL("blending_render_pass_mask.png"),
kUseMasks | kUseAntialiasing);
}
@@ -365,7 +370,7 @@ TEST_F(LayerTreeHostBlendingPixelTest,
}
TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithRenderPassColorMatrix_GL) {
- RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW,
+ RunBlendingWithRenderPass(GL_ZERO_COPY_RECT_DRAW,
FILE_PATH_LITERAL("blending_render_pass.png"),
kUseColorMatrix);
}
@@ -377,7 +382,7 @@ TEST_F(LayerTreeHostBlendingPixelTest,
}
TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithRenderPassColorMatrixAA_GL) {
- RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW,
+ RunBlendingWithRenderPass(GL_ZERO_COPY_RECT_DRAW,
FILE_PATH_LITERAL("blending_render_pass.png"),
kUseAntialiasing | kUseColorMatrix);
}
@@ -391,7 +396,7 @@ TEST_F(LayerTreeHostBlendingPixelTest,
TEST_F(LayerTreeHostBlendingPixelTest,
BlendingWithRenderPassWithMaskColorMatrix_GL) {
- RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW,
+ RunBlendingWithRenderPass(GL_ZERO_COPY_RECT_DRAW,
FILE_PATH_LITERAL("blending_render_pass_mask.png"),
kUseMasks | kUseColorMatrix);
}
@@ -405,7 +410,7 @@ TEST_F(LayerTreeHostBlendingPixelTest,
TEST_F(LayerTreeHostBlendingPixelTest,
BlendingWithRenderPassWithMaskColorMatrixAA_GL) {
- RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW,
+ RunBlendingWithRenderPass(GL_ZERO_COPY_RECT_DRAW,
FILE_PATH_LITERAL("blending_render_pass_mask.png"),
kUseMasks | kUseAntialiasing | kUseColorMatrix);
}
@@ -419,20 +424,20 @@ TEST_F(LayerTreeHostBlendingPixelTest,
// Tests for render passes forcing shaders for all the blend modes.
TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithRenderPassShaders_GL) {
- RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW,
+ RunBlendingWithRenderPass(GL_ZERO_COPY_RECT_DRAW,
FILE_PATH_LITERAL("blending_render_pass.png"),
kForceShaders);
}
TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithRenderPassShadersAA_GL) {
- RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW,
+ RunBlendingWithRenderPass(GL_ZERO_COPY_RECT_DRAW,
FILE_PATH_LITERAL("blending_render_pass.png"),
kUseAntialiasing | kForceShaders);
}
TEST_F(LayerTreeHostBlendingPixelTest,
BlendingWithRenderPassShadersWithMask_GL) {
- RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW,
+ RunBlendingWithRenderPass(GL_ZERO_COPY_RECT_DRAW,
FILE_PATH_LITERAL("blending_render_pass_mask.png"),
kUseMasks | kForceShaders);
}
@@ -446,7 +451,7 @@ TEST_F(LayerTreeHostBlendingPixelTest,
TEST_F(LayerTreeHostBlendingPixelTest,
BlendingWithRenderPassShadersWithMaskAA_GL) {
- RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW,
+ RunBlendingWithRenderPass(GL_ZERO_COPY_RECT_DRAW,
FILE_PATH_LITERAL("blending_render_pass_mask.png"),
kUseMasks | kUseAntialiasing | kForceShaders);
}
@@ -460,21 +465,21 @@ TEST_F(LayerTreeHostBlendingPixelTest,
TEST_F(LayerTreeHostBlendingPixelTest,
BlendingWithRenderPassShadersColorMatrix_GL) {
- RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW,
+ RunBlendingWithRenderPass(GL_ZERO_COPY_RECT_DRAW,
FILE_PATH_LITERAL("blending_render_pass.png"),
kUseColorMatrix | kForceShaders);
}
TEST_F(LayerTreeHostBlendingPixelTest,
BlendingWithRenderPassShadersColorMatrixAA_GL) {
- RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW,
+ RunBlendingWithRenderPass(GL_ZERO_COPY_RECT_DRAW,
FILE_PATH_LITERAL("blending_render_pass.png"),
kUseAntialiasing | kUseColorMatrix | kForceShaders);
}
TEST_F(LayerTreeHostBlendingPixelTest,
BlendingWithRenderPassShadersWithMaskColorMatrix_GL) {
- RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW,
+ RunBlendingWithRenderPass(GL_ZERO_COPY_RECT_DRAW,
FILE_PATH_LITERAL("blending_render_pass_mask.png"),
kUseMasks | kUseColorMatrix | kForceShaders);
}
@@ -489,7 +494,7 @@ TEST_F(LayerTreeHostBlendingPixelTest,
TEST_F(LayerTreeHostBlendingPixelTest,
BlendingWithRenderPassShadersWithMaskColorMatrixAA_GL) {
RunBlendingWithRenderPass(
- GL_ASYNC_UPLOAD_2D_DRAW,
+ GL_ZERO_COPY_RECT_DRAW,
FILE_PATH_LITERAL("blending_render_pass_mask.png"),
kUseMasks | kUseAntialiasing | kUseColorMatrix | kForceShaders);
}
diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_filters.cc b/chromium/cc/trees/layer_tree_host_pixeltest_filters.cc
index dd3cf733144..a98b08bbdf7 100644
--- a/chromium/cc/trees/layer_tree_host_pixeltest_filters.cc
+++ b/chromium/cc/trees/layer_tree_host_pixeltest_filters.cc
@@ -277,16 +277,87 @@ TEST_F(ImageFilterClippedPixelTest, ImageFilterClipped_Software) {
RunPixelTestType(PIXEL_TEST_SOFTWARE);
}
-TEST_F(LayerTreeHostFiltersPixelTest, ImageFilterScaled_GL) {
- scoped_refptr<SolidColorLayer> background =
- CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorWHITE);
+class ImageScaledBackgroundFilter : public LayerTreeHostFiltersPixelTest {
+ protected:
+ void RunPixelTestType(PixelTestType test_type, base::FilePath image_name) {
+ scoped_refptr<SolidColorLayer> background =
+ CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorWHITE);
+
+ gfx::Rect rect(50, 50, 100, 100);
+
+ const int kInset = 3;
+ for (int i = 0; !rect.IsEmpty(); ++i) {
+ scoped_refptr<SolidColorLayer> layer =
+ CreateSolidColorLayer(rect, (i & 1) ? SK_ColorWHITE : SK_ColorRED);
+
+ gfx::Transform transform;
+ transform.Translate(rect.width() / 2.0, rect.height() / 2.0);
+ transform.RotateAboutZAxis(30.0);
+ transform.Translate(-rect.width() / 2.0, -rect.height() / 2.0);
+ layer->SetTransform(transform);
+
+ background->AddChild(layer);
- gfx::Rect rect(50, 50, 100, 100);
+ rect.Inset(kInset, kInset);
+ }
+
+ scoped_refptr<SolidColorLayer> filter =
+ CreateSolidColorLayer(gfx::Rect(100, 0, 100, 200), SK_ColorTRANSPARENT);
+
+ background->AddChild(filter);
+
+ // Apply a scale to |background| so that we can see any scaling artifacts
+ // that may appear.
+ gfx::Transform background_transform;
+ static float scale = 1.1f;
+ background_transform.Scale(scale, scale);
+ background->SetTransform(background_transform);
+
+ FilterOperations filters;
+ filters.Append(FilterOperation::CreateGrayscaleFilter(1.0f));
+ filter->SetBackgroundFilters(filters);
+
+#if defined(OS_WIN)
+ // Windows has 153 pixels off by at most 2: crbug.com/225027
+ float percentage_pixels_large_error = 0.3825f; // 153px / (200*200)
+ float percentage_pixels_small_error = 0.0f;
+ float average_error_allowed_in_bad_pixels = 1.f;
+ int large_error_allowed = 2;
+ int small_error_allowed = 0;
+ pixel_comparator_.reset(new FuzzyPixelComparator(
+ true, // discard_alpha
+ percentage_pixels_large_error, percentage_pixels_small_error,
+ average_error_allowed_in_bad_pixels, large_error_allowed,
+ small_error_allowed));
+#endif
+
+ RunPixelTest(test_type, background, image_name);
+ }
+};
+
+TEST_F(ImageScaledBackgroundFilter, ImageFilterScaled_GL) {
+ RunPixelTestType(PIXEL_TEST_GL,
+ base::FilePath(FILE_PATH_LITERAL(
+ "background_filter_on_scaled_layer_gl.png")));
+}
+
+TEST_F(ImageScaledBackgroundFilter, ImageFilterScaled_Software) {
+ RunPixelTestType(PIXEL_TEST_SOFTWARE,
+ base::FilePath(FILE_PATH_LITERAL(
+ "background_filter_on_scaled_layer_sw.png")));
+}
+
+class ImageBackgroundFilter : public LayerTreeHostFiltersPixelTest {
+ protected:
+ void RunPixelTestType(PixelTestType test_type, base::FilePath image_name) {
+ // Add a white background with a rotated red rect in the center.
+ scoped_refptr<SolidColorLayer> background =
+ CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorWHITE);
+
+ gfx::Rect rect(50, 50, 100, 100);
- const int kInset = 3;
- for (int i = 0; !rect.IsEmpty(); ++i) {
scoped_refptr<SolidColorLayer> layer =
- CreateSolidColorLayer(rect, (i & 1) ? SK_ColorWHITE : SK_ColorRED);
+ CreateSolidColorLayer(rect, SK_ColorRED);
gfx::Transform transform;
transform.Translate(rect.width() / 2.0, rect.height() / 2.0);
@@ -296,42 +367,50 @@ TEST_F(LayerTreeHostFiltersPixelTest, ImageFilterScaled_GL) {
background->AddChild(layer);
- rect.Inset(kInset, kInset);
- }
+ // Add a slightly transparent blue layer.
+ scoped_refptr<SolidColorLayer> filter =
+ CreateSolidColorLayer(gfx::Rect(100, 0, 100, 200), 0x220000FF);
- scoped_refptr<SolidColorLayer> filter =
- CreateSolidColorLayer(gfx::Rect(100, 0, 100, 200), SK_ColorTRANSPARENT);
+ // Add some rotation so that we can see that it blurs only under the layer.
+ gfx::Transform transform_filter;
+ transform_filter.RotateAboutZAxis(10.0);
+ filter->SetTransform(transform_filter);
- background->AddChild(filter);
+ background->AddChild(filter);
- // Apply a scale to |background| so that we can see any scaling artifacts that
- // may appear.
- gfx::Transform background_transform;
- static float scale = 1.1f;
- background_transform.Scale(scale, scale);
- background->SetTransform(background_transform);
-
- FilterOperations filters;
- filters.Append(FilterOperation::CreateGrayscaleFilter(1.0f));
- filter->SetBackgroundFilters(filters);
+ // Add a blur filter to the blue layer.
+ FilterOperations filters;
+ filters.Append(FilterOperation::CreateBlurFilter(5.0f));
+ filter->SetBackgroundFilters(filters);
#if defined(OS_WIN)
- // Windows has 153 pixels off by at most 2: crbug.com/225027
- float percentage_pixels_large_error = 0.3825f; // 153px / (200*200)
- float percentage_pixels_small_error = 0.0f;
- float average_error_allowed_in_bad_pixels = 1.f;
- int large_error_allowed = 2;
- int small_error_allowed = 0;
- pixel_comparator_.reset(new FuzzyPixelComparator(
- true, // discard_alpha
- percentage_pixels_large_error, percentage_pixels_small_error,
- average_error_allowed_in_bad_pixels, large_error_allowed,
- small_error_allowed));
+ // Windows has 994 pixels off by at most 2: crbug.com/225027
+ float percentage_pixels_large_error = 2.4825f; // 994px / (200*200)
+ float percentage_pixels_small_error = 0.0f;
+ float average_error_allowed_in_bad_pixels = 1.f;
+ int large_error_allowed = 2;
+ int small_error_allowed = 0;
+ pixel_comparator_.reset(new FuzzyPixelComparator(
+ true, // discard_alpha
+ percentage_pixels_large_error, percentage_pixels_small_error,
+ average_error_allowed_in_bad_pixels, large_error_allowed,
+ small_error_allowed));
#endif
- // TODO(hendrikw): Enable test in software as well: crbug.com/432157
- RunPixelTest(PIXEL_TEST_GL, background,
- base::FilePath(FILE_PATH_LITERAL("filter_on_scaled_layer.png")));
+ RunPixelTest(test_type, background, image_name);
+ }
+};
+
+TEST_F(ImageBackgroundFilter, BackgroundFilterRotated_GL) {
+ RunPixelTestType(
+ PIXEL_TEST_GL,
+ base::FilePath(FILE_PATH_LITERAL("background_filter_rotated_gl.png")));
+}
+
+TEST_F(ImageBackgroundFilter, BackgroundFilterRotated_Software) {
+ RunPixelTestType(
+ PIXEL_TEST_SOFTWARE,
+ base::FilePath(FILE_PATH_LITERAL("background_filter_rotated_sw.png")));
}
class ImageScaledRenderSurface : public LayerTreeHostFiltersPixelTest {
diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc b/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc
index 6a4bebd4f35..ce9dde54c4d 100644
--- a/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc
+++ b/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc
@@ -7,8 +7,13 @@
#include "cc/layers/picture_image_layer.h"
#include "cc/layers/picture_layer.h"
#include "cc/layers/solid_color_layer.h"
+#include "cc/playback/display_item_list_settings.h"
+#include "cc/playback/drawing_display_item.h"
#include "cc/test/layer_tree_pixel_resource_test.h"
#include "cc/test/pixel_comparator.h"
+#include "third_party/skia/include/core/SkImage.h"
+#include "third_party/skia/include/core/SkPictureRecorder.h"
+#include "third_party/skia/include/core/SkSurface.h"
#if !defined(OS_ANDROID)
@@ -25,10 +30,25 @@ class MaskContentLayerClient : public ContentLayerClient {
~MaskContentLayerClient() override {}
bool FillsBoundsCompletely() const override { return false; }
+ size_t GetApproximateUnsharedMemoryUsage() const override { return 0; }
+ // TODO(pdr): Remove PaintContents as all calls should go through
+ // PaintContentsToDisplayList.
void PaintContents(SkCanvas* canvas,
const gfx::Rect& rect,
PaintingControlSetting picture_control) override {
+ scoped_refptr<DisplayItemList> contents =
+ PaintContentsToDisplayList(rect, picture_control);
+ contents->Raster(canvas, nullptr, rect, 1.0f);
+ }
+
+ scoped_refptr<DisplayItemList> PaintContentsToDisplayList(
+ const gfx::Rect& clip,
+ PaintingControlSetting picture_control) override {
+ SkPictureRecorder recorder;
+ skia::RefPtr<SkCanvas> canvas = skia::SharePtr(
+ recorder.beginRecording(gfx::RectToSkRect(gfx::Rect(bounds_))));
+
SkPaint paint;
paint.setStyle(SkPaint::kStroke_Style);
paint.setStrokeWidth(SkIntToScalar(2));
@@ -44,13 +64,17 @@ class MaskContentLayerClient : public ContentLayerClient {
paint);
inset_rect.Inset(3, 3, 2, 2);
}
- }
- scoped_refptr<DisplayItemList> PaintContentsToDisplayList(
- const gfx::Rect& clip,
- PaintingControlSetting picture_control) override {
- NOTIMPLEMENTED();
- return nullptr;
+ scoped_refptr<DisplayItemList> display_list =
+ DisplayItemList::Create(clip, DisplayItemListSettings());
+ auto* item = display_list->CreateAndAppendItem<DrawingDisplayItem>();
+
+ skia::RefPtr<SkPicture> picture =
+ skia::AdoptRef(recorder.endRecordingAsPicture());
+ item->SetNew(picture.Pass());
+
+ display_list->Finalize();
+ return display_list;
}
private:
@@ -90,14 +114,16 @@ TEST_P(LayerTreeHostMasksPixelTest, ImageMaskOfLayer) {
mask->SetIsMask(true);
mask->SetBounds(mask_bounds);
- SkBitmap bitmap;
- bitmap.allocN32Pixels(200, 200);
- SkCanvas canvas(bitmap);
- canvas.scale(SkIntToScalar(4), SkIntToScalar(4));
+ skia::RefPtr<SkSurface> surface =
+ skia::AdoptRef(SkSurface::NewRasterN32Premul(200, 200));
+ SkCanvas* canvas = surface->getCanvas();
+ canvas->scale(SkIntToScalar(4), SkIntToScalar(4));
MaskContentLayerClient client(mask_bounds);
- client.PaintContents(&canvas, gfx::Rect(mask_bounds),
+ client.PaintContents(canvas, gfx::Rect(mask_bounds),
ContentLayerClient::PAINTING_BEHAVIOR_NORMAL);
- mask->SetBitmap(bitmap);
+ skia::RefPtr<const SkImage> image =
+ skia::AdoptRef(surface->newImageSnapshot());
+ mask->SetImage(image.Pass());
scoped_refptr<SolidColorLayer> green = CreateSolidColorLayerWithBorder(
gfx::Rect(25, 25, 50, 50), kCSSGreen, 1, SK_ColorBLACK);
@@ -292,9 +318,23 @@ class CheckerContentLayerClient : public ContentLayerClient {
: bounds_(bounds), color_(color), vertical_(vertical) {}
~CheckerContentLayerClient() override {}
bool FillsBoundsCompletely() const override { return false; }
+ size_t GetApproximateUnsharedMemoryUsage() const override { return 0; }
+ // TODO(pdr): Remove PaintContents as all calls should go through
+ // PaintContentsToDisplayList.
void PaintContents(SkCanvas* canvas,
const gfx::Rect& rect,
PaintingControlSetting picture_control) override {
+ scoped_refptr<DisplayItemList> contents =
+ PaintContentsToDisplayList(rect, picture_control);
+ contents->Raster(canvas, nullptr, rect, 1.0f);
+ }
+ scoped_refptr<DisplayItemList> PaintContentsToDisplayList(
+ const gfx::Rect& clip,
+ PaintingControlSetting picture_control) override {
+ SkPictureRecorder recorder;
+ skia::RefPtr<SkCanvas> canvas = skia::SharePtr(
+ recorder.beginRecording(gfx::RectToSkRect(gfx::Rect(bounds_))));
+
SkPaint paint;
paint.setStyle(SkPaint::kStroke_Style);
paint.setStrokeWidth(SkIntToScalar(4));
@@ -309,12 +349,17 @@ class CheckerContentLayerClient : public ContentLayerClient {
canvas->drawLine(0, i, bounds_.width(), i, paint);
}
}
- }
- scoped_refptr<DisplayItemList> PaintContentsToDisplayList(
- const gfx::Rect& clip,
- PaintingControlSetting picture_control) override {
- NOTIMPLEMENTED();
- return nullptr;
+
+ scoped_refptr<DisplayItemList> display_list =
+ DisplayItemList::Create(clip, DisplayItemListSettings());
+ auto* item = display_list->CreateAndAppendItem<DrawingDisplayItem>();
+
+ skia::RefPtr<SkPicture> picture =
+ skia::AdoptRef(recorder.endRecordingAsPicture());
+ item->SetNew(picture.Pass());
+
+ display_list->Finalize();
+ return display_list;
}
private:
@@ -329,9 +374,23 @@ class CircleContentLayerClient : public ContentLayerClient {
: bounds_(bounds) {}
~CircleContentLayerClient() override {}
bool FillsBoundsCompletely() const override { return false; }
+ size_t GetApproximateUnsharedMemoryUsage() const override { return 0; }
+ // TODO(pdr): Remove PaintContents as all calls should go through
+ // PaintContentsToDisplayList.
void PaintContents(SkCanvas* canvas,
const gfx::Rect& rect,
PaintingControlSetting picture_control) override {
+ scoped_refptr<DisplayItemList> contents =
+ PaintContentsToDisplayList(rect, picture_control);
+ contents->Raster(canvas, nullptr, rect, 1.0f);
+ }
+ scoped_refptr<DisplayItemList> PaintContentsToDisplayList(
+ const gfx::Rect& clip,
+ PaintingControlSetting picture_control) override {
+ SkPictureRecorder recorder;
+ skia::RefPtr<SkCanvas> canvas = skia::SharePtr(
+ recorder.beginRecording(gfx::RectToSkRect(gfx::Rect(bounds_))));
+
SkPaint paint;
paint.setStyle(SkPaint::kFill_Style);
paint.setColor(SK_ColorWHITE);
@@ -340,12 +399,16 @@ class CircleContentLayerClient : public ContentLayerClient {
bounds_.height() / 2,
bounds_.width() / 4,
paint);
- }
- scoped_refptr<DisplayItemList> PaintContentsToDisplayList(
- const gfx::Rect& clip,
- PaintingControlSetting picture_control) override {
- NOTIMPLEMENTED();
- return nullptr;
+
+ scoped_refptr<DisplayItemList> display_list =
+ DisplayItemList::Create(clip, DisplayItemListSettings());
+ auto* item = display_list->CreateAndAppendItem<DrawingDisplayItem>();
+ skia::RefPtr<SkPicture> picture =
+ skia::AdoptRef(recorder.endRecordingAsPicture());
+ item->SetNew(picture.Pass());
+
+ display_list->Finalize();
+ return display_list;
}
private:
@@ -355,19 +418,16 @@ class CircleContentLayerClient : public ContentLayerClient {
using LayerTreeHostMasksForBackgroundFiltersPixelTest =
ParameterizedPixelResourceTest;
-INSTANTIATE_TEST_CASE_P(
- PixelResourceTest,
- LayerTreeHostMasksForBackgroundFiltersPixelTest,
- ::testing::Values(
- // SOFTWARE, Background filters aren't implemented in software
- GL_GPU_RASTER_2D_DRAW,
- GL_ONE_COPY_2D_STAGING_2D_DRAW,
- GL_ONE_COPY_RECT_STAGING_2D_DRAW,
- GL_ONE_COPY_EXTERNAL_STAGING_2D_DRAW,
- GL_ZERO_COPY_2D_DRAW,
- GL_ZERO_COPY_RECT_DRAW,
- GL_ZERO_COPY_EXTERNAL_DRAW,
- GL_ASYNC_UPLOAD_2D_DRAW));
+INSTANTIATE_TEST_CASE_P(PixelResourceTest,
+ LayerTreeHostMasksForBackgroundFiltersPixelTest,
+ ::testing::Values(SOFTWARE,
+ GL_GPU_RASTER_2D_DRAW,
+ GL_ONE_COPY_2D_STAGING_2D_DRAW,
+ GL_ONE_COPY_RECT_STAGING_2D_DRAW,
+ GL_ONE_COPY_EXTERNAL_STAGING_2D_DRAW,
+ GL_ZERO_COPY_2D_DRAW,
+ GL_ZERO_COPY_RECT_DRAW,
+ GL_ZERO_COPY_EXTERNAL_DRAW));
TEST_P(LayerTreeHostMasksForBackgroundFiltersPixelTest,
MaskOfLayerWithBackgroundFilter) {
@@ -387,7 +447,7 @@ TEST_P(LayerTreeHostMasksForBackgroundFiltersPixelTest,
background->AddChild(blur);
FilterOperations filters;
- filters.Append(FilterOperation::CreateBlurFilter(1.5f));
+ filters.Append(FilterOperation::CreateGrayscaleFilter(1.0));
blur->SetBackgroundFilters(filters);
gfx::Size mask_bounds(100, 100);
diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_synchronous.cc b/chromium/cc/trees/layer_tree_host_pixeltest_synchronous.cc
index a5286a2473e..1eb32ba6440 100644
--- a/chromium/cc/trees/layer_tree_host_pixeltest_synchronous.cc
+++ b/chromium/cc/trees/layer_tree_host_pixeltest_synchronous.cc
@@ -22,7 +22,6 @@ class LayerTreeHostSynchronousPixelTest : public LayerTreePixelTest {
LayerTreePixelTest::InitializeSettings(settings);
settings->single_thread_proxy_scheduler = false;
settings->use_zero_copy = true;
- settings->use_one_copy = false;
}
void BeginTest() override {
@@ -37,7 +36,7 @@ TEST_F(LayerTreeHostSynchronousPixelTest, OneContentLayer) {
FakeContentLayerClient client;
SkPaint green_paint;
green_paint.setColor(SkColorSetARGB(255, 0, 255, 0));
- client.add_draw_rect(gfx::RectF(bounds), green_paint);
+ client.add_draw_rect(gfx::Rect(bounds), green_paint);
scoped_refptr<PictureLayer> root =
PictureLayer::Create(layer_settings(), &client);
root->SetBounds(bounds);
@@ -68,7 +67,7 @@ TEST_F(LayerTreeHostSynchronousGPUPixelTest, OneContentLayer) {
FakeContentLayerClient client;
SkPaint green_paint;
green_paint.setColor(SkColorSetARGB(255, 0, 255, 0));
- client.add_draw_rect(gfx::RectF(bounds), green_paint);
+ client.add_draw_rect(gfx::Rect(bounds), green_paint);
scoped_refptr<PictureLayer> root =
PictureLayer::Create(layer_settings(), &client);
root->SetBounds(bounds);
diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc b/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc
index 7a0af81f4e4..f013e989d3c 100644
--- a/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc
+++ b/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc
@@ -6,6 +6,7 @@
#include "cc/layers/picture_layer.h"
#include "cc/output/copy_output_request.h"
#include "cc/playback/display_item_list.h"
+#include "cc/playback/display_item_list_settings.h"
#include "cc/playback/drawing_display_item.h"
#include "cc/test/layer_tree_pixel_test.h"
#include "cc/test/test_gpu_memory_buffer_manager.h"
@@ -28,15 +29,12 @@ class LayerTreeHostTilesPixelTest : public LayerTreePixelTest {
protected:
void InitializeSettings(LayerTreeSettings* settings) override {
LayerTreePixelTest::InitializeSettings(settings);
- settings->use_display_lists = true;
switch (raster_mode_) {
case PARTIAL_ONE_COPY:
- settings->use_one_copy = true;
settings->use_zero_copy = false;
settings->use_persistent_map_for_gpu_memory_buffers = true;
break;
case FULL_ONE_COPY:
- settings->use_one_copy = true;
settings->use_zero_copy = false;
settings->use_persistent_map_for_gpu_memory_buffers = false;
break;
@@ -101,9 +99,10 @@ class BlueYellowClient : public ContentLayerClient {
scoped_refptr<DisplayItemList> PaintContentsToDisplayList(
const gfx::Rect& clip,
PaintingControlSetting painting_status) override {
- bool use_cached_picture = false;
+ DisplayItemListSettings settings;
+ settings.use_cached_picture = false;
scoped_refptr<DisplayItemList> display_list =
- DisplayItemList::Create(clip, use_cached_picture);
+ DisplayItemList::Create(clip, settings);
SkPictureRecorder recorder;
skia::RefPtr<SkCanvas> canvas = skia::SharePtr(
@@ -133,6 +132,7 @@ class BlueYellowClient : public ContentLayerClient {
}
bool FillsBoundsCompletely() const override { return true; }
+ size_t GetApproximateUnsharedMemoryUsage() const override { return 0; }
void set_blue_top(bool b) { blue_top_ = b; }
@@ -160,6 +160,7 @@ class LayerTreeHostTilesTestPartialInvalidation
// only re-raster the stuff in the rect. If it doesn't do partial raster
// it would re-raster the whole thing instead.
client_.set_blue_top(false);
+ Finish();
picture_layer_->SetNeedsDisplayRect(gfx::Rect(50, 50, 100, 100));
// Add a copy request to see what happened!
@@ -188,6 +189,13 @@ TEST_F(LayerTreeHostTilesTestPartialInvalidation,
}
TEST_F(LayerTreeHostTilesTestPartialInvalidation,
+ PartialRaster_MultiThread_OneCopy) {
+ RunRasterPixelTest(
+ true, PARTIAL_ONE_COPY, picture_layer_,
+ base::FilePath(FILE_PATH_LITERAL("blue_yellow_partial_flipped.png")));
+}
+
+TEST_F(LayerTreeHostTilesTestPartialInvalidation,
FullRaster_MultiThread_OneCopy) {
RunRasterPixelTest(
true, FULL_ONE_COPY, picture_layer_,
diff --git a/chromium/cc/trees/layer_tree_host_unittest.cc b/chromium/cc/trees/layer_tree_host_unittest.cc
index 6d9c9c67199..fe10a47a6de 100644
--- a/chromium/cc/trees/layer_tree_host_unittest.cc
+++ b/chromium/cc/trees/layer_tree_host_unittest.cc
@@ -26,17 +26,18 @@
#include "cc/output/copy_output_result.h"
#include "cc/output/output_surface.h"
#include "cc/output/swap_promise.h"
+#include "cc/playback/display_item_list_settings.h"
#include "cc/quads/draw_quad.h"
#include "cc/quads/io_surface_draw_quad.h"
#include "cc/quads/render_pass_draw_quad.h"
#include "cc/quads/tile_draw_quad.h"
#include "cc/test/fake_content_layer_client.h"
+#include "cc/test/fake_display_list_recording_source.h"
#include "cc/test/fake_layer_tree_host_client.h"
#include "cc/test/fake_output_surface.h"
#include "cc/test/fake_painted_scrollbar_layer.h"
#include "cc/test/fake_picture_layer.h"
#include "cc/test/fake_picture_layer_impl.h"
-#include "cc/test/fake_picture_pile.h"
#include "cc/test/fake_proxy.h"
#include "cc/test/fake_scoped_ui_resource.h"
#include "cc/test/fake_video_frame_provider.h"
@@ -109,6 +110,80 @@ class LayerTreeHostTestSetNeedsCommitInsideLayout : public LayerTreeHostTest {
SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestSetNeedsCommitInsideLayout);
+class LayerTreeHostTestFrameOrdering : public LayerTreeHostTest {
+ protected:
+ enum MainOrder : int {
+ MAIN_START = 1,
+ MAIN_LAYOUT,
+ MAIN_COMMIT_COMPLETE,
+ MAIN_DID_BEGIN_FRAME,
+ MAIN_END,
+ };
+
+ enum ImplOrder : int {
+ IMPL_START = 1,
+ IMPL_COMMIT,
+ IMPL_COMMIT_COMPLETE,
+ IMPL_ACTIVATE,
+ IMPL_DRAW,
+ IMPL_SWAP,
+ IMPL_END,
+ };
+
+ template <typename T>
+ bool CheckStep(T next, T* var) {
+ int expected = next - 1;
+ EXPECT_EQ(expected, *var);
+ bool correct = expected == *var;
+ *var = next;
+ return correct;
+ }
+
+ void BeginTest() override { PostSetNeedsCommitToMainThread(); }
+
+ void Layout() override { EXPECT_TRUE(CheckStep(MAIN_LAYOUT, &main_)); }
+
+ void DidCommit() override {
+ EXPECT_TRUE(CheckStep(MAIN_COMMIT_COMPLETE, &main_));
+ }
+
+ void DidBeginMainFrame() override {
+ EXPECT_TRUE(CheckStep(MAIN_DID_BEGIN_FRAME, &main_));
+ }
+
+ void BeginCommitOnThread(LayerTreeHostImpl* impl) override {
+ EXPECT_TRUE(CheckStep(IMPL_COMMIT, &impl_));
+ }
+
+ void CommitCompleteOnThread(LayerTreeHostImpl* impl) override {
+ EXPECT_TRUE(CheckStep(IMPL_COMMIT_COMPLETE, &impl_));
+ }
+
+ void WillActivateTreeOnThread(LayerTreeHostImpl* impl) override {
+ EXPECT_TRUE(CheckStep(IMPL_ACTIVATE, &impl_));
+ }
+
+ void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
+ EXPECT_TRUE(CheckStep(IMPL_DRAW, &impl_));
+ }
+
+ void SwapBuffersCompleteOnThread(LayerTreeHostImpl* impl) override {
+ EXPECT_TRUE(CheckStep(IMPL_SWAP, &impl_));
+
+ EndTest();
+ }
+
+ void AfterTest() override {
+ EXPECT_TRUE(CheckStep(MAIN_END, &main_));
+ EXPECT_TRUE(CheckStep(IMPL_END, &impl_));
+ }
+
+ MainOrder main_ = MAIN_START;
+ ImplOrder impl_ = IMPL_START;
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestFrameOrdering);
+
class LayerTreeHostTestSetNeedsUpdateInsideLayout : public LayerTreeHostTest {
protected:
void BeginTest() override { PostSetNeedsCommitToMainThread(); }
@@ -272,6 +347,79 @@ class LayerTreeHostTestReadyToDrawNonEmpty
// single threaded mode.
SINGLE_THREAD_TEST_F(LayerTreeHostTestReadyToDrawNonEmpty);
+// This tests if we get the READY_TO_DRAW signal and draw if we become invisible
+// and then become visible again.
+class LayerTreeHostTestReadyToDrawVisibility : public LayerTreeHostTest {
+ public:
+ LayerTreeHostTestReadyToDrawVisibility()
+ : LayerTreeHostTest(),
+ toggled_visibility_(false),
+ did_notify_ready_to_draw_(false),
+ did_draw_(false) {}
+
+ void BeginTest() override { PostSetNeedsCommitToMainThread(); }
+
+ void SetupTree() override {
+ client_.set_fill_with_nonsolid_color(true);
+ scoped_refptr<FakePictureLayer> root_layer =
+ FakePictureLayer::Create(layer_settings(), &client_);
+ root_layer->SetBounds(gfx::Size(1024, 1024));
+ root_layer->SetIsDrawable(true);
+
+ layer_tree_host()->SetRootLayer(root_layer);
+ LayerTreeHostTest::SetupTree();
+ }
+
+ void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
+ if (!toggled_visibility_) {
+ {
+ DebugScopedSetMainThread main(proxy());
+ layer_tree_host()->SetVisible(false);
+ }
+ toggled_visibility_ = true;
+ EXPECT_FALSE(host_impl->visible());
+ }
+ }
+
+ void NotifyReadyToDrawOnThread(LayerTreeHostImpl* host_impl) override {
+ // Sometimes the worker thread posts NotifyReadyToDraw in the extremely
+ // short duration of time between PrepareTiles and SetVisible(false) so we
+ // might get two NotifyReadyToDraw signals for this test.
+ did_notify_ready_to_draw_ = true;
+ }
+
+ void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override {
+ EXPECT_FALSE(did_draw_);
+ did_draw_ = true;
+ EndTest();
+ }
+
+ void DidFinishImplFrameOnThread(LayerTreeHostImpl* host_impl) override {
+ if (!host_impl->visible()) {
+ {
+ DebugScopedSetMainThread main(proxy());
+ layer_tree_host()->SetVisible(true);
+ }
+ EXPECT_TRUE(host_impl->visible());
+ }
+ }
+
+ void AfterTest() override {
+ EXPECT_TRUE(did_notify_ready_to_draw_);
+ EXPECT_TRUE(did_draw_);
+ }
+
+ private:
+ FakeContentLayerClient client_;
+ bool toggled_visibility_;
+ bool did_notify_ready_to_draw_;
+ bool did_draw_;
+};
+
+// Note: With this test setup, we only get tiles flagged as REQUIRED_FOR_DRAW in
+// single threaded mode.
+SINGLE_THREAD_TEST_F(LayerTreeHostTestReadyToDrawVisibility);
+
class LayerTreeHostFreeWorkerContextResourcesTest : public LayerTreeHostTest {
public:
scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface() override {
@@ -316,7 +464,7 @@ class LayerTreeHostFreeWorkerContextResourcesTest : public LayerTreeHostTest {
explicit MockSetWorkerContextShouldAggressivelyFreeResourcesOutputSurface(
bool delegated_rendering)
: FakeOutputSurface(TestContextProvider::Create(),
- TestContextProvider::Create(),
+ TestContextProvider::CreateWorker(),
delegated_rendering) {}
MOCK_METHOD1(SetWorkerContextShouldAggressivelyFreeResources,
void(bool is_visible));
@@ -443,7 +591,6 @@ class LayerTreeHostTestPushPropertiesTo : public LayerTreeHostTest {
protected:
void SetupTree() override {
scoped_refptr<Layer> root = Layer::Create(layer_settings());
- root->CreateRenderSurface();
root->SetBounds(gfx::Size(10, 10));
layer_tree_host()->SetRootLayer(root);
LayerTreeHostTest::SetupTree();
@@ -589,7 +736,7 @@ class LayerTreeHostTestSetNeedsRedrawRect : public LayerTreeHostTest {
DrawResult draw_result) override {
EXPECT_EQ(DRAW_SUCCESS, draw_result);
- gfx::RectF root_damage_rect;
+ gfx::Rect root_damage_rect;
if (!frame_data->render_passes.empty())
root_damage_rect = frame_data->render_passes.back()->damage_rect;
@@ -713,7 +860,6 @@ class LayerTreeHostTestNoExtraCommitFromInvalidate : public LayerTreeHostTest {
void SetupTree() override {
root_layer_ = Layer::Create(layer_settings());
root_layer_->SetBounds(gfx::Size(10, 20));
- root_layer_->CreateRenderSurface();
scaled_layer_ = FakePictureLayer::Create(layer_settings(), &client_);
scaled_layer_->SetBounds(gfx::Size(1, 1));
@@ -764,7 +910,6 @@ class LayerTreeHostTestNoExtraCommitFromScrollbarInvalidate
void SetupTree() override {
root_layer_ = Layer::Create(layer_settings());
root_layer_->SetBounds(gfx::Size(10, 20));
- root_layer_->CreateRenderSurface();
bool paint_scrollbar = true;
bool has_thumb = false;
@@ -813,6 +958,69 @@ class LayerTreeHostTestNoExtraCommitFromScrollbarInvalidate
SINGLE_AND_MULTI_THREAD_TEST_F(
LayerTreeHostTestNoExtraCommitFromScrollbarInvalidate);
+class LayerTreeHostTestDeviceScaleFactorChange : public LayerTreeHostTest {
+ public:
+ void InitializeSettings(LayerTreeSettings* settings) override {
+ settings->layer_transforms_should_scale_layer_contents = true;
+ }
+
+ void SetupTree() override {
+ root_layer_ = Layer::Create(layer_settings());
+ root_layer_->SetBounds(gfx::Size(10, 20));
+
+ child_layer_ = FakePictureLayer::Create(layer_settings(), &client_);
+ child_layer_->SetBounds(gfx::Size(10, 10));
+ root_layer_->AddChild(child_layer_);
+
+ layer_tree_host()->SetRootLayer(root_layer_);
+ LayerTreeHostTest::SetupTree();
+ }
+
+ void BeginTest() override { PostSetNeedsCommitToMainThread(); }
+
+ void DidCommit() override {
+ if (layer_tree_host()->source_frame_number() == 1)
+ layer_tree_host()->SetDeviceScaleFactor(4.f);
+ }
+
+ void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
+ if (host_impl->sync_tree()->source_frame_number() == 1) {
+ EXPECT_EQ(4.f, host_impl->sync_tree()->device_scale_factor());
+ if (host_impl->pending_tree()) {
+ // The active tree's device scale factor shouldn't change until
+ // activation.
+ EXPECT_EQ(1.f, host_impl->active_tree()->device_scale_factor());
+ }
+ }
+ }
+
+ DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
+ LayerTreeHostImpl::FrameData* frame_data,
+ DrawResult draw_result) override {
+ if (host_impl->active_tree()->source_frame_number() == 0) {
+ EXPECT_EQ(1.f, host_impl->active_tree()->device_scale_factor());
+ } else {
+ gfx::Rect root_damage_rect =
+ frame_data->render_passes.back()->damage_rect;
+ EXPECT_EQ(gfx::Rect(host_impl->active_tree()->root_layer()->bounds()),
+ root_damage_rect);
+ EXPECT_EQ(4.f, host_impl->active_tree()->device_scale_factor());
+ EndTest();
+ }
+
+ return draw_result;
+ }
+
+ void AfterTest() override {}
+
+ private:
+ FakeContentLayerClient client_;
+ scoped_refptr<Layer> root_layer_;
+ scoped_refptr<Layer> child_layer_;
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestDeviceScaleFactorChange);
+
class LayerTreeHostTestSetNextCommitForcesRedraw : public LayerTreeHostTest {
public:
LayerTreeHostTestSetNextCommitForcesRedraw()
@@ -837,7 +1045,7 @@ class LayerTreeHostTestSetNextCommitForcesRedraw : public LayerTreeHostTest {
DrawResult draw_result) override {
EXPECT_EQ(DRAW_SUCCESS, draw_result);
- gfx::RectF root_damage_rect;
+ gfx::Rect root_damage_rect;
if (!frame_data->render_passes.empty())
root_damage_rect = frame_data->render_passes.back()->damage_rect;
@@ -937,7 +1145,7 @@ class LayerTreeHostTestUndrawnLayersDamageLater : public LayerTreeHostTest {
DrawResult draw_result) override {
EXPECT_EQ(DRAW_SUCCESS, draw_result);
- gfx::RectF root_damage_rect;
+ gfx::Rect root_damage_rect;
if (!frame_data->render_passes.empty())
root_damage_rect = frame_data->render_passes.back()->damage_rect;
@@ -1004,17 +1212,15 @@ class LayerTreeHostTestDamageWithScale : public LayerTreeHostTest {
void SetupTree() override {
client_.set_fill_with_nonsolid_color(true);
- scoped_ptr<FakePicturePile> pile(
- new FakePicturePile(LayerTreeSettings().minimum_contents_scale,
- LayerTreeSettings().default_tile_grid_size));
+ scoped_ptr<FakeDisplayListRecordingSource> recording(
+ new FakeDisplayListRecordingSource);
root_layer_ = FakePictureLayer::CreateWithRecordingSource(
- layer_settings(), &client_, pile.Pass());
+ layer_settings(), &client_, recording.Pass());
root_layer_->SetBounds(gfx::Size(50, 50));
- pile.reset(new FakePicturePile(LayerTreeSettings().minimum_contents_scale,
- LayerTreeSettings().default_tile_grid_size));
+ recording.reset(new FakeDisplayListRecordingSource);
child_layer_ = FakePictureLayer::CreateWithRecordingSource(
- layer_settings(), &client_, pile.Pass());
+ layer_settings(), &client_, recording.Pass());
child_layer_->SetBounds(gfx::Size(25, 25));
child_layer_->SetIsDrawable(true);
child_layer_->SetContentsOpaque(true);
@@ -1041,7 +1247,7 @@ class LayerTreeHostTestDamageWithScale : public LayerTreeHostTest {
DrawResult draw_result) override {
EXPECT_EQ(DRAW_SUCCESS, draw_result);
- gfx::RectF root_damage_rect;
+ gfx::Rect root_damage_rect;
if (!frame_data->render_passes.empty())
root_damage_rect = frame_data->render_passes.back()->damage_rect;
@@ -1242,22 +1448,24 @@ class LayerTreeHostTestStartPageScaleAnimation : public LayerTreeHostTest {
void SetupTree() override {
LayerTreeHostTest::SetupTree();
+ Layer* root_layer = layer_tree_host()->root_layer();
+
scoped_refptr<FakePictureLayer> layer =
FakePictureLayer::Create(layer_settings(), &client_);
layer->set_always_update_resources(true);
scroll_layer_ = layer;
- Layer* root_layer = layer_tree_host()->root_layer();
- scroll_layer_->SetScrollClipLayerId(root_layer->id());
- scroll_layer_->SetIsContainerForFixedPositionLayers(true);
scroll_layer_->SetBounds(gfx::Size(2 * root_layer->bounds().width(),
2 * root_layer->bounds().height()));
scroll_layer_->SetScrollOffset(gfx::ScrollOffset());
- layer_tree_host()->root_layer()->AddChild(scroll_layer_);
- // This test requires the page_scale and inner viewport layers to be
- // identified.
- layer_tree_host()->RegisterViewportLayers(NULL, root_layer,
- scroll_layer_.get(), NULL);
+
+ CreateVirtualViewportLayers(root_layer,
+ scroll_layer_,
+ root_layer->bounds(),
+ root_layer->bounds(),
+ layer_tree_host(),
+ layer_settings());
+
layer_tree_host()->SetPageScaleFactorAndLimits(1.f, 0.5f, 2.f);
}
@@ -1348,17 +1556,22 @@ class TestOpacityChangeLayerDelegate : public ContentLayerClient {
void PaintContents(SkCanvas* canvas,
const gfx::Rect& clip,
PaintingControlSetting picture_control) override {
- // Set layer opacity to 0.
- if (test_layer_)
- test_layer_->SetOpacity(0.f);
+ NOTIMPLEMENTED();
}
scoped_refptr<DisplayItemList> PaintContentsToDisplayList(
const gfx::Rect& clip,
PaintingControlSetting picture_control) override {
- NOTIMPLEMENTED();
- return nullptr;
+ // Set layer opacity to 0.
+ if (test_layer_)
+ test_layer_->SetOpacity(0.f);
+
+ // Return a dummy display list.
+ scoped_refptr<DisplayItemList> display_list =
+ DisplayItemList::Create(clip, DisplayItemListSettings());
+ return display_list;
}
bool FillsBoundsCompletely() const override { return false; }
+ size_t GetApproximateUnsharedMemoryUsage() const override { return 0; }
private:
Layer* test_layer_;
@@ -1428,7 +1641,7 @@ class LayerTreeHostTestDeviceScaleFactorScalesViewportAndLayers
// Should only do one commit.
EXPECT_EQ(0, impl->active_tree()->source_frame_number());
// Device scale factor should come over to impl.
- EXPECT_NEAR(impl->device_scale_factor(), 1.5f, 0.00001f);
+ EXPECT_NEAR(impl->active_tree()->device_scale_factor(), 1.5f, 0.00001f);
// Both layers are on impl.
ASSERT_EQ(1u, impl->active_tree()->root_layer()->children().size());
@@ -1466,8 +1679,8 @@ class LayerTreeHostTestDeviceScaleFactorScalesViewportAndLayers
EXPECT_FLOAT_EQ(1.5f, child->MaximumTilingContentsScale());
gfx::Transform scale_transform;
- scale_transform.Scale(impl->device_scale_factor(),
- impl->device_scale_factor());
+ scale_transform.Scale(impl->active_tree()->device_scale_factor(),
+ impl->active_tree()->device_scale_factor());
// The root layer is scaled by 2x.
gfx::Transform root_screen_space_transform = scale_transform;
@@ -1627,7 +1840,6 @@ class LayerTreeHostTestCompositeImmediatelyStateTransitions
void InitializeSettings(LayerTreeSettings* settings) override {
settings->single_thread_proxy_scheduler = false;
settings->use_zero_copy = true;
- settings->use_one_copy = false;
}
void BeginTest() override {
@@ -1878,6 +2090,10 @@ class LayerTreeHostTestAbortedCommitDoesntStallSynchronousCompositor
}
void ScheduledActionInvalidateOutputSurface() override {
+ // Do not call ImplThreadTaskRunner after the test ended because of the
+ // possibility of use-after-free due to a race.
+ if (TestEnded())
+ return;
ImplThreadTaskRunner()->PostTask(
FROM_HERE,
base::Bind(
@@ -1900,7 +2116,8 @@ class LayerTreeHostTestAbortedCommitDoesntStallDisabledVsync
: public LayerTreeHostTestAbortedCommitDoesntStall {
void InitializeSettings(LayerTreeSettings* settings) override {
LayerTreeHostTestAbortedCommitDoesntStall::InitializeSettings(settings);
- settings->renderer_settings.disable_gpu_vsync = true;
+ settings->wait_for_beginframe_interval = false;
+ settings->renderer_settings.disable_display_vsync = true;
}
};
@@ -1945,17 +2162,22 @@ class LayerTreeHostTestChangeLayerPropertiesInPaintContents
void PaintContents(SkCanvas* canvas,
const gfx::Rect& clip,
PaintingControlSetting picture_control) override {
- layer_->SetBounds(gfx::Size(2, 2));
+ NOTIMPLEMENTED();
}
scoped_refptr<DisplayItemList> PaintContentsToDisplayList(
const gfx::Rect& clip,
PaintingControlSetting picture_control) override {
- NOTIMPLEMENTED();
- return nullptr;
+ layer_->SetBounds(gfx::Size(2, 2));
+
+ // Return a dummy display list.
+ scoped_refptr<DisplayItemList> display_list =
+ DisplayItemList::Create(clip, DisplayItemListSettings());
+ return display_list;
}
bool FillsBoundsCompletely() const override { return false; }
+ size_t GetApproximateUnsharedMemoryUsage() const override { return 0; }
private:
Layer* layer_;
@@ -2465,7 +2687,6 @@ class LayerTreeHostTestLayersPushProperties : public LayerTreeHostTest {
void SetupTree() override {
root_ = PushPropertiesCountingLayer::Create(layer_settings());
- root_->CreateRenderSurface();
child_ = PushPropertiesCountingLayer::Create(layer_settings());
child2_ = PushPropertiesCountingLayer::Create(layer_settings());
grandchild_ = PushPropertiesCountingLayer::Create(layer_settings());
@@ -2479,7 +2700,6 @@ class LayerTreeHostTestLayersPushProperties : public LayerTreeHostTest {
child2_->AddChild(leaf_always_pushing_layer_);
other_root_ = PushPropertiesCountingLayer::Create(layer_settings());
- other_root_->CreateRenderSurface();
// Don't set the root layer here.
LayerTreeHostTest::SetupTree();
@@ -2857,7 +3077,6 @@ class LayerTreeHostTestPropertyChangesDuringUpdateArePushed
void SetupTree() override {
root_ = Layer::Create(layer_settings());
- root_->CreateRenderSurface();
root_->SetBounds(gfx::Size(1, 1));
bool paint_scrollbar = true;
@@ -2914,7 +3133,6 @@ class LayerTreeHostTestSetDrawableCausesCommit : public LayerTreeHostTest {
void SetupTree() override {
root_ = PushPropertiesCountingLayer::Create(layer_settings());
- root_->CreateRenderSurface();
child_ = PushPropertiesCountingLayer::Create(layer_settings());
root_->AddChild(child_);
@@ -2976,7 +3194,6 @@ class LayerTreeHostTestCasePushPropertiesThreeGrandChildren
void SetupTree() override {
root_ = PushPropertiesCountingLayer::Create(layer_settings());
- root_->CreateRenderSurface();
child_ = PushPropertiesCountingLayer::Create(layer_settings());
grandchild1_ = PushPropertiesCountingLayer::Create(layer_settings());
grandchild2_ = PushPropertiesCountingLayer::Create(layer_settings());
@@ -3522,7 +3739,6 @@ class LayerTreeHostTestPushHiddenLayer : public LayerTreeHostTest {
protected:
void SetupTree() override {
root_layer_ = Layer::Create(layer_settings());
- root_layer_->CreateRenderSurface();
root_layer_->SetPosition(gfx::Point());
root_layer_->SetBounds(gfx::Size(10, 10));
@@ -3617,55 +3833,6 @@ class LayerTreeHostTestUpdateLayerInEmptyViewport : public LayerTreeHostTest {
MULTI_THREAD_TEST_F(LayerTreeHostTestUpdateLayerInEmptyViewport);
-class LayerTreeHostTestMaxTransferBufferUsageBytes : public LayerTreeHostTest {
- protected:
- void InitializeSettings(LayerTreeSettings* settings) override {
- // Testing async uploads.
- settings->use_zero_copy = false;
- settings->use_one_copy = false;
- }
-
- scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface() override {
- scoped_refptr<TestContextProvider> context_provider =
- TestContextProvider::Create();
- context_provider->SetMaxTransferBufferUsageBytes(512 * 512);
- if (delegating_renderer())
- return FakeOutputSurface::CreateDelegating3d(context_provider);
- else
- return FakeOutputSurface::Create3d(context_provider);
- }
-
- void SetupTree() override {
- client_.set_fill_with_nonsolid_color(true);
- scoped_refptr<FakePictureLayer> root_layer =
- FakePictureLayer::Create(layer_settings(), &client_);
- root_layer->SetBounds(gfx::Size(1024, 1024));
- root_layer->SetIsDrawable(true);
-
- layer_tree_host()->SetRootLayer(root_layer);
- LayerTreeHostTest::SetupTree();
- }
-
- void BeginTest() override { PostSetNeedsCommitToMainThread(); }
-
- void DidActivateTreeOnThread(LayerTreeHostImpl* impl) override {
- TestWebGraphicsContext3D* context = TestContext();
-
- // Expect that the transfer buffer memory used is equal to the
- // MaxTransferBufferUsageBytes value set in CreateOutputSurface.
- EXPECT_EQ(512 * 512u, context->max_used_transfer_buffer_usage_bytes());
- EndTest();
- }
-
- void AfterTest() override {}
-
- private:
- FakeContentLayerClient client_;
-};
-
-// Impl-side painting is a multi-threaded compositor feature.
-MULTI_THREAD_TEST_F(LayerTreeHostTestMaxTransferBufferUsageBytes);
-
class LayerTreeHostTestSetMemoryPolicyOnLostOutputSurface
: public LayerTreeHostTest {
protected:
@@ -3782,7 +3949,6 @@ class TestSwapPromise : public SwapPromise {
void DidSwap(CompositorFrameMetadata* metadata) override {
base::AutoLock lock(result_->lock);
- EXPECT_TRUE(result_->did_activate_called);
EXPECT_FALSE(result_->did_swap_called);
EXPECT_FALSE(result_->did_not_swap_called);
result_->did_swap_called = true;
@@ -3805,6 +3971,53 @@ class TestSwapPromise : public SwapPromise {
TestSwapPromiseResult* result_;
};
+class PinnedLayerTreeSwapPromise : public LayerTreeHostTest {
+ protected:
+ void BeginTest() override {
+ PostSetNextCommitForcesRedrawToMainThread();
+ PostSetNeedsCommitToMainThread();
+ }
+
+ void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
+ int frame = host_impl->active_tree()->source_frame_number();
+ if (frame == -1) {
+ host_impl->active_tree()->QueuePinnedSwapPromise(make_scoped_ptr(
+ new TestSwapPromise(&pinned_active_swap_promise_result_)));
+ host_impl->pending_tree()->QueueSwapPromise(
+ make_scoped_ptr(new TestSwapPromise(&pending_swap_promise_result_)));
+ host_impl->active_tree()->QueueSwapPromise(
+ make_scoped_ptr(new TestSwapPromise(&active_swap_promise_result_)));
+ }
+ }
+
+ void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override {
+ EndTest();
+ }
+
+ void AfterTest() override {
+ // The pending swap promise should activate and swap.
+ EXPECT_TRUE(pending_swap_promise_result_.did_activate_called);
+ EXPECT_TRUE(pending_swap_promise_result_.did_swap_called);
+
+ // The active swap promise should fail to swap (it is cancelled by
+ // the activation of a new frame).
+ EXPECT_FALSE(active_swap_promise_result_.did_activate_called);
+ EXPECT_FALSE(active_swap_promise_result_.did_swap_called);
+ EXPECT_TRUE(active_swap_promise_result_.did_not_swap_called);
+ EXPECT_EQ(active_swap_promise_result_.reason, SwapPromise::SWAP_FAILS);
+
+ // The pinned active swap promise should not activate, but should swap.
+ EXPECT_FALSE(pinned_active_swap_promise_result_.did_activate_called);
+ EXPECT_TRUE(pinned_active_swap_promise_result_.did_swap_called);
+ }
+
+ TestSwapPromiseResult pending_swap_promise_result_;
+ TestSwapPromiseResult active_swap_promise_result_;
+ TestSwapPromiseResult pinned_active_swap_promise_result_;
+};
+
+MULTI_THREAD_TEST_F(PinnedLayerTreeSwapPromise);
+
class LayerTreeHostTestBreakSwapPromise : public LayerTreeHostTest {
protected:
LayerTreeHostTestBreakSwapPromise()
@@ -4219,22 +4432,21 @@ class LayerTreeHostTestGpuRasterizationDefault : public LayerTreeHostTest {
void SetupTree() override {
LayerTreeHostTest::SetupTree();
- scoped_refptr<PictureLayer> layer =
- PictureLayer::Create(layer_settings(), &layer_client_);
+ scoped_ptr<FakeDisplayListRecordingSource> recording_source(
+ new FakeDisplayListRecordingSource);
+ recording_source_ = recording_source.get();
+
+ scoped_refptr<FakePictureLayer> layer =
+ FakePictureLayer::CreateWithRecordingSource(
+ layer_settings(), &layer_client_, recording_source.Pass());
+ layer_ = layer.get();
layer->SetBounds(gfx::Size(10, 10));
layer->SetIsDrawable(true);
layer_tree_host()->root_layer()->AddChild(layer);
}
void BeginTest() override {
- Layer* root = layer_tree_host()->root_layer();
- PictureLayer* layer = static_cast<PictureLayer*>(root->child_at(0));
- RecordingSource* recording_source = layer->GetRecordingSourceForTesting();
-
- // Verify default values.
- EXPECT_TRUE(root->IsSuitableForGpuRasterization());
- EXPECT_TRUE(layer->IsSuitableForGpuRasterization());
- EXPECT_TRUE(recording_source->IsSuitableForGpuRasterization());
+ // Verify default value.
EXPECT_FALSE(layer_tree_host()->has_gpu_rasterization_trigger());
// Setting gpu rasterization trigger does not enable gpu rasterization.
@@ -4245,11 +4457,17 @@ class LayerTreeHostTestGpuRasterizationDefault : public LayerTreeHostTest {
}
void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
+ EXPECT_TRUE(recording_source_->IsSuitableForGpuRasterization());
+ EXPECT_TRUE(layer_->IsSuitableForGpuRasterization());
+
EXPECT_FALSE(host_impl->pending_tree()->use_gpu_rasterization());
EXPECT_FALSE(host_impl->use_gpu_rasterization());
}
void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
+ EXPECT_TRUE(recording_source_->IsSuitableForGpuRasterization());
+ EXPECT_TRUE(layer_->IsSuitableForGpuRasterization());
+
EXPECT_FALSE(host_impl->active_tree()->use_gpu_rasterization());
EXPECT_FALSE(host_impl->use_gpu_rasterization());
EndTest();
@@ -4258,10 +4476,64 @@ class LayerTreeHostTestGpuRasterizationDefault : public LayerTreeHostTest {
void AfterTest() override {}
FakeContentLayerClient layer_client_;
+ FakePictureLayer* layer_;
+ FakeDisplayListRecordingSource* recording_source_;
};
MULTI_THREAD_TEST_F(LayerTreeHostTestGpuRasterizationDefault);
+class LayerTreeHostTestEmptyLayerGpuRasterization : public LayerTreeHostTest {
+ protected:
+ void SetupTree() override {
+ LayerTreeHostTest::SetupTree();
+
+ scoped_ptr<FakeDisplayListRecordingSource> recording_source(
+ new FakeDisplayListRecordingSource);
+ recording_source_ = recording_source.get();
+
+ scoped_refptr<FakePictureLayer> layer =
+ FakePictureLayer::CreateWithRecordingSource(
+ layer_settings(), &layer_client_, recording_source.Pass());
+ layer_ = layer.get();
+ layer->SetBounds(gfx::Size());
+ layer->SetIsDrawable(true);
+ layer_tree_host()->root_layer()->AddChild(layer);
+ }
+
+ void BeginTest() override {
+ // Setting gpu rasterization trigger does not enable gpu rasterization.
+ layer_tree_host()->SetHasGpuRasterizationTrigger(true);
+ EXPECT_TRUE(layer_tree_host()->has_gpu_rasterization_trigger());
+
+ PostSetNeedsCommitToMainThread();
+ }
+
+ void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
+ EXPECT_TRUE(recording_source_->IsSuitableForGpuRasterization());
+ EXPECT_TRUE(layer_->IsSuitableForGpuRasterization());
+
+ EXPECT_FALSE(host_impl->pending_tree()->use_gpu_rasterization());
+ EXPECT_FALSE(host_impl->use_gpu_rasterization());
+ }
+
+ void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
+ EXPECT_TRUE(recording_source_->IsSuitableForGpuRasterization());
+ EXPECT_TRUE(layer_->IsSuitableForGpuRasterization());
+
+ EXPECT_FALSE(host_impl->active_tree()->use_gpu_rasterization());
+ EXPECT_FALSE(host_impl->use_gpu_rasterization());
+ EndTest();
+ }
+
+ void AfterTest() override {}
+
+ FakeContentLayerClient layer_client_;
+ FakePictureLayer* layer_;
+ FakeDisplayListRecordingSource* recording_source_;
+};
+
+MULTI_THREAD_TEST_F(LayerTreeHostTestEmptyLayerGpuRasterization);
+
class LayerTreeHostTestGpuRasterizationEnabled : public LayerTreeHostTest {
protected:
void InitializeSettings(LayerTreeSettings* settings) override {
@@ -4272,22 +4544,21 @@ class LayerTreeHostTestGpuRasterizationEnabled : public LayerTreeHostTest {
void SetupTree() override {
LayerTreeHostTest::SetupTree();
- scoped_refptr<PictureLayer> layer =
- PictureLayer::Create(layer_settings(), &layer_client_);
+ scoped_ptr<FakeDisplayListRecordingSource> recording_source(
+ new FakeDisplayListRecordingSource);
+ recording_source_ = recording_source.get();
+
+ scoped_refptr<FakePictureLayer> layer =
+ FakePictureLayer::CreateWithRecordingSource(
+ layer_settings(), &layer_client_, recording_source.Pass());
+ layer_ = layer.get();
layer->SetBounds(gfx::Size(10, 10));
layer->SetIsDrawable(true);
layer_tree_host()->root_layer()->AddChild(layer);
}
void BeginTest() override {
- Layer* root = layer_tree_host()->root_layer();
- PictureLayer* layer = static_cast<PictureLayer*>(root->child_at(0));
- RecordingSource* recording_source = layer->GetRecordingSourceForTesting();
-
- // Verify default values.
- EXPECT_TRUE(root->IsSuitableForGpuRasterization());
- EXPECT_TRUE(layer->IsSuitableForGpuRasterization());
- EXPECT_TRUE(recording_source->IsSuitableForGpuRasterization());
+ // Verify default value.
EXPECT_FALSE(layer_tree_host()->has_gpu_rasterization_trigger());
// Gpu rasterization trigger is relevant.
@@ -4295,23 +4566,29 @@ class LayerTreeHostTestGpuRasterizationEnabled : public LayerTreeHostTest {
EXPECT_TRUE(layer_tree_host()->has_gpu_rasterization_trigger());
// Content-based veto is relevant as well.
- recording_source->SetUnsuitableForGpuRasterizationForTesting();
- EXPECT_FALSE(recording_source->IsSuitableForGpuRasterization());
- EXPECT_FALSE(layer->IsSuitableForGpuRasterization());
+ recording_source_->SetUnsuitableForGpuRasterization();
+
// Veto will take effect when layers are updated.
// The results will be verified after commit is completed below.
- // Since we are manually marking picture pile as unsuitable,
+ // Since we are manually marking the source as unsuitable,
// make sure that the layer gets a chance to update.
- layer->SetNeedsDisplay();
+ layer_->SetNeedsDisplay();
PostSetNeedsCommitToMainThread();
}
void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
+ // Ensure the suitability bit sticks.
+ EXPECT_FALSE(recording_source_->IsSuitableForGpuRasterization());
+ EXPECT_FALSE(layer_->IsSuitableForGpuRasterization());
+
EXPECT_FALSE(host_impl->pending_tree()->use_gpu_rasterization());
EXPECT_FALSE(host_impl->use_gpu_rasterization());
}
void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
+ EXPECT_FALSE(recording_source_->IsSuitableForGpuRasterization());
+ EXPECT_FALSE(layer_->IsSuitableForGpuRasterization());
+
EXPECT_FALSE(host_impl->active_tree()->use_gpu_rasterization());
EXPECT_FALSE(host_impl->use_gpu_rasterization());
EndTest();
@@ -4320,6 +4597,8 @@ class LayerTreeHostTestGpuRasterizationEnabled : public LayerTreeHostTest {
void AfterTest() override {}
FakeContentLayerClient layer_client_;
+ FakePictureLayer* layer_;
+ FakeDisplayListRecordingSource* recording_source_;
};
MULTI_THREAD_TEST_F(LayerTreeHostTestGpuRasterizationEnabled);
@@ -4334,22 +4613,22 @@ class LayerTreeHostTestGpuRasterizationForced : public LayerTreeHostTest {
void SetupTree() override {
LayerTreeHostTest::SetupTree();
+ scoped_ptr<FakeDisplayListRecordingSource> recording_source(
+ new FakeDisplayListRecordingSource);
+ recording_source_ = recording_source.get();
+
scoped_refptr<FakePictureLayer> layer =
- FakePictureLayer::Create(layer_settings(), &layer_client_);
+ FakePictureLayer::CreateWithRecordingSource(
+ layer_settings(), &layer_client_, recording_source.Pass());
+ layer_ = layer.get();
+
layer->SetBounds(gfx::Size(10, 10));
layer->SetIsDrawable(true);
layer_tree_host()->root_layer()->AddChild(layer);
}
void BeginTest() override {
- Layer* root = layer_tree_host()->root_layer();
- PictureLayer* layer = static_cast<PictureLayer*>(root->child_at(0));
- RecordingSource* recording_source = layer->GetRecordingSourceForTesting();
-
- // Verify default values.
- EXPECT_TRUE(root->IsSuitableForGpuRasterization());
- EXPECT_TRUE(layer->IsSuitableForGpuRasterization());
- EXPECT_TRUE(recording_source->IsSuitableForGpuRasterization());
+ // Verify default value.
EXPECT_FALSE(layer_tree_host()->has_gpu_rasterization_trigger());
// With gpu rasterization forced, gpu rasterization trigger is irrelevant.
@@ -4357,23 +4636,29 @@ class LayerTreeHostTestGpuRasterizationForced : public LayerTreeHostTest {
EXPECT_TRUE(layer_tree_host()->has_gpu_rasterization_trigger());
// Content-based veto is irrelevant as well.
- recording_source->SetUnsuitableForGpuRasterizationForTesting();
- EXPECT_FALSE(recording_source->IsSuitableForGpuRasterization());
- EXPECT_FALSE(layer->IsSuitableForGpuRasterization());
+ recording_source_->SetUnsuitableForGpuRasterization();
+
// Veto will take effect when layers are updated.
// The results will be verified after commit is completed below.
- // Since we are manually marking picture pile as unsuitable,
+ // Since we are manually marking the source as unsuitable,
// make sure that the layer gets a chance to update.
- layer->SetNeedsDisplay();
+ layer_->SetNeedsDisplay();
PostSetNeedsCommitToMainThread();
}
void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
+ // Ensure the suitability bit sticks.
+ EXPECT_FALSE(recording_source_->IsSuitableForGpuRasterization());
+ EXPECT_FALSE(layer_->IsSuitableForGpuRasterization());
+
EXPECT_TRUE(host_impl->sync_tree()->use_gpu_rasterization());
EXPECT_TRUE(host_impl->use_gpu_rasterization());
}
void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
+ EXPECT_FALSE(recording_source_->IsSuitableForGpuRasterization());
+ EXPECT_FALSE(layer_->IsSuitableForGpuRasterization());
+
EXPECT_TRUE(host_impl->active_tree()->use_gpu_rasterization());
EXPECT_TRUE(host_impl->use_gpu_rasterization());
EndTest();
@@ -4382,93 +4667,12 @@ class LayerTreeHostTestGpuRasterizationForced : public LayerTreeHostTest {
void AfterTest() override {}
FakeContentLayerClient layer_client_;
+ FakePictureLayer* layer_;
+ FakeDisplayListRecordingSource* recording_source_;
};
SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestGpuRasterizationForced);
-class LayerTreeHostTestContinuousPainting : public LayerTreeHostTest {
- public:
- LayerTreeHostTestContinuousPainting()
- : num_commits_(0), num_draws_(0), bounds_(20, 20), child_layer_(NULL) {}
-
- protected:
- enum { kExpectedNumCommits = 10 };
-
- void SetupTree() override {
- scoped_refptr<Layer> root_layer = Layer::Create(layer_settings());
- root_layer->SetBounds(bounds_);
- root_layer->CreateRenderSurface();
-
- child_layer_ = FakePictureLayer::Create(layer_settings(), &client_);
- child_layer_->SetBounds(bounds_);
- child_layer_->SetIsDrawable(true);
- root_layer->AddChild(child_layer_);
-
- layer_tree_host()->SetRootLayer(root_layer);
- layer_tree_host()->SetViewportSize(bounds_);
- LayerTreeHostTest::SetupTree();
- }
-
- void BeginTest() override {
- MainThreadTaskRunner()->PostTask(
- FROM_HERE,
- base::Bind(
- &LayerTreeHostTestContinuousPainting::EnableContinuousPainting,
- base::Unretained(this)));
- // Wait 50x longer than expected.
- double milliseconds_per_frame =
- 1000.0 / layer_tree_host()->settings().renderer_settings.refresh_rate;
- MainThreadTaskRunner()->PostDelayedTask(
- FROM_HERE,
- base::Bind(
- &LayerTreeHostTestContinuousPainting::DisableContinuousPainting,
- base::Unretained(this)),
- base::TimeDelta::FromMilliseconds(50 * kExpectedNumCommits *
- milliseconds_per_frame));
- }
-
- void BeginMainFrame(const BeginFrameArgs& args) override {
- child_layer_->SetNeedsDisplay();
- }
-
- void AfterTest() override {
- EXPECT_LE(kExpectedNumCommits, num_commits_);
- EXPECT_LE(kExpectedNumCommits, num_draws_);
- EXPECT_LE(kExpectedNumCommits, child_layer_->update_count());
- }
-
- void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
- if (++num_draws_ == kExpectedNumCommits)
- EndTest();
- }
-
- void CommitCompleteOnThread(LayerTreeHostImpl* impl) override {
- ++num_commits_;
- }
-
- private:
- void EnableContinuousPainting() {
- LayerTreeDebugState debug_state = layer_tree_host()->debug_state();
- debug_state.continuous_painting = true;
- layer_tree_host()->SetDebugState(debug_state);
- }
-
- void DisableContinuousPainting() {
- LayerTreeDebugState debug_state = layer_tree_host()->debug_state();
- debug_state.continuous_painting = false;
- layer_tree_host()->SetDebugState(debug_state);
- EndTest();
- }
-
- int num_commits_;
- int num_draws_;
- const gfx::Size bounds_;
- FakeContentLayerClient client_;
- scoped_refptr<FakePictureLayer> child_layer_;
-};
-
-MULTI_THREAD_TEST_F(LayerTreeHostTestContinuousPainting);
-
class LayerTreeHostTestWillBeginImplFrameHasDidFinishImplFrame
: public LayerTreeHostTest {
public:
@@ -4478,7 +4682,6 @@ class LayerTreeHostTestWillBeginImplFrameHasDidFinishImplFrame
: will_begin_impl_frame_count_(0), did_finish_impl_frame_count_(0) {}
void BeginTest() override {
- // Kick off the test with a commit.
PostSetNeedsCommitToMainThread();
}
@@ -4524,6 +4727,70 @@ class LayerTreeHostTestWillBeginImplFrameHasDidFinishImplFrame
SINGLE_AND_MULTI_THREAD_TEST_F(
LayerTreeHostTestWillBeginImplFrameHasDidFinishImplFrame);
+::testing::AssertionResult AssertFrameTimeContained(
+ const char* haystack_expr,
+ const char* needle_expr,
+ const std::vector<BeginFrameArgs> haystack,
+ const BeginFrameArgs needle) {
+ auto failure = ::testing::AssertionFailure()
+ << needle.frame_time << " (" << needle_expr
+ << ") not found in " << haystack_expr;
+
+ if (haystack.size() == 0) {
+ failure << " which is empty.";
+ } else {
+ failure << " which contains:\n";
+ for (size_t i = 0; i < haystack.size(); i++) {
+ if (haystack[i].frame_time == needle.frame_time)
+ return ::testing::AssertionSuccess();
+ failure << " [" << i << "]: " << haystack[i].frame_time << "\n";
+ }
+ }
+
+ return failure;
+}
+
+class LayerTreeHostTestBeginMainFrameTimeIsAlsoImplTime
+ : public LayerTreeHostTest {
+ public:
+ LayerTreeHostTestBeginMainFrameTimeIsAlsoImplTime()
+ : impl_frame_args_(), will_begin_impl_frame_count_(0) {}
+
+ void BeginTest() override {
+ // Kick off the test with a commit.
+ PostSetNeedsCommitToMainThread();
+ }
+
+ void WillBeginImplFrameOnThread(LayerTreeHostImpl* impl,
+ const BeginFrameArgs& args) override {
+ impl_frame_args_.push_back(args);
+
+ will_begin_impl_frame_count_++;
+ if (will_begin_impl_frame_count_ < 10)
+ PostSetNeedsCommitToMainThread();
+ }
+
+ void BeginMainFrame(const BeginFrameArgs& args) override {
+ ASSERT_GT(impl_frame_args_.size(), 0U)
+ << "BeginMainFrame called before BeginImplFrame called!";
+ EXPECT_PRED_FORMAT2(AssertFrameTimeContained, impl_frame_args_, args);
+ }
+
+ void SendBeginMainFrameNotExpectedSoon() override { EndTest(); }
+
+ void AfterTest() override {
+ EXPECT_GT(impl_frame_args_.size(), 0U);
+ EXPECT_GE(will_begin_impl_frame_count_, 10);
+ }
+
+ private:
+ std::vector<BeginFrameArgs> impl_frame_args_;
+ int will_begin_impl_frame_count_;
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(
+ LayerTreeHostTestBeginMainFrameTimeIsAlsoImplTime);
+
class LayerTreeHostTestSendBeginFramesToChildren : public LayerTreeHostTest {
public:
LayerTreeHostTestSendBeginFramesToChildren()
@@ -4657,7 +4924,6 @@ class LayerTreeHostTestSynchronousCompositeSwapPromise
void InitializeSettings(LayerTreeSettings* settings) override {
settings->single_thread_proxy_scheduler = false;
settings->use_zero_copy = true;
- settings->use_one_copy = false;
}
void BeginTest() override {
@@ -4790,21 +5056,19 @@ class LayerTreeHostTestCrispUpAfterPinchEnds : public LayerTreeHostTest {
pinch->SetIsContainerForFixedPositionLayers(true);
root->AddChild(pinch);
- scoped_ptr<FakePicturePile> pile(
- new FakePicturePile(LayerTreeSettings().minimum_contents_scale,
- LayerTreeSettings().default_tile_grid_size));
- pile->SetPlaybackAllowedEvent(&playback_allowed_event_);
+ scoped_ptr<FakeDisplayListRecordingSource> recording(
+ new FakeDisplayListRecordingSource);
+ recording->SetPlaybackAllowedEvent(&playback_allowed_event_);
scoped_refptr<FakePictureLayer> layer =
FakePictureLayer::CreateWithRecordingSource(layer_settings(), &client_,
- pile.Pass());
+ recording.Pass());
layer->SetBounds(gfx::Size(500, 500));
layer->SetContentsOpaque(true);
// Avoid LCD text on the layer so we don't cause extra commits when we
// pinch.
- layer->disable_lcd_text();
pinch->AddChild(layer);
- layer_tree_host()->RegisterViewportLayers(NULL, root, pinch, pinch);
+ layer_tree_host()->RegisterViewportLayers(NULL, root, pinch, nullptr);
layer_tree_host()->SetPageScaleFactorAndLimits(1.f, 1.f, 4.f);
layer_tree_host()->SetRootLayer(root);
LayerTreeHostTest::SetupTree();
@@ -4961,10 +5225,6 @@ MULTI_THREAD_TEST_F(LayerTreeHostTestCrispUpAfterPinchEnds);
class LayerTreeHostTestCrispUpAfterPinchEndsWithOneCopy
: public LayerTreeHostTestCrispUpAfterPinchEnds {
protected:
- void InitializeSettings(LayerTreeSettings* settings) override {
- settings->use_one_copy = true;
- }
-
scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface() override {
scoped_ptr<TestWebGraphicsContext3D> context3d =
TestWebGraphicsContext3D::Create();
@@ -4999,12 +5259,11 @@ class RasterizeWithGpuRasterizationCreatesResources : public LayerTreeHostTest {
scoped_refptr<Layer> root = Layer::Create(layer_settings());
root->SetBounds(gfx::Size(500, 500));
- scoped_ptr<FakePicturePile> pile(
- new FakePicturePile(LayerTreeSettings().minimum_contents_scale,
- LayerTreeSettings().default_tile_grid_size));
+ scoped_ptr<FakeDisplayListRecordingSource> recording(
+ new FakeDisplayListRecordingSource);
scoped_refptr<FakePictureLayer> layer =
FakePictureLayer::CreateWithRecordingSource(layer_settings(), &client_,
- pile.Pass());
+ recording.Pass());
layer->SetBounds(gfx::Size(500, 500));
layer->SetContentsOpaque(true);
root->AddChild(layer);
@@ -5041,12 +5300,11 @@ class GpuRasterizationRasterizesBorderTiles : public LayerTreeHostTest {
void SetupTree() override {
client_.set_fill_with_nonsolid_color(true);
- scoped_ptr<FakePicturePile> pile(
- new FakePicturePile(LayerTreeSettings().minimum_contents_scale,
- LayerTreeSettings().default_tile_grid_size));
+ scoped_ptr<FakeDisplayListRecordingSource> recording(
+ new FakeDisplayListRecordingSource);
scoped_refptr<FakePictureLayer> root =
FakePictureLayer::CreateWithRecordingSource(layer_settings(), &client_,
- pile.Pass());
+ recording.Pass());
root->SetBounds(gfx::Size(10000, 10000));
root->SetContentsOpaque(true);
@@ -5094,21 +5352,19 @@ class LayerTreeHostTestContinuousDrawWhenCreatingVisibleTiles
pinch->SetIsContainerForFixedPositionLayers(true);
root->AddChild(pinch);
- scoped_ptr<FakePicturePile> pile(
- new FakePicturePile(LayerTreeSettings().minimum_contents_scale,
- LayerTreeSettings().default_tile_grid_size));
- pile->SetPlaybackAllowedEvent(&playback_allowed_event_);
+ scoped_ptr<FakeDisplayListRecordingSource> recording(
+ new FakeDisplayListRecordingSource);
+ recording->SetPlaybackAllowedEvent(&playback_allowed_event_);
scoped_refptr<FakePictureLayer> layer =
FakePictureLayer::CreateWithRecordingSource(layer_settings(), &client_,
- pile.Pass());
+ recording.Pass());
layer->SetBounds(gfx::Size(500, 500));
layer->SetContentsOpaque(true);
// Avoid LCD text on the layer so we don't cause extra commits when we
// pinch.
- layer->disable_lcd_text();
pinch->AddChild(layer);
- layer_tree_host()->RegisterViewportLayers(NULL, root, pinch, pinch);
+ layer_tree_host()->RegisterViewportLayers(NULL, root, pinch, nullptr);
layer_tree_host()->SetPageScaleFactorAndLimits(1.f, 1.f, 4.f);
layer_tree_host()->SetRootLayer(root);
LayerTreeHostTest::SetupTree();
@@ -5495,12 +5751,10 @@ class LayerTreeHostTestUpdateCopyRequests : public LayerTreeHostTest {
case 1:
child->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
base::Bind(CopyOutputCallback)));
- EXPECT_TRUE(
- root->draw_properties().layer_or_descendant_has_copy_request);
+ EXPECT_GT(root->num_layer_or_descendants_with_copy_request(), 0);
break;
case 2:
- EXPECT_FALSE(
- root->draw_properties().layer_or_descendant_has_copy_request);
+ EXPECT_EQ(root->num_layer_or_descendants_with_copy_request(), 0);
EndTest();
break;
}
@@ -6057,5 +6311,87 @@ class LayerTreeTestPageScaleFlags : public LayerTreeTest {
SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeTestPageScaleFlags);
+class LayerTreeHostScrollingAndScalingUpdatesLayers : public LayerTreeHostTest {
+ public:
+ LayerTreeHostScrollingAndScalingUpdatesLayers()
+ : requested_update_layers_(false), commit_count_(0) {}
+
+ void SetupTree() override {
+ LayerTreeHostTest::SetupTree();
+ Layer* root_layer = layer_tree_host()->root_layer();
+ scoped_refptr<Layer> scroll_layer = Layer::Create(layer_settings());
+ CreateVirtualViewportLayers(root_layer, scroll_layer, root_layer->bounds(),
+ root_layer->bounds(), layer_tree_host(),
+ layer_settings());
+ }
+
+ void BeginTest() override {
+ LayerTreeHostCommon::ScrollUpdateInfo scroll;
+ scroll.layer_id = layer_tree_host()->root_layer()->id();
+ scroll.scroll_delta = gfx::Vector2d(0, 33);
+ scroll_info_.scrolls.push_back(scroll);
+
+ scale_info_.page_scale_delta = 2.71f;
+
+ PostSetNeedsCommitToMainThread();
+ }
+
+ void BeginMainFrame(const BeginFrameArgs& args) override {
+ switch (commit_count_) {
+ case 0:
+ requested_update_layers_ = false;
+ layer_tree_host()->ApplyScrollAndScale(&no_op_info_);
+ EXPECT_FALSE(requested_update_layers_);
+ break;
+ case 1:
+ requested_update_layers_ = false;
+ layer_tree_host()->ApplyScrollAndScale(&scale_info_);
+ EXPECT_TRUE(requested_update_layers_);
+ break;
+ case 2:
+ requested_update_layers_ = false;
+ layer_tree_host()->ApplyScrollAndScale(&scroll_info_);
+ EXPECT_TRUE(requested_update_layers_);
+ EndTest();
+ break;
+ default:
+ NOTREACHED();
+ }
+ }
+
+ void DidSetNeedsUpdateLayers() override { requested_update_layers_ = true; }
+
+ void DidCommit() override {
+ if (++commit_count_ < 3)
+ PostSetNeedsCommitToMainThread();
+ }
+
+ void AfterTest() override {}
+
+ ScrollAndScaleSet scroll_info_;
+ ScrollAndScaleSet scale_info_;
+ ScrollAndScaleSet no_op_info_;
+ bool requested_update_layers_;
+ int commit_count_;
+};
+
+MULTI_THREAD_TEST_F(LayerTreeHostScrollingAndScalingUpdatesLayers);
+
+class LayerTreeHostTestDestroyWhileInitializingOutputSurface
+ : public LayerTreeHostTest {
+ protected:
+ void BeginTest() override {
+ // By ending the test immediately we start initialization of an output
+ // surface but destroy the LTH before it completes. This test verifies
+ // that this works correctly and the output surface is destroyed on
+ // the correct thread.
+ EndTest();
+ }
+
+ void AfterTest() override {}
+};
+
+MULTI_THREAD_TEST_F(LayerTreeHostTestDestroyWhileInitializingOutputSurface);
+
} // namespace
} // namespace cc
diff --git a/chromium/cc/trees/layer_tree_host_unittest_animation.cc b/chromium/cc/trees/layer_tree_host_unittest_animation.cc
index 9b16e39cb83..c9f922020b2 100644
--- a/chromium/cc/trees/layer_tree_host_unittest_animation.cc
+++ b/chromium/cc/trees/layer_tree_host_unittest_animation.cc
@@ -8,6 +8,8 @@
#include "cc/animation/layer_animation_controller.h"
#include "cc/animation/scroll_offset_animation_curve.h"
#include "cc/animation/timing_function.h"
+#include "cc/animation/transform_operations.h"
+#include "cc/base/completion_event.h"
#include "cc/base/time_util.h"
#include "cc/layers/layer.h"
#include "cc/layers/layer_impl.h"
@@ -227,8 +229,6 @@ SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestAnimationsGetDeleted);
class LayerTreeHostAnimationTestAddAnimationWithTimingFunction
: public LayerTreeHostAnimationTest {
public:
- LayerTreeHostAnimationTestAddAnimationWithTimingFunction() {}
-
void SetupTree() override {
LayerTreeHostAnimationTest::SetupTree();
picture_ = FakePictureLayer::Create(layer_settings(), &client_);
@@ -240,6 +240,10 @@ class LayerTreeHostAnimationTestAddAnimationWithTimingFunction
void AnimateLayers(LayerTreeHostImpl* host_impl,
base::TimeTicks monotonic_time) override {
+ // TODO(ajuma): This test only checks the active tree. Add checks for
+ // pending tree too.
+ if (!host_impl->active_tree()->root_layer())
+ return;
LayerAnimationController* controller_impl =
host_impl->active_tree()->root_layer()->children()[0]->
layer_animation_controller();
@@ -276,8 +280,6 @@ SINGLE_AND_MULTI_THREAD_TEST_F(
class LayerTreeHostAnimationTestSynchronizeAnimationStartTimes
: public LayerTreeHostAnimationTest {
public:
- LayerTreeHostAnimationTestSynchronizeAnimationStartTimes() {}
-
void SetupTree() override {
LayerTreeHostAnimationTest::SetupTree();
picture_ = FakePictureLayer::Create(layer_settings(), &client_);
@@ -331,8 +333,6 @@ SINGLE_AND_MULTI_THREAD_TEST_F(
class LayerTreeHostAnimationTestAnimationFinishedEvents
: public LayerTreeHostAnimationTest {
public:
- LayerTreeHostAnimationTestAnimationFinishedEvents() {}
-
void BeginTest() override {
PostAddInstantAnimationToMainThread(layer_tree_host()->root_layer());
}
@@ -404,8 +404,6 @@ SINGLE_AND_MULTI_THREAD_TEST_F(
class LayerTreeHostAnimationTestLayerAddedWithAnimation
: public LayerTreeHostAnimationTest {
public:
- LayerTreeHostAnimationTestLayerAddedWithAnimation() {}
-
void BeginTest() override { PostSetNeedsCommitToMainThread(); }
void DidCommit() override {
@@ -547,49 +545,6 @@ class LayerTreeHostAnimationTestAnimateAfterSetNeedsCommit
MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestAnimateAfterSetNeedsCommit);
-// Make sure the main thread can still execute animations when CanDraw() is not
-// true.
-class LayerTreeHostAnimationTestRunAnimationWhenNotCanDraw
- : public LayerTreeHostAnimationTest {
- public:
- LayerTreeHostAnimationTestRunAnimationWhenNotCanDraw() : started_times_(0) {}
-
- void SetupTree() override {
- LayerTreeHostAnimationTest::SetupTree();
- picture_ = FakePictureLayer::Create(layer_settings(), &client_);
- picture_->SetBounds(gfx::Size(4, 4));
- picture_->set_layer_animation_delegate(this);
- layer_tree_host()->root_layer()->AddChild(picture_);
- }
-
- void BeginTest() override {
- layer_tree_host()->SetViewportSize(gfx::Size());
- PostAddAnimationToMainThread(picture_.get());
- }
-
- void NotifyAnimationStarted(base::TimeTicks monotonic_time,
- Animation::TargetProperty target_property,
- int group) override {
- started_times_++;
- }
-
- void NotifyAnimationFinished(base::TimeTicks monotonic_time,
- Animation::TargetProperty target_property,
- int group) override {
- EndTest();
- }
-
- void AfterTest() override { EXPECT_EQ(1, started_times_); }
-
- private:
- int started_times_;
- FakeContentLayerClient client_;
- scoped_refptr<FakePictureLayer> picture_;
-};
-
-SINGLE_AND_MULTI_THREAD_TEST_F(
- LayerTreeHostAnimationTestRunAnimationWhenNotCanDraw);
-
// Animations should not be started when frames are being skipped due to
// checkerboard.
class LayerTreeHostAnimationTestCheckerboardDoesntStartAnimations
@@ -610,7 +565,6 @@ class LayerTreeHostAnimationTestCheckerboardDoesntStartAnimations
void BeginTest() override {
prevented_draw_ = 0;
- added_animations_ = 0;
started_times_ = 0;
PostSetNeedsCommitToMainThread();
@@ -619,7 +573,8 @@ class LayerTreeHostAnimationTestCheckerboardDoesntStartAnimations
DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
LayerTreeHostImpl::FrameData* frame_data,
DrawResult draw_result) override {
- if (added_animations_ < 2)
+ // Don't checkerboard when the first animation wants to start.
+ if (host_impl->active_tree()->source_frame_number() < 2)
return draw_result;
if (TestEnded())
return draw_result;
@@ -635,12 +590,10 @@ class LayerTreeHostAnimationTestCheckerboardDoesntStartAnimations
case 1:
// The animation is longer than 1 BeginFrame interval.
AddOpacityTransitionToLayer(picture_.get(), 0.1, 0.2f, 0.8f, false);
- added_animations_++;
break;
case 2:
// This second animation will not be drawn so it should not start.
AddAnimatedTransformToLayer(picture_.get(), 0.1, 5, 5);
- added_animations_++;
break;
}
}
@@ -662,7 +615,6 @@ class LayerTreeHostAnimationTestCheckerboardDoesntStartAnimations
}
int prevented_draw_;
- int added_animations_;
int started_times_;
FakeContentLayerClient client_;
scoped_refptr<FakePictureLayer> picture_;
@@ -677,8 +629,6 @@ MULTI_THREAD_TEST_F(
class LayerTreeHostAnimationTestScrollOffsetChangesArePropagated
: public LayerTreeHostAnimationTest {
public:
- LayerTreeHostAnimationTestScrollOffsetChangesArePropagated() {}
-
void SetupTree() override {
LayerTreeHostAnimationTest::SetupTree();
@@ -921,13 +871,77 @@ class LayerTreeHostAnimationTestAnimationsAddedToNewAndExistingLayers
MULTI_THREAD_BLOCKNOTIFY_TEST_F(
LayerTreeHostAnimationTestAnimationsAddedToNewAndExistingLayers);
+class LayerTreeHostAnimationTestPendingTreeAnimatesFirstCommit
+ : public LayerTreeHostAnimationTest {
+ public:
+ void SetupTree() override {
+ LayerTreeHostAnimationTest::SetupTree();
+
+ layer_ = FakePictureLayer::Create(layer_settings(), &client_);
+ layer_->SetBounds(gfx::Size(2, 2));
+ // Transform the layer to 4,4 to start.
+ gfx::Transform start_transform;
+ start_transform.Translate(4.0, 4.0);
+ layer_->SetTransform(start_transform);
+
+ layer_tree_host()->root_layer()->AddChild(layer_);
+ }
+
+ void BeginTest() override {
+ // Add a translate from 6,7 to 8,9.
+ TransformOperations start;
+ start.AppendTranslate(6.f, 7.f, 0.f);
+ TransformOperations end;
+ end.AppendTranslate(8.f, 9.f, 0.f);
+ AddAnimatedTransformToLayer(layer_.get(), 4.0, start, end);
+
+ PostSetNeedsCommitToMainThread();
+ }
+
+ void WillPrepareTiles(LayerTreeHostImpl* host_impl) override {
+ if (host_impl->sync_tree()->source_frame_number() != 0)
+ return;
+
+ // After checking this on the sync tree, we will activate, which will cause
+ // PrepareTiles to happen again (which races with the test exiting).
+ if (TestEnded())
+ return;
+
+ LayerImpl* root = host_impl->sync_tree()->root_layer();
+ LayerImpl* child = root->children()[0];
+ LayerAnimationController* controller_impl =
+ child->layer_animation_controller();
+ Animation* animation = controller_impl->GetAnimation(Animation::TRANSFORM);
+
+ // The animation should be starting for the first frame.
+ EXPECT_EQ(Animation::STARTING, animation->run_state());
+
+ // And the transform should be propogated to the sync tree layer, at its
+ // starting state which is 6,7.
+ gfx::Transform expected_transform;
+ expected_transform.Translate(6.0, 7.0);
+ EXPECT_EQ(expected_transform, child->draw_transform());
+ // And the sync tree layer should know it is animating.
+ EXPECT_TRUE(child->screen_space_transform_is_animating());
+
+ controller_impl->AbortAnimations(Animation::TRANSFORM);
+ EndTest();
+ }
+
+ void AfterTest() override {}
+
+ FakeContentLayerClient client_;
+ scoped_refptr<Layer> layer_;
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(
+ LayerTreeHostAnimationTestPendingTreeAnimatesFirstCommit);
+
// When a layer with an animation is removed from the tree and later re-added,
// the animation should resume.
class LayerTreeHostAnimationTestAnimatedLayerRemovedAndAdded
: public LayerTreeHostAnimationTest {
public:
- LayerTreeHostAnimationTestAnimatedLayerRemovedAndAdded() {}
-
void SetupTree() override {
LayerTreeHostAnimationTest::SetupTree();
layer_ = Layer::Create(layer_settings());
@@ -1030,6 +1044,228 @@ class LayerTreeHostAnimationTestAddAnimationAfterAnimating
SINGLE_AND_MULTI_THREAD_TEST_F(
LayerTreeHostAnimationTestAddAnimationAfterAnimating);
+class LayerTreeHostAnimationTestRemoveAnimation
+ : public LayerTreeHostAnimationTest {
+ public:
+ void SetupTree() override {
+ LayerTreeHostAnimationTest::SetupTree();
+ layer_ = FakePictureLayer::Create(layer_settings(), &client_);
+ layer_->SetBounds(gfx::Size(4, 4));
+ layer_tree_host()->root_layer()->AddChild(layer_);
+ }
+
+ void BeginTest() override { PostSetNeedsCommitToMainThread(); }
+
+ void DidCommit() override {
+ switch (layer_tree_host()->source_frame_number()) {
+ case 1:
+ AddAnimatedTransformToLayer(layer_.get(), 1.0, 5, 5);
+ break;
+ case 2:
+ LayerAnimationController* controller =
+ layer_->layer_animation_controller();
+ Animation* animation = controller->GetAnimation(Animation::TRANSFORM);
+ layer_->RemoveAnimation(animation->id());
+ gfx::Transform transform;
+ transform.Translate(10.f, 10.f);
+ layer_->SetTransform(transform);
+
+ // Do something that causes property trees to get rebuilt. This is
+ // intended to simulate the conditions that caused the bug whose fix
+ // this is testing (the test will pass without it but won't test what
+ // we want it to). We were updating the wrong transform node at the end
+ // of an animation (we were assuming the layer with the finished
+ // animation still had its own transform node). But nodes can only get
+ // added/deleted when something triggers a rebuild. Adding a layer
+ // triggers a rebuild, and since the layer that had an animation before
+ // no longer has one, it doesn't get a transform node in the rebuild.
+ layer_->AddChild(Layer::Create(layer_settings()));
+ break;
+ }
+ }
+
+ void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override {
+ LayerImpl* root = host_impl->active_tree()->root_layer();
+ LayerImpl* child = root->children()[0];
+ switch (host_impl->active_tree()->source_frame_number()) {
+ case 0:
+ // No animation yet.
+ break;
+ case 1:
+ // Animation is started.
+ EXPECT_TRUE(child->screen_space_transform_is_animating());
+ break;
+ case 2: {
+ // The animation is removed, the transform that was set afterward is
+ // applied.
+ gfx::Transform expected_transform;
+ expected_transform.Translate(10.f, 10.f);
+ EXPECT_EQ(expected_transform, child->draw_transform());
+ EXPECT_FALSE(child->screen_space_transform_is_animating());
+ EndTest();
+ break;
+ }
+ default:
+ NOTREACHED();
+ }
+ }
+
+ void AfterTest() override {}
+
+ private:
+ scoped_refptr<Layer> layer_;
+ FakeContentLayerClient client_;
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestRemoveAnimation);
+
+class LayerTreeHostAnimationTestIsAnimating
+ : public LayerTreeHostAnimationTest {
+ public:
+ void SetupTree() override {
+ LayerTreeHostAnimationTest::SetupTree();
+ layer_ = FakePictureLayer::Create(layer_settings(), &client_);
+ layer_->SetBounds(gfx::Size(4, 4));
+ layer_tree_host()->root_layer()->AddChild(layer_);
+ }
+
+ void BeginTest() override { PostSetNeedsCommitToMainThread(); }
+
+ void DidCommit() override {
+ switch (layer_tree_host()->source_frame_number()) {
+ case 1:
+ AddAnimatedTransformToLayer(layer_.get(), 1.0, 5, 5);
+ break;
+ case 2:
+ LayerAnimationController* controller =
+ layer_->layer_animation_controller();
+ Animation* animation = controller->GetAnimation(Animation::TRANSFORM);
+ layer_->RemoveAnimation(animation->id());
+ break;
+ }
+ }
+
+ void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
+ LayerImpl* root = host_impl->sync_tree()->root_layer();
+ LayerImpl* child = root->children()[0];
+ switch (host_impl->sync_tree()->source_frame_number()) {
+ case 0:
+ // No animation yet.
+ break;
+ case 1:
+ // Animation is started.
+ EXPECT_TRUE(child->screen_space_transform_is_animating());
+ break;
+ case 2:
+ // The animation is removed/stopped.
+ EXPECT_FALSE(child->screen_space_transform_is_animating());
+ EndTest();
+ break;
+ default:
+ NOTREACHED();
+ }
+ }
+
+ void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override {
+ LayerImpl* root = host_impl->active_tree()->root_layer();
+ LayerImpl* child = root->children()[0];
+ switch (host_impl->active_tree()->source_frame_number()) {
+ case 0:
+ // No animation yet.
+ break;
+ case 1:
+ // Animation is started.
+ EXPECT_TRUE(child->screen_space_transform_is_animating());
+ break;
+ case 2:
+ // The animation is removed/stopped.
+ EXPECT_FALSE(child->screen_space_transform_is_animating());
+ EndTest();
+ break;
+ default:
+ NOTREACHED();
+ }
+ }
+
+ void AfterTest() override {}
+
+ private:
+ scoped_refptr<Layer> layer_;
+ FakeContentLayerClient client_;
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestIsAnimating);
+
+class LayerTreeHostAnimationTestAnimationFinishesDuringCommit
+ : public LayerTreeHostAnimationTest {
+ public:
+ LayerTreeHostAnimationTestAnimationFinishesDuringCommit()
+ : signalled_(false) {}
+
+ void SetupTree() override {
+ LayerTreeHostAnimationTest::SetupTree();
+ layer_ = FakePictureLayer::Create(layer_settings(), &client_);
+ layer_->SetBounds(gfx::Size(4, 4));
+ layer_tree_host()->root_layer()->AddChild(layer_);
+ }
+
+ void BeginTest() override { PostSetNeedsCommitToMainThread(); }
+
+ void DidCommit() override {
+ if (layer_tree_host()->source_frame_number() == 1)
+ AddAnimatedTransformToLayer(layer_.get(), 0.04, 5, 5);
+ }
+
+ void WillCommit() override {
+ if (layer_tree_host()->source_frame_number() == 2) {
+ // Block until the animation finishes on the compositor thread. Since
+ // animations have already been ticked on the main thread, when the commit
+ // happens the state on the main thread will be consistent with having a
+ // running animation but the state on the compositor thread will be
+ // consistent with having only a finished animation.
+ completion_.Wait();
+ }
+ }
+
+ void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
+ switch (host_impl->sync_tree()->source_frame_number()) {
+ case 1:
+ PostSetNeedsCommitToMainThread();
+ break;
+ case 2:
+ gfx::Transform expected_transform;
+ expected_transform.Translate(5.f, 5.f);
+ LayerImpl* layer_impl =
+ host_impl->sync_tree()->root_layer()->children()[0];
+ EXPECT_EQ(expected_transform, layer_impl->draw_transform());
+ EndTest();
+ break;
+ }
+ }
+
+ void UpdateAnimationState(LayerTreeHostImpl* host_impl,
+ bool has_unfinished_animation) override {
+ if (host_impl->active_tree()->source_frame_number() == 1 &&
+ !has_unfinished_animation && !signalled_) {
+ // The animation has finished, so allow the main thread to commit.
+ completion_.Signal();
+ signalled_ = true;
+ }
+ }
+
+ void AfterTest() override {}
+
+ private:
+ scoped_refptr<Layer> layer_;
+ FakeContentLayerClient client_;
+ CompletionEvent completion_;
+ bool signalled_;
+};
+
+// An animation finishing during commit can only happen when we have a separate
+// compositor thread.
+MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestAnimationFinishesDuringCommit);
+
class LayerTreeHostAnimationTestNotifyAnimationFinished
: public LayerTreeHostAnimationTest {
public:
@@ -1045,7 +1281,6 @@ class LayerTreeHostAnimationTestNotifyAnimationFinished
}
void BeginTest() override {
- layer_tree_host()->SetViewportSize(gfx::Size());
PostAddLongAnimationToMainThread(picture_.get());
}
diff --git a/chromium/cc/trees/layer_tree_host_unittest_animation_timelines.cc b/chromium/cc/trees/layer_tree_host_unittest_animation_timelines.cc
index 4bf8e83d221..ca7e754b1fb 100644
--- a/chromium/cc/trees/layer_tree_host_unittest_animation_timelines.cc
+++ b/chromium/cc/trees/layer_tree_host_unittest_animation_timelines.cc
@@ -13,6 +13,7 @@
#include "cc/animation/layer_animation_controller.h"
#include "cc/animation/scroll_offset_animation_curve.h"
#include "cc/animation/timing_function.h"
+#include "cc/base/completion_event.h"
#include "cc/base/time_util.h"
#include "cc/layers/layer.h"
#include "cc/layers/layer_impl.h"
@@ -443,53 +444,6 @@ class LayerTreeHostTimelinesTestLayerAddedWithAnimation
SINGLE_AND_MULTI_THREAD_TEST_F(
LayerTreeHostTimelinesTestLayerAddedWithAnimation);
-// Make sure the main thread can still execute animations when CanDraw() is not
-// true.
-// Evolved from LayerTreeHostAnimationTestRunAnimationWhenNotCanDraw
-class LayerTreeHostTimelinesTestRunAnimationWhenNotCanDraw
- : public LayerTreeHostTimelinesTest {
- public:
- LayerTreeHostTimelinesTestRunAnimationWhenNotCanDraw() : started_times_(0) {}
-
- void SetupTree() override {
- LayerTreeHostTimelinesTest::SetupTree();
- picture_ = FakePictureLayer::Create(layer_settings(), &client_);
- picture_->SetBounds(gfx::Size(4, 4));
- layer_tree_host()->root_layer()->AddChild(picture_);
-
- AttachPlayersToTimeline();
- player_child_->AttachLayer(picture_->id());
- player_child_->set_layer_animation_delegate(this);
- }
-
- void BeginTest() override {
- layer_tree_host()->SetViewportSize(gfx::Size());
- PostAddAnimationToMainThreadPlayer(player_child_.get());
- }
-
- void NotifyAnimationStarted(base::TimeTicks monotonic_time,
- Animation::TargetProperty target_property,
- int group) override {
- started_times_++;
- }
-
- void NotifyAnimationFinished(base::TimeTicks monotonic_time,
- Animation::TargetProperty target_property,
- int group) override {
- EndTest();
- }
-
- void AfterTest() override { EXPECT_EQ(1, started_times_); }
-
- private:
- int started_times_;
- FakeContentLayerClient client_;
- scoped_refptr<FakePictureLayer> picture_;
-};
-
-SINGLE_AND_MULTI_THREAD_TEST_F(
- LayerTreeHostTimelinesTestRunAnimationWhenNotCanDraw);
-
// Animations should not be started when frames are being skipped due to
// checkerboard.
// Evolved from LayerTreeHostAnimationTestCheckerboardDoesntStartAnimations.
@@ -515,7 +469,6 @@ class LayerTreeHostTimelinesTestCheckerboardDoesntStartAnimations
void BeginTest() override {
prevented_draw_ = 0;
- added_animations_ = 0;
started_times_ = 0;
PostSetNeedsCommitToMainThread();
@@ -524,7 +477,8 @@ class LayerTreeHostTimelinesTestCheckerboardDoesntStartAnimations
DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
LayerTreeHostImpl::FrameData* frame_data,
DrawResult draw_result) override {
- if (added_animations_ < 2)
+ // Don't checkerboard when the first animation wants to start.
+ if (host_impl->active_tree()->source_frame_number() < 2)
return draw_result;
if (TestEnded())
return draw_result;
@@ -541,12 +495,10 @@ class LayerTreeHostTimelinesTestCheckerboardDoesntStartAnimations
// The animation is longer than 1 BeginFrame interval.
AddOpacityTransitionToPlayer(player_child_.get(), 0.1, 0.2f, 0.8f,
false);
- added_animations_++;
break;
case 2:
// This second animation will not be drawn so it should not start.
AddAnimatedTransformToPlayer(player_child_.get(), 0.1, 5, 5);
- added_animations_++;
break;
}
}
@@ -568,7 +520,6 @@ class LayerTreeHostTimelinesTestCheckerboardDoesntStartAnimations
}
int prevented_draw_;
- int added_animations_;
int started_times_;
FakeContentLayerClient client_;
scoped_refptr<FakePictureLayer> picture_;
@@ -919,5 +870,133 @@ class LayerTreeHostTimelinesTestAddAnimationAfterAnimating
SINGLE_AND_MULTI_THREAD_TEST_F(
LayerTreeHostTimelinesTestAddAnimationAfterAnimating);
+class LayerTreeHostTimelinesTestRemoveAnimation
+ : public LayerTreeHostTimelinesTest {
+ public:
+ void SetupTree() override {
+ LayerTreeHostTimelinesTest::SetupTree();
+ layer_ = FakePictureLayer::Create(layer_settings(), &client_);
+ layer_->SetBounds(gfx::Size(4, 4));
+ layer_tree_host()->root_layer()->AddChild(layer_);
+
+ AttachPlayersToTimeline();
+
+ player_->AttachLayer(layer_tree_host()->root_layer()->id());
+ player_child_->AttachLayer(layer_->id());
+ }
+
+ void BeginTest() override { PostSetNeedsCommitToMainThread(); }
+
+ void DidCommit() override {
+ switch (layer_tree_host()->source_frame_number()) {
+ case 1:
+ AddAnimatedTransformToPlayer(player_child_.get(), 1.0, 5, 5);
+ break;
+ case 2:
+ LayerAnimationController* controller =
+ player_child_->element_animations()->layer_animation_controller();
+ Animation* animation = controller->GetAnimation(Animation::TRANSFORM);
+ player_child_->RemoveAnimation(animation->id());
+ gfx::Transform transform;
+ transform.Translate(10.f, 10.f);
+ layer_->SetTransform(transform);
+
+ // Do something that causes property trees to get rebuilt.
+ layer_->AddChild(Layer::Create(layer_settings()));
+ break;
+ }
+ }
+
+ void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override {
+ if (host_impl->active_tree()->source_frame_number() < 2)
+ return;
+ gfx::Transform expected_transform;
+ expected_transform.Translate(10.f, 10.f);
+ EXPECT_EQ(expected_transform, host_impl->active_tree()
+ ->root_layer()
+ ->children()[0]
+ ->draw_transform());
+ EndTest();
+ }
+
+ void AfterTest() override {}
+
+ private:
+ scoped_refptr<Layer> layer_;
+ FakeContentLayerClient client_;
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTimelinesTestRemoveAnimation);
+
+class LayerTreeHostTimelinesTestAnimationFinishesDuringCommit
+ : public LayerTreeHostTimelinesTest {
+ public:
+ void SetupTree() override {
+ LayerTreeHostTimelinesTest::SetupTree();
+ layer_ = FakePictureLayer::Create(layer_settings(), &client_);
+ layer_->SetBounds(gfx::Size(4, 4));
+ layer_tree_host()->root_layer()->AddChild(layer_);
+
+ AttachPlayersToTimeline();
+
+ player_->AttachLayer(layer_tree_host()->root_layer()->id());
+ player_child_->AttachLayer(layer_->id());
+ }
+
+ void BeginTest() override { PostSetNeedsCommitToMainThread(); }
+
+ void DidCommit() override {
+ if (layer_tree_host()->source_frame_number() == 1)
+ AddAnimatedTransformToPlayer(player_child_.get(), 0.04, 5, 5);
+ }
+
+ void WillCommit() override {
+ if (layer_tree_host()->source_frame_number() == 2) {
+ // Block until the animation finishes on the compositor thread. Since
+ // animations have already been ticked on the main thread, when the commit
+ // happens the state on the main thread will be consistent with having a
+ // running animation but the state on the compositor thread will be
+ // consistent with having only a finished animation.
+ completion_.Wait();
+ }
+ }
+
+ void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
+ switch (host_impl->sync_tree()->source_frame_number()) {
+ case 1:
+ PostSetNeedsCommitToMainThread();
+ break;
+ case 2:
+ gfx::Transform expected_transform;
+ expected_transform.Translate(5.f, 5.f);
+ LayerImpl* layer_impl =
+ host_impl->sync_tree()->root_layer()->children()[0];
+ EXPECT_EQ(expected_transform, layer_impl->draw_transform());
+ EndTest();
+ break;
+ }
+ }
+
+ void UpdateAnimationState(LayerTreeHostImpl* host_impl,
+ bool has_unfinished_animation) override {
+ if (host_impl->active_tree()->source_frame_number() == 1 &&
+ !has_unfinished_animation) {
+ // The animation has finished, so allow the main thread to commit.
+ completion_.Signal();
+ }
+ }
+
+ void AfterTest() override {}
+
+ private:
+ scoped_refptr<Layer> layer_;
+ FakeContentLayerClient client_;
+ CompletionEvent completion_;
+};
+
+// An animation finishing during commit can only happen when we have a separate
+// compositor thread.
+MULTI_THREAD_TEST_F(LayerTreeHostTimelinesTestAnimationFinishesDuringCommit);
+
} // namespace
} // namespace cc
diff --git a/chromium/cc/trees/layer_tree_host_unittest_context.cc b/chromium/cc/trees/layer_tree_host_unittest_context.cc
index d25d047d0a7..34a70b9ab45 100644
--- a/chromium/cc/trees/layer_tree_host_unittest_context.cc
+++ b/chromium/cc/trees/layer_tree_host_unittest_context.cc
@@ -33,7 +33,7 @@
#include "cc/test/fake_scrollbar.h"
#include "cc/test/fake_video_frame_provider.h"
#include "cc/test/layer_tree_test.h"
-#include "cc/test/render_pass_test_common.h"
+#include "cc/test/render_pass_test_utils.h"
#include "cc/test/test_context_provider.h"
#include "cc/test/test_shared_bitmap_manager.h"
#include "cc/test/test_web_graphics_context_3d.h"
@@ -382,6 +382,70 @@ class LayerTreeHostClientNotReadyDoesNotCreateOutputSurface
SINGLE_AND_MULTI_THREAD_TEST_F(
LayerTreeHostClientNotReadyDoesNotCreateOutputSurface);
+// This tests the OutputSurface release logic in the following sequence.
+// SetUp LTH and create and init OutputSurface
+// LTH::SetVisible(false);
+// LTH::ReleaseOutputSurface();
+// ...
+// LTH::SetVisible(true);
+// Create and init new OutputSurface
+class LayerTreeHostClientTakeAwayOutputSurface
+ : public LayerTreeHostContextTest {
+ public:
+ LayerTreeHostClientTakeAwayOutputSurface()
+ : LayerTreeHostContextTest(), setos_counter_(0) {}
+
+ void BeginTest() override { PostSetNeedsCommitToMainThread(); }
+
+ void RequestNewOutputSurface() override {
+ if (layer_tree_host()->visible())
+ CreateAndSetOutputSurface();
+ }
+
+ void CreateAndSetOutputSurface() {
+ scoped_ptr<OutputSurface> surface =
+ LayerTreeHostContextTest::CreateOutputSurface();
+ CHECK(surface);
+ setos_counter_++;
+ layer_tree_host()->SetOutputSurface(surface.Pass());
+ }
+
+ void HideAndReleaseOutputSurface() {
+ EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
+ layer_tree_host()->SetVisible(false);
+ scoped_ptr<OutputSurface> surface =
+ layer_tree_host()->ReleaseOutputSurface();
+ CHECK(surface);
+ MainThreadTaskRunner()->PostTask(
+ FROM_HERE,
+ base::Bind(&LayerTreeHostClientTakeAwayOutputSurface::MakeVisible,
+ base::Unretained(this)));
+ }
+
+ void DidInitializeOutputSurface() override {
+ EXPECT_TRUE(layer_tree_host()->visible());
+ if (setos_counter_ == 1) {
+ MainThreadTaskRunner()->PostTask(
+ FROM_HERE, base::Bind(&LayerTreeHostClientTakeAwayOutputSurface::
+ HideAndReleaseOutputSurface,
+ base::Unretained(this)));
+ } else {
+ EndTest();
+ }
+ }
+
+ void MakeVisible() {
+ EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
+ layer_tree_host()->SetVisible(true);
+ }
+
+ void AfterTest() override {}
+
+ int setos_counter_;
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostClientTakeAwayOutputSurface);
+
class MultipleCompositeDoesNotCreateOutputSurface
: public LayerTreeHostContextTest {
public:
@@ -391,7 +455,6 @@ class MultipleCompositeDoesNotCreateOutputSurface
void InitializeSettings(LayerTreeSettings* settings) override {
settings->single_thread_proxy_scheduler = false;
settings->use_zero_copy = true;
- settings->use_one_copy = false;
}
void RequestNewOutputSurface() override {
@@ -431,7 +494,6 @@ class FailedCreateDoesNotCreateExtraOutputSurface
void InitializeSettings(LayerTreeSettings* settings) override {
settings->single_thread_proxy_scheduler = false;
settings->use_zero_copy = true;
- settings->use_one_copy = false;
}
void RequestNewOutputSurface() override {
@@ -485,7 +547,6 @@ class LayerTreeHostContextTestCommitAfterDelayedOutputSurface
void InitializeSettings(LayerTreeSettings* settings) override {
settings->single_thread_proxy_scheduler = false;
settings->use_zero_copy = true;
- settings->use_one_copy = false;
}
void RequestNewOutputSurface() override {
@@ -528,7 +589,6 @@ class LayerTreeHostContextTestAvoidUnnecessaryComposite
void InitializeSettings(LayerTreeSettings* settings) override {
settings->single_thread_proxy_scheduler = false;
settings->use_zero_copy = true;
- settings->use_one_copy = false;
}
void RequestNewOutputSurface() override {
@@ -565,7 +625,7 @@ class LayerTreeHostContextTestLostContextSucceedsWithContent
// Paint non-solid color.
SkPaint paint;
paint.setColor(SkColorSetARGB(100, 80, 200, 200));
- client_.add_draw_rect(gfx::Rect(0, 0, 5, 5), paint);
+ client_.add_draw_rect(gfx::Rect(5, 5), paint);
layer_ = FakePictureLayer::Create(layer_settings(), &client_);
layer_->SetBounds(gfx::Size(10, 10));
@@ -643,7 +703,7 @@ class LayerTreeHostContextTestLostContextAndEvictTextures
// Paint non-solid color.
SkPaint paint;
paint.setColor(SkColorSetARGB(100, 80, 200, 200));
- client_.add_draw_rect(gfx::Rect(0, 0, 5, 5), paint);
+ client_.add_draw_rect(gfx::Rect(5, 5), paint);
scoped_refptr<FakePictureLayer> picture_layer =
FakePictureLayer::Create(layer_settings(), &client_);
@@ -857,7 +917,7 @@ class LayerTreeHostContextTestDontUseLostResources
scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
- scoped_ptr<TestRenderPass> pass_for_quad = TestRenderPass::Create();
+ scoped_ptr<RenderPass> pass_for_quad = RenderPass::Create();
pass_for_quad->SetNew(
// AppendOneOfEveryQuadType() makes a RenderPass quad with this id.
RenderPassId(2, 1),
@@ -865,13 +925,14 @@ class LayerTreeHostContextTestDontUseLostResources
gfx::Rect(0, 0, 10, 10),
gfx::Transform());
- scoped_ptr<TestRenderPass> pass = TestRenderPass::Create();
+ scoped_ptr<RenderPass> pass = RenderPass::Create();
pass->SetNew(RenderPassId(1, 1),
gfx::Rect(0, 0, 10, 10),
gfx::Rect(0, 0, 10, 10),
gfx::Transform());
- pass->AppendOneOfEveryQuadType(child_resource_provider_.get(),
- RenderPassId(2, 1));
+ uint32_t mailbox_sync_point;
+ AddOneOfEveryQuadType(pass.get(), child_resource_provider_.get(),
+ RenderPassId(2, 1), &mailbox_sync_point);
frame_data->render_pass_list.push_back(pass_for_quad.Pass());
frame_data->render_pass_list.push_back(pass.Pass());
@@ -950,12 +1011,12 @@ class LayerTreeHostContextTestDontUseLostResources
color_video_frame_ = VideoFrame::CreateColorFrame(
gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
hw_video_frame_ = VideoFrame::WrapNativeTexture(
- media::VideoFrame::ARGB,
+ media::PIXEL_FORMAT_ARGB,
gpu::MailboxHolder(mailbox, GL_TEXTURE_2D, sync_point),
media::VideoFrame::ReleaseMailboxCB(), gfx::Size(4, 4),
gfx::Rect(0, 0, 4, 4), gfx::Size(4, 4), base::TimeDelta());
scaled_hw_video_frame_ = VideoFrame::WrapNativeTexture(
- media::VideoFrame::ARGB,
+ media::PIXEL_FORMAT_ARGB,
gpu::MailboxHolder(mailbox, GL_TEXTURE_2D, sync_point),
media::VideoFrame::ReleaseMailboxCB(), gfx::Size(4, 4),
gfx::Rect(0, 0, 3, 2), gfx::Size(4, 4), base::TimeDelta());
@@ -1521,67 +1582,6 @@ class UIResourceLostEviction : public UIResourceLostTestSimple {
SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostEviction);
-class LayerTreeHostContextTestSurfaceCreateCallback
- : public LayerTreeHostContextTest {
- public:
- LayerTreeHostContextTestSurfaceCreateCallback()
- : LayerTreeHostContextTest() {}
-
- void SetupTree() override {
- picture_layer_ = FakePictureLayer::Create(layer_settings(), &client_);
- picture_layer_->SetBounds(gfx::Size(10, 20));
- layer_tree_host()->SetRootLayer(picture_layer_);
-
- LayerTreeHostContextTest::SetupTree();
- }
-
- void BeginTest() override { PostSetNeedsCommitToMainThread(); }
-
- void DidCommit() override {
- switch (layer_tree_host()->source_frame_number()) {
- case 1:
- EXPECT_EQ(1u, picture_layer_->output_surface_created_count());
- layer_tree_host()->SetNeedsCommit();
- break;
- case 2:
- EXPECT_EQ(1u, picture_layer_->output_surface_created_count());
- layer_tree_host()->SetNeedsCommit();
- break;
- case 3:
- EXPECT_EQ(1u, picture_layer_->output_surface_created_count());
- break;
- case 4:
- EXPECT_EQ(2u, picture_layer_->output_surface_created_count());
- layer_tree_host()->SetNeedsCommit();
- break;
- }
- }
-
- void CommitCompleteOnThread(LayerTreeHostImpl* impl) override {
- LayerTreeHostContextTest::CommitCompleteOnThread(impl);
- switch (LastCommittedSourceFrameNumber(impl)) {
- case 0:
- break;
- case 1:
- break;
- case 2:
- LoseContext();
- break;
- case 3:
- EndTest();
- break;
- }
- }
-
- void AfterTest() override {}
-
- protected:
- FakeContentLayerClient client_;
- scoped_refptr<FakePictureLayer> picture_layer_;
-};
-
-SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestSurfaceCreateCallback);
-
class LayerTreeHostContextTestLoseAfterSendingBeginMainFrame
: public LayerTreeHostContextTest {
protected:
diff --git a/chromium/cc/trees/layer_tree_host_unittest_damage.cc b/chromium/cc/trees/layer_tree_host_unittest_damage.cc
index fc5cacf087e..20667bf54a2 100644
--- a/chromium/cc/trees/layer_tree_host_unittest_damage.cc
+++ b/chromium/cc/trees/layer_tree_host_unittest_damage.cc
@@ -55,17 +55,17 @@ class LayerTreeHostDamageTestSetNeedsRedraw
RenderSurfaceImpl* root_surface =
impl->active_tree()->root_layer()->render_surface();
- gfx::RectF root_damage =
+ gfx::Rect root_damage =
root_surface->damage_tracker()->current_damage_rect();
switch (draw_count_) {
case 0:
// The first frame has full damage.
- EXPECT_EQ(gfx::RectF(10.f, 10.f).ToString(), root_damage.ToString());
+ EXPECT_EQ(gfx::Rect(10, 10), root_damage);
break;
case 1:
// The second frame has full damage.
- EXPECT_EQ(gfx::RectF(10.f, 10.f).ToString(), root_damage.ToString());
+ EXPECT_EQ(gfx::Rect(10, 10), root_damage);
EndTest();
break;
case 2:
@@ -117,17 +117,17 @@ class LayerTreeHostDamageTestSetViewportSize
RenderSurfaceImpl* root_surface =
impl->active_tree()->root_layer()->render_surface();
- gfx::RectF root_damage =
+ gfx::Rect root_damage =
root_surface->damage_tracker()->current_damage_rect();
switch (draw_count_) {
case 0:
// The first frame has full damage.
- EXPECT_EQ(gfx::RectF(10.f, 10.f).ToString(), root_damage.ToString());
+ EXPECT_EQ(gfx::Rect(10, 10), root_damage);
break;
case 1:
// The second frame has full damage.
- EXPECT_EQ(gfx::RectF(15.f, 15.f).ToString(), root_damage.ToString());
+ EXPECT_EQ(gfx::Rect(15, 15), root_damage);
EndTest();
break;
case 2:
@@ -260,7 +260,7 @@ class LayerTreeHostDamageTestForcedFullDamage : public LayerTreeHostDamageTest {
RenderSurfaceImpl* root_surface =
host_impl->active_tree()->root_layer()->render_surface();
- gfx::RectF root_damage =
+ gfx::Rect root_damage =
root_surface->damage_tracker()->current_damage_rect();
root_damage.Intersect(root_surface->content_rect());
@@ -268,13 +268,12 @@ class LayerTreeHostDamageTestForcedFullDamage : public LayerTreeHostDamageTest {
switch (source_frame) {
case 0:
// The first frame draws and clears any damage.
- EXPECT_EQ(gfx::RectF(root_surface->content_rect()).ToString(),
- root_damage.ToString());
+ EXPECT_EQ(root_surface->content_rect(), root_damage);
EXPECT_FALSE(frame_data->has_no_damage);
break;
case 1:
// If we get a frame without damage then we don't draw.
- EXPECT_EQ(gfx::RectF().ToString(), root_damage.ToString());
+ EXPECT_EQ(gfx::Rect(), root_damage);
EXPECT_TRUE(frame_data->has_no_damage);
// Then we set full damage for the next frame.
@@ -282,8 +281,7 @@ class LayerTreeHostDamageTestForcedFullDamage : public LayerTreeHostDamageTest {
break;
case 2:
// The whole frame should be damaged as requested.
- EXPECT_EQ(gfx::RectF(root_surface->content_rect()).ToString(),
- root_damage.ToString());
+ EXPECT_EQ(root_surface->content_rect(), root_damage);
EXPECT_FALSE(frame_data->has_no_damage);
// Just a part of the next frame should be damaged.
@@ -292,8 +290,7 @@ class LayerTreeHostDamageTestForcedFullDamage : public LayerTreeHostDamageTest {
case 3:
// The update rect in the child should be damaged and the damaged area
// should match the invalidation.
- EXPECT_EQ(gfx::RectF(100+10, 100+11, 12, 13).ToString(),
- root_damage.ToString());
+ EXPECT_EQ(gfx::Rect(100 + 10, 100 + 11, 12, 13), root_damage);
EXPECT_FALSE(frame_data->has_no_damage);
// If we damage part of the frame, but also damage the full
@@ -303,8 +300,7 @@ class LayerTreeHostDamageTestForcedFullDamage : public LayerTreeHostDamageTest {
break;
case 4:
// The whole frame is damaged.
- EXPECT_EQ(gfx::RectF(root_surface->content_rect()).ToString(),
- root_damage.ToString());
+ EXPECT_EQ(root_surface->content_rect(), root_damage);
EXPECT_FALSE(frame_data->has_no_damage);
EndTest();
@@ -362,9 +358,9 @@ class LayerTreeHostScrollbarDamageTest : public LayerTreeHostDamageTest {
root_layer->AddChild(scrollbar_layer);
gfx::RectF content_rect(content_layer->position(),
- content_layer->bounds());
+ gfx::SizeF(content_layer->bounds()));
gfx::RectF scrollbar_rect(scrollbar_layer->position(),
- scrollbar_layer->bounds());
+ gfx::SizeF(scrollbar_layer->bounds()));
EXPECT_FALSE(content_rect.Intersects(scrollbar_rect));
LayerTreeHostDamageTest::SetupTree();
@@ -387,7 +383,7 @@ class LayerTreeHostDamageTestScrollbarDoesDamage
EXPECT_EQ(DRAW_SUCCESS, draw_result);
RenderSurfaceImpl* root_surface =
host_impl->active_tree()->root_layer()->render_surface();
- gfx::RectF root_damage =
+ gfx::Rect root_damage =
root_surface->damage_tracker()->current_damage_rect();
root_damage.Intersect(root_surface->content_rect());
switch (did_swaps_) {
@@ -421,10 +417,10 @@ class LayerTreeHostDamageTestScrollbarDoesDamage
case 1:
// Test that modifying the position of the content layer (not
// scrolling) won't damage the scrollbar.
- scroll_layer->SetPosition(gfx::Point(1, 1));
- scroll_layer->PushScrollOffsetFromMainThread(
- scroll_layer->BaseScrollOffset());
- host_impl->SetNeedsRedraw();
+ MainThreadTaskRunner()->PostTask(
+ FROM_HERE, base::Bind(&LayerTreeHostDamageTestScrollbarDoesDamage::
+ ModifyContentLayerPosition,
+ base::Unretained(this)));
break;
case 2:
scroll_layer->ScrollBy(gfx::Vector2dF(10.f, 10.f));
@@ -441,6 +437,14 @@ class LayerTreeHostDamageTestScrollbarDoesDamage
}
}
+ void ModifyContentLayerPosition() {
+ EXPECT_EQ(1, did_swaps_);
+ Layer* root = layer_tree_host()->root_layer();
+ Layer* scroll_clip_layer = root->child_at(0);
+ Layer* scroll_layer = scroll_clip_layer->child_at(0);
+ scroll_layer->SetPosition(gfx::Point(10, 10));
+ }
+
void ResizeScrollLayer() {
EXPECT_EQ(3, did_swaps_);
Layer* root = layer_tree_host()->root_layer();
@@ -470,7 +474,7 @@ class LayerTreeHostDamageTestScrollbarCommitDoesNoDamage
EXPECT_EQ(DRAW_SUCCESS, draw_result);
RenderSurfaceImpl* root_surface =
host_impl->active_tree()->root_layer()->render_surface();
- gfx::RectF root_damage =
+ gfx::Rect root_damage =
root_surface->damage_tracker()->current_damage_rect();
root_damage.Intersect(root_surface->content_rect());
int frame = host_impl->active_tree()->source_frame_number();
diff --git a/chromium/cc/trees/layer_tree_host_unittest_delegated.cc b/chromium/cc/trees/layer_tree_host_unittest_delegated.cc
index 2ebb337e807..f5aafaf2efc 100644
--- a/chromium/cc/trees/layer_tree_host_unittest_delegated.cc
+++ b/chromium/cc/trees/layer_tree_host_unittest_delegated.cc
@@ -8,6 +8,7 @@
#include "base/bind.h"
#include "base/location.h"
+#include "base/synchronization/lock.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread.h"
#include "base/time/time.h"
@@ -1748,14 +1749,23 @@ class DelegatedFrameIsActivatedDuringCommit
}
void WillActivateTreeOnThread(LayerTreeHostImpl* impl) override {
+ base::AutoLock lock(activate_count_lock_);
++activate_count_;
}
void DidCommit() override {
+ // The first frame doesn't cause anything to be returned so it does not
+ // need to wait for activation.
+ if (layer_tree_host()->source_frame_number() > 1) {
+ base::AutoLock lock(activate_count_lock_);
+ // The activate happened before commit is done on the main side.
+ EXPECT_EQ(activate_count_, layer_tree_host()->source_frame_number());
+ }
+
switch (layer_tree_host()->source_frame_number()) {
case 1: {
- // The first frame has been activated. Set a new frame, and
- // expect the next commit to finish *after* it is activated.
+ // The first frame has been committed and will activate. Set a new
+ // frame, and expect the next commit to finish *after* it is activated.
scoped_ptr<DelegatedFrameData> frame =
CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1));
AddTextureQuad(frame.get(), 555);
@@ -1779,27 +1789,9 @@ class DelegatedFrameIsActivatedDuringCommit
}
void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
- switch (host_impl->active_tree()->source_frame_number()) {
- case 0: {
- // The activate for the 1st frame should have happened before now.
- EXPECT_EQ(1, activate_count_);
- break;
- }
- case 1: {
- // The activate for the 2nd frame should have happened before now.
- EXPECT_EQ(2, activate_count_);
- break;
- }
- case 2: {
- // The activate to remove the layer should have happened before now.
- EXPECT_EQ(3, activate_count_);
- break;
- }
- case 3: {
- NOTREACHED();
- break;
- }
- }
+ // The activate didn't happen before commit is done on the impl side (but it
+ // should happen before the main thread is done).
+ EXPECT_EQ(activate_count_, host_impl->sync_tree()->source_frame_number());
}
void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override {
@@ -1817,6 +1809,7 @@ class DelegatedFrameIsActivatedDuringCommit
EndTest();
}
+ base::Lock activate_count_lock_;
int activate_count_;
size_t returned_resource_count_;
};
diff --git a/chromium/cc/trees/layer_tree_host_unittest_picture.cc b/chromium/cc/trees/layer_tree_host_unittest_picture.cc
index 7a0d7bfa520..9c5d00eddb1 100644
--- a/chromium/cc/trees/layer_tree_host_unittest_picture.cc
+++ b/chromium/cc/trees/layer_tree_host_unittest_picture.cc
@@ -210,6 +210,10 @@ class LayerTreeHostPictureTestChangeLiveTilesRectWithRecycleTree
picture_->SetBounds(gfx::Size(100, 100000));
root->AddChild(picture_);
+ // picture_'s transform is going to be changing on the compositor thread, so
+ // force it to have a transform node by making it scrollable.
+ picture_->SetScrollClipLayerId(root->id());
+
layer_tree_host()->SetRootLayer(root);
LayerTreeHostPictureTest::SetupTree();
}
@@ -406,7 +410,7 @@ class LayerTreeHostPictureTestRSLLMembershipWithScale
picture_->SetBounds(gfx::Size(100, 100));
pinch_->AddChild(picture_);
- layer_tree_host()->RegisterViewportLayers(NULL, root, pinch_, pinch_);
+ layer_tree_host()->RegisterViewportLayers(NULL, root, pinch_, nullptr);
layer_tree_host()->SetPageScaleFactorAndLimits(1.f, 1.f, 4.f);
layer_tree_host()->SetRootLayer(root);
LayerTreeHostPictureTest::SetupTree();
@@ -420,6 +424,7 @@ class LayerTreeHostPictureTestRSLLMembershipWithScale
frame_ = 0;
draws_in_frame_ = 0;
last_frame_drawn_ = -1;
+ ready_to_draw_ = false;
PostSetNeedsCommitToMainThread();
}
@@ -428,19 +433,25 @@ class LayerTreeHostPictureTestRSLLMembershipWithScale
LayerImpl* pinch = root->children()[0];
LayerImpl* gchild = pinch->children()[0];
FakePictureLayerImpl* picture = static_cast<FakePictureLayerImpl*>(gchild);
+ ready_to_draw_ = false;
switch (frame_) {
case 0:
- // On 1st commit the layer has tilings.
- EXPECT_GT(picture->tilings()->num_tilings(), 0u);
+ // On 1st commit the pending layer has tilings.
+ ASSERT_EQ(1u, picture->tilings()->num_tilings());
+ EXPECT_EQ(1.f, picture->tilings()->tiling_at(0)->contents_scale());
break;
case 1:
- // On 2nd commit, the layer is transparent, so does not have tilings.
- EXPECT_EQ(0u, picture->tilings()->num_tilings());
+ // On 2nd commit, the pending layer is transparent, so has a stale
+ // value.
+ ASSERT_EQ(1u, picture->tilings()->num_tilings());
+ EXPECT_EQ(1.f, picture->tilings()->tiling_at(0)->contents_scale());
break;
case 2:
- // On 3rd commit, the layer is visible again, so has tilings.
- EXPECT_GT(picture->tilings()->num_tilings(), 0u);
+ // On 3rd commit, the pending layer is visible again, so has tilings and
+ // is updated for the pinch.
+ ASSERT_EQ(1u, picture->tilings()->num_tilings());
+ EXPECT_EQ(2.f, picture->tilings()->tiling_at(0)->contents_scale());
}
}
@@ -470,30 +481,29 @@ class LayerTreeHostPictureTestRSLLMembershipWithScale
// If the pinch gesture caused a commit we could get here with a
// pending tree.
EXPECT_FALSE(impl->pending_tree());
- // The active layer now has only a 2.f scale tiling, which means the
- // recycled layer's tiling is destroyed.
EXPECT_EQ(2.f, picture->HighResTiling()->contents_scale());
- EXPECT_EQ(0u, picture->GetRecycledTwinLayer()
- ->picture_layer_tiling_set()
- ->num_tilings());
-
- ++frame_;
- MainThreadTaskRunner()->PostTask(
- FROM_HERE,
- base::Bind(
- &LayerTreeHostPictureTestRSLLMembershipWithScale::NextStep,
- base::Unretained(this)));
+
+ // Need to wait for ready to draw here so that the pinch is
+ // entirely complete, otherwise another draw might come in before
+ // the commit occurs.
+ if (ready_to_draw_) {
+ ++frame_;
+ MainThreadTaskRunner()->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &LayerTreeHostPictureTestRSLLMembershipWithScale::NextStep,
+ base::Unretained(this)));
+ }
}
break;
case 1:
EXPECT_EQ(1, draws_in_frame_);
- // On 2nd commit, the layer is transparent, so does not create
- // tilings. Since the 1.f tiling was destroyed in the recycle tree, it
- // has no tilings left. This is propogated to the active tree.
- EXPECT_EQ(0u, picture->picture_layer_tiling_set()->num_tilings());
- EXPECT_EQ(0u, picture->GetRecycledTwinLayer()
- ->picture_layer_tiling_set()
- ->num_tilings());
+ // On 2nd commit, this active layer is transparent, so does not update
+ // tilings. It has the high res scale=2 from the previous frame, and
+ // also a scale=1 copied from the pending layer's stale value during
+ // activation.
+ EXPECT_EQ(2u, picture->picture_layer_tiling_set()->num_tilings());
+
++frame_;
MainThreadTaskRunner()->PostTask(
FROM_HERE,
@@ -524,6 +534,16 @@ class LayerTreeHostPictureTestRSLLMembershipWithScale
}
}
+ void NotifyReadyToDrawOnThread(LayerTreeHostImpl* impl) override {
+ ready_to_draw_ = true;
+ if (frame_ == 0) {
+ // The ready to draw can race with a draw in which everything is
+ // actually ready. Therefore, just issue one more extra draw
+ // here to force notify->draw ordering.
+ impl->SetNeedsRedraw();
+ }
+ }
+
void AfterTest() override {}
FakeContentLayerClient client_;
@@ -532,12 +552,12 @@ class LayerTreeHostPictureTestRSLLMembershipWithScale
int frame_;
int draws_in_frame_;
int last_frame_drawn_;
+ bool ready_to_draw_;
};
// Multi-thread only because in single thread you can't pinch zoom on the
// compositor thread.
-// Disabled due to flakiness. See http://crbug.com/460581
-// MULTI_THREAD_TEST_F(LayerTreeHostPictureTestRSLLMembershipWithScale);
+MULTI_THREAD_TEST_F(LayerTreeHostPictureTestRSLLMembershipWithScale);
} // namespace
} // namespace cc
diff --git a/chromium/cc/trees/layer_tree_host_unittest_proxy.cc b/chromium/cc/trees/layer_tree_host_unittest_proxy.cc
index 66340e7bbff..d4057cfa10a 100644
--- a/chromium/cc/trees/layer_tree_host_unittest_proxy.cc
+++ b/chromium/cc/trees/layer_tree_host_unittest_proxy.cc
@@ -4,6 +4,8 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
+#include "cc/test/fake_content_layer_client.h"
+#include "cc/test/fake_picture_layer.h"
#include "cc/test/layer_tree_test.h"
#include "cc/trees/thread_proxy.h"
@@ -71,9 +73,16 @@ PROXY_TEST_SCHEDULED_ACTION(ProxyTestScheduledActionsBasic);
class ThreadProxyTest : public ProxyTest {
protected:
- ThreadProxyTest() {}
+ ThreadProxyTest()
+ : update_check_layer_(
+ FakePictureLayer::Create(layer_settings(), &client_)) {}
~ThreadProxyTest() override {}
+ void SetupTree() override {
+ layer_tree_host()->SetRootLayer(update_check_layer_);
+ ProxyTest::SetupTree();
+ }
+
const ThreadProxy::MainThreadOnly& ThreadProxyMainOnly() const {
DCHECK(proxy());
DCHECK(proxy()->HasImplThread());
@@ -86,6 +95,10 @@ class ThreadProxyTest : public ProxyTest {
return static_cast<const ThreadProxy*>(proxy())->impl();
}
+ protected:
+ FakeContentLayerClient client_;
+ scoped_refptr<FakePictureLayer> update_check_layer_;
+
private:
DISALLOW_COPY_AND_ASSIGN(ThreadProxyTest);
};
@@ -96,19 +109,26 @@ class ThreadProxyTestSetNeedsCommit : public ThreadProxyTest {
~ThreadProxyTestSetNeedsCommit() override {}
void BeginTest() override {
- EXPECT_FALSE(ThreadProxyMainOnly().commit_requested);
- EXPECT_FALSE(ThreadProxyMainOnly().commit_request_sent_to_impl_thread);
+ EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
+ ThreadProxyMainOnly().max_requested_pipeline_stage);
proxy()->SetNeedsCommit();
- EXPECT_TRUE(ThreadProxyMainOnly().commit_requested);
- EXPECT_TRUE(ThreadProxyMainOnly().commit_request_sent_to_impl_thread);
+ EXPECT_EQ(ThreadProxy::COMMIT_PIPELINE_STAGE,
+ ThreadProxyMainOnly().max_requested_pipeline_stage);
}
void DidBeginMainFrame() override {
- EXPECT_FALSE(ThreadProxyMainOnly().commit_requested);
- EXPECT_FALSE(ThreadProxyMainOnly().commit_request_sent_to_impl_thread);
+ EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
+ ThreadProxyMainOnly().max_requested_pipeline_stage);
+ EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
+ ThreadProxyMainOnly().current_pipeline_stage);
+ }
+ void DidCommit() override {
+ EXPECT_EQ(1, update_check_layer_->update_count());
+ EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
+ ThreadProxyMainOnly().current_pipeline_stage);
EndTest();
}
@@ -118,4 +138,153 @@ class ThreadProxyTestSetNeedsCommit : public ThreadProxyTest {
THREAD_PROXY_TEST_F(ThreadProxyTestSetNeedsCommit);
+class ThreadProxyTestSetNeedsAnimate : public ThreadProxyTest {
+ protected:
+ ThreadProxyTestSetNeedsAnimate() {}
+ ~ThreadProxyTestSetNeedsAnimate() override {}
+
+ void BeginTest() override {
+ EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
+ ThreadProxyMainOnly().max_requested_pipeline_stage);
+
+ proxy()->SetNeedsAnimate();
+
+ EXPECT_EQ(ThreadProxy::ANIMATE_PIPELINE_STAGE,
+ ThreadProxyMainOnly().max_requested_pipeline_stage);
+ }
+
+ void DidBeginMainFrame() override {
+ EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
+ ThreadProxyMainOnly().max_requested_pipeline_stage);
+ EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
+ ThreadProxyMainOnly().current_pipeline_stage);
+ }
+
+ void DidCommit() override {
+ EXPECT_EQ(0, update_check_layer_->update_count());
+ EndTest();
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ThreadProxyTestSetNeedsAnimate);
+};
+
+THREAD_PROXY_TEST_F(ThreadProxyTestSetNeedsAnimate);
+
+class ThreadProxyTestSetNeedsUpdateLayers : public ThreadProxyTest {
+ protected:
+ ThreadProxyTestSetNeedsUpdateLayers() {}
+ ~ThreadProxyTestSetNeedsUpdateLayers() override {}
+
+ void BeginTest() override {
+ EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
+ ThreadProxyMainOnly().max_requested_pipeline_stage);
+
+ proxy()->SetNeedsUpdateLayers();
+
+ EXPECT_EQ(ThreadProxy::UPDATE_LAYERS_PIPELINE_STAGE,
+ ThreadProxyMainOnly().max_requested_pipeline_stage);
+ }
+
+ void DidBeginMainFrame() override {
+ EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
+ ThreadProxyMainOnly().max_requested_pipeline_stage);
+ EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
+ ThreadProxyMainOnly().current_pipeline_stage);
+ }
+
+ void DidCommit() override {
+ EXPECT_EQ(1, update_check_layer_->update_count());
+ EndTest();
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ThreadProxyTestSetNeedsUpdateLayers);
+};
+
+THREAD_PROXY_TEST_F(ThreadProxyTestSetNeedsUpdateLayers);
+
+class ThreadProxyTestSetNeedsUpdateLayersWhileAnimating
+ : public ThreadProxyTest {
+ protected:
+ ThreadProxyTestSetNeedsUpdateLayersWhileAnimating() {}
+ ~ThreadProxyTestSetNeedsUpdateLayersWhileAnimating() override {}
+
+ void BeginTest() override { proxy()->SetNeedsAnimate(); }
+
+ void WillBeginMainFrame() override {
+ EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
+ ThreadProxyMainOnly().max_requested_pipeline_stage);
+ EXPECT_EQ(ThreadProxy::ANIMATE_PIPELINE_STAGE,
+ ThreadProxyMainOnly().current_pipeline_stage);
+ EXPECT_EQ(ThreadProxy::ANIMATE_PIPELINE_STAGE,
+ ThreadProxyMainOnly().final_pipeline_stage);
+
+ proxy()->SetNeedsUpdateLayers();
+
+ EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
+ ThreadProxyMainOnly().max_requested_pipeline_stage);
+ EXPECT_EQ(ThreadProxy::UPDATE_LAYERS_PIPELINE_STAGE,
+ ThreadProxyMainOnly().final_pipeline_stage);
+ }
+
+ void DidBeginMainFrame() override {
+ EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
+ ThreadProxyMainOnly().max_requested_pipeline_stage);
+ EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
+ ThreadProxyMainOnly().current_pipeline_stage);
+ }
+
+ void DidCommit() override {
+ EXPECT_EQ(1, update_check_layer_->update_count());
+ EndTest();
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ThreadProxyTestSetNeedsUpdateLayersWhileAnimating);
+};
+
+THREAD_PROXY_TEST_F(ThreadProxyTestSetNeedsUpdateLayersWhileAnimating);
+
+class ThreadProxyTestSetNeedsCommitWhileAnimating : public ThreadProxyTest {
+ protected:
+ ThreadProxyTestSetNeedsCommitWhileAnimating() {}
+ ~ThreadProxyTestSetNeedsCommitWhileAnimating() override {}
+
+ void BeginTest() override { proxy()->SetNeedsAnimate(); }
+
+ void WillBeginMainFrame() override {
+ EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
+ ThreadProxyMainOnly().max_requested_pipeline_stage);
+ EXPECT_EQ(ThreadProxy::ANIMATE_PIPELINE_STAGE,
+ ThreadProxyMainOnly().current_pipeline_stage);
+ EXPECT_EQ(ThreadProxy::ANIMATE_PIPELINE_STAGE,
+ ThreadProxyMainOnly().final_pipeline_stage);
+
+ proxy()->SetNeedsCommit();
+
+ EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
+ ThreadProxyMainOnly().max_requested_pipeline_stage);
+ EXPECT_EQ(ThreadProxy::COMMIT_PIPELINE_STAGE,
+ ThreadProxyMainOnly().final_pipeline_stage);
+ }
+
+ void DidBeginMainFrame() override {
+ EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
+ ThreadProxyMainOnly().max_requested_pipeline_stage);
+ EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
+ ThreadProxyMainOnly().current_pipeline_stage);
+ }
+
+ void DidCommit() override {
+ EXPECT_EQ(1, update_check_layer_->update_count());
+ EndTest();
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ThreadProxyTestSetNeedsCommitWhileAnimating);
+};
+
+THREAD_PROXY_TEST_F(ThreadProxyTestSetNeedsCommitWhileAnimating);
+
} // namespace cc
diff --git a/chromium/cc/trees/layer_tree_host_unittest_scroll.cc b/chromium/cc/trees/layer_tree_host_unittest_scroll.cc
index dc075b563cf..79fde4f24a6 100644
--- a/chromium/cc/trees/layer_tree_host_unittest_scroll.cc
+++ b/chromium/cc/trees/layer_tree_host_unittest_scroll.cc
@@ -28,7 +28,24 @@
namespace cc {
namespace {
-class LayerTreeHostScrollTest : public LayerTreeTest {};
+class LayerTreeHostScrollTest : public LayerTreeTest {
+ protected:
+ void SetupTree() override {
+ LayerTreeTest::SetupTree();
+ Layer* root_layer = layer_tree_host()->root_layer();
+
+ // Create an effective max_scroll_offset of (100, 100).
+ gfx::Size scroll_layer_bounds(root_layer->bounds().width() + 100,
+ root_layer->bounds().height() + 100);
+
+ CreateVirtualViewportLayers(root_layer,
+ root_layer->bounds(),
+ root_layer->bounds(),
+ scroll_layer_bounds,
+ layer_tree_host(),
+ layer_settings());
+ }
+};
class LayerTreeHostScrollTestScrollSimple : public LayerTreeHostScrollTest {
public:
@@ -39,24 +56,13 @@ class LayerTreeHostScrollTestScrollSimple : public LayerTreeHostScrollTest {
num_scrolls_(0) {}
void BeginTest() override {
- Layer* root_layer = layer_tree_host()->root_layer();
- scoped_refptr<Layer> scroll_layer = Layer::Create(layer_settings());
- root_layer->AddChild(scroll_layer);
- // Create an effective max_scroll_offset of (100, 100).
- scroll_layer->SetBounds(gfx::Size(root_layer->bounds().width() + 100,
- root_layer->bounds().height() + 100));
- scroll_layer->SetIsDrawable(true);
- scroll_layer->SetIsContainerForFixedPositionLayers(true);
- scroll_layer->SetScrollClipLayerId(root_layer->id());
- scroll_layer->SetScrollOffset(initial_scroll_);
- layer_tree_host()->RegisterViewportLayers(NULL, root_layer, scroll_layer,
- NULL);
+ layer_tree_host()->outer_viewport_scroll_layer()->SetScrollOffset(
+ initial_scroll_);
PostSetNeedsCommitToMainThread();
}
void Layout() override {
- Layer* root = layer_tree_host()->root_layer();
- Layer* scroll_layer = root->children()[0].get();
+ Layer* scroll_layer = layer_tree_host()->outer_viewport_scroll_layer();
if (!layer_tree_host()->source_frame_number()) {
EXPECT_VECTOR_EQ(initial_scroll_, scroll_layer->scroll_offset());
} else {
@@ -71,7 +77,7 @@ class LayerTreeHostScrollTestScrollSimple : public LayerTreeHostScrollTest {
void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
LayerImpl* root = impl->active_tree()->root_layer();
- LayerImpl* scroll_layer = root->children()[0];
+ LayerImpl* scroll_layer = impl->OuterViewportScrollLayer();
EXPECT_VECTOR_EQ(gfx::Vector2d(), scroll_layer->ScrollDelta());
scroll_layer->SetScrollClipLayer(root->id());
@@ -86,8 +92,8 @@ class LayerTreeHostScrollTestScrollSimple : public LayerTreeHostScrollTest {
PostSetNeedsCommitToMainThread();
break;
case 1:
- EXPECT_VECTOR_EQ(scroll_layer->BaseScrollOffset(), second_scroll_);
- EXPECT_VECTOR_EQ(scroll_layer->ScrollDelta(), scroll_amount_);
+ EXPECT_VECTOR_EQ(second_scroll_, scroll_layer->BaseScrollOffset());
+ EXPECT_VECTOR_EQ(scroll_amount_, scroll_layer->ScrollDelta());
EndTest();
break;
}
@@ -119,36 +125,26 @@ class LayerTreeHostScrollTestScrollMultipleRedraw
: initial_scroll_(40, 10), scroll_amount_(-3, 17), num_scrolls_(0) {}
void BeginTest() override {
- Layer* root_layer = layer_tree_host()->root_layer();
- scroll_layer_ = Layer::Create(layer_settings());
- root_layer->AddChild(scroll_layer_);
- // Create an effective max_scroll_offset of (100, 100).
- scroll_layer_->SetBounds(gfx::Size(root_layer->bounds().width() + 100,
- root_layer->bounds().height() + 100));
- scroll_layer_->SetIsDrawable(true);
- scroll_layer_->SetIsContainerForFixedPositionLayers(true);
- scroll_layer_->SetScrollClipLayerId(root_layer->id());
+ scroll_layer_ = layer_tree_host()->outer_viewport_scroll_layer();
scroll_layer_->SetScrollOffset(initial_scroll_);
- layer_tree_host()->RegisterViewportLayers(NULL, root_layer, scroll_layer_,
- NULL);
PostSetNeedsCommitToMainThread();
}
void BeginCommitOnThread(LayerTreeHostImpl* impl) override {
switch (layer_tree_host()->source_frame_number()) {
case 0:
- EXPECT_VECTOR_EQ(scroll_layer_->scroll_offset(), initial_scroll_);
+ EXPECT_VECTOR_EQ(initial_scroll_, scroll_layer_->scroll_offset());
break;
case 1:
EXPECT_VECTOR_EQ(
- scroll_layer_->scroll_offset(),
gfx::ScrollOffsetWithDelta(initial_scroll_,
- scroll_amount_ + scroll_amount_));
+ scroll_amount_ + scroll_amount_),
+ scroll_layer_->scroll_offset());
case 2:
EXPECT_VECTOR_EQ(
- scroll_layer_->scroll_offset(),
gfx::ScrollOffsetWithDelta(initial_scroll_,
- scroll_amount_ + scroll_amount_));
+ scroll_amount_ + scroll_amount_),
+ scroll_layer_->scroll_offset());
break;
}
}
@@ -159,30 +155,30 @@ class LayerTreeHostScrollTestScrollMultipleRedraw
if (impl->active_tree()->source_frame_number() == 0 &&
impl->SourceAnimationFrameNumberForTesting() == 1) {
// First draw after first commit.
- EXPECT_VECTOR_EQ(scroll_layer->ScrollDelta(), gfx::Vector2d());
+ EXPECT_VECTOR_EQ(gfx::Vector2d(), scroll_layer->ScrollDelta());
scroll_layer->ScrollBy(scroll_amount_);
- EXPECT_VECTOR_EQ(scroll_layer->ScrollDelta(), scroll_amount_);
+ EXPECT_VECTOR_EQ(scroll_amount_, scroll_layer->ScrollDelta());
- EXPECT_VECTOR_EQ(scroll_layer->BaseScrollOffset(), initial_scroll_);
+ EXPECT_VECTOR_EQ(initial_scroll_, scroll_layer->BaseScrollOffset());
PostSetNeedsRedrawToMainThread();
} else if (impl->active_tree()->source_frame_number() == 0 &&
impl->SourceAnimationFrameNumberForTesting() == 2) {
// Second draw after first commit.
EXPECT_EQ(scroll_layer->ScrollDelta(), scroll_amount_);
scroll_layer->ScrollBy(scroll_amount_);
- EXPECT_VECTOR_EQ(scroll_layer->ScrollDelta(),
- scroll_amount_ + scroll_amount_);
+ EXPECT_VECTOR_EQ(scroll_amount_ + scroll_amount_,
+ scroll_layer->ScrollDelta());
- EXPECT_VECTOR_EQ(scroll_layer_->scroll_offset(), initial_scroll_);
+ EXPECT_VECTOR_EQ(initial_scroll_, scroll_layer_->scroll_offset());
PostSetNeedsCommitToMainThread();
} else if (impl->active_tree()->source_frame_number() == 1) {
// Third or later draw after second commit.
EXPECT_GE(impl->SourceAnimationFrameNumberForTesting(), 3u);
- EXPECT_VECTOR_EQ(scroll_layer_->ScrollDelta(), gfx::Vector2d());
+ EXPECT_VECTOR_EQ(gfx::Vector2d(), scroll_layer_->ScrollDelta());
EXPECT_VECTOR_EQ(
- scroll_layer_->scroll_offset(),
gfx::ScrollOffsetWithDelta(initial_scroll_,
- scroll_amount_ + scroll_amount_));
+ scroll_amount_ + scroll_amount_),
+ scroll_layer_->scroll_offset());
EndTest();
}
}
@@ -221,34 +217,31 @@ class LayerTreeHostScrollTestScrollAbortedCommit
num_impl_commits_(0),
num_impl_scrolls_(0) {}
- void BeginTest() override { PostSetNeedsCommitToMainThread(); }
+ void BeginTest() override {
+ layer_tree_host()->outer_viewport_scroll_layer()->SetScrollOffset(
+ initial_scroll_);
+ PostSetNeedsCommitToMainThread();
+ }
void SetupTree() override {
LayerTreeHostScrollTest::SetupTree();
- Layer* root_layer = layer_tree_host()->root_layer();
- scoped_refptr<Layer> root_scroll_layer = Layer::Create(layer_settings());
- root_scroll_layer->SetScrollClipLayerId(root_layer->id());
- root_scroll_layer->SetScrollOffset(initial_scroll_);
- root_scroll_layer->SetBounds(gfx::Size(200, 200));
- root_scroll_layer->SetIsDrawable(true);
- root_scroll_layer->SetIsContainerForFixedPositionLayers(true);
- root_layer->AddChild(root_scroll_layer);
-
- layer_tree_host()->RegisterViewportLayers(NULL, root_layer,
- root_scroll_layer, NULL);
+
+ gfx::Size scroll_layer_bounds(200, 200);
+ layer_tree_host()->outer_viewport_scroll_layer()->SetBounds(
+ scroll_layer_bounds);
layer_tree_host()->SetPageScaleFactorAndLimits(1.f, 0.01f, 100.f);
}
void WillBeginMainFrame() override {
num_will_begin_main_frames_++;
Layer* root_scroll_layer =
- layer_tree_host()->root_layer()->children()[0].get();
+ layer_tree_host()->outer_viewport_scroll_layer();
switch (num_will_begin_main_frames_) {
case 1:
// This will not be aborted because of the initial prop changes.
EXPECT_EQ(0, num_impl_scrolls_);
EXPECT_EQ(0, layer_tree_host()->source_frame_number());
- EXPECT_VECTOR_EQ(root_scroll_layer->scroll_offset(), initial_scroll_);
+ EXPECT_VECTOR_EQ(initial_scroll_, root_scroll_layer->scroll_offset());
EXPECT_EQ(1.f, layer_tree_host()->page_scale_factor());
break;
case 2:
@@ -257,8 +250,8 @@ class LayerTreeHostScrollTestScrollAbortedCommit
EXPECT_EQ(1, num_impl_scrolls_);
EXPECT_EQ(1, layer_tree_host()->source_frame_number());
EXPECT_VECTOR_EQ(
- root_scroll_layer->scroll_offset(),
- gfx::ScrollOffsetWithDelta(initial_scroll_, impl_scroll_));
+ gfx::ScrollOffsetWithDelta(initial_scroll_, impl_scroll_),
+ root_scroll_layer->scroll_offset());
EXPECT_EQ(impl_scale_, layer_tree_host()->page_scale_factor());
PostSetNeedsRedrawToMainThread();
break;
@@ -268,9 +261,9 @@ class LayerTreeHostScrollTestScrollAbortedCommit
// The source frame number still increases even with the abort.
EXPECT_EQ(2, layer_tree_host()->source_frame_number());
EXPECT_VECTOR_EQ(
- root_scroll_layer->scroll_offset(),
gfx::ScrollOffsetWithDelta(initial_scroll_,
- impl_scroll_ + impl_scroll_));
+ impl_scroll_ + impl_scroll_),
+ root_scroll_layer->scroll_offset());
EXPECT_EQ(impl_scale_ * impl_scale_,
layer_tree_host()->page_scale_factor());
root_scroll_layer->SetScrollOffset(gfx::ScrollOffsetWithDelta(
@@ -282,8 +275,8 @@ class LayerTreeHostScrollTestScrollAbortedCommit
EXPECT_EQ(3, layer_tree_host()->source_frame_number());
gfx::Vector2dF delta =
impl_scroll_ + impl_scroll_ + impl_scroll_ + second_main_scroll_;
- EXPECT_VECTOR_EQ(root_scroll_layer->scroll_offset(),
- gfx::ScrollOffsetWithDelta(initial_scroll_, delta));
+ EXPECT_VECTOR_EQ(gfx::ScrollOffsetWithDelta(initial_scroll_, delta),
+ root_scroll_layer->scroll_offset());
// End the test by drawing to verify this commit is also aborted.
PostSetNeedsRedrawToMainThread();
@@ -302,20 +295,19 @@ class LayerTreeHostScrollTestScrollAbortedCommit
}
void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
- LayerImpl* root_scroll_layer =
- impl->active_tree()->root_layer()->children()[0];
+ LayerImpl* root_scroll_layer = impl->OuterViewportScrollLayer();
if (impl->active_tree()->source_frame_number() == 0 &&
impl->SourceAnimationFrameNumberForTesting() == 1) {
// First draw
- EXPECT_VECTOR_EQ(root_scroll_layer->ScrollDelta(), gfx::Vector2d());
+ EXPECT_VECTOR_EQ(gfx::Vector2d(), root_scroll_layer->ScrollDelta());
root_scroll_layer->ScrollBy(impl_scroll_);
- EXPECT_VECTOR_EQ(root_scroll_layer->ScrollDelta(), impl_scroll_);
- EXPECT_VECTOR_EQ(root_scroll_layer->BaseScrollOffset(), initial_scroll_);
+ EXPECT_VECTOR_EQ(impl_scroll_, root_scroll_layer->ScrollDelta());
+ EXPECT_VECTOR_EQ(initial_scroll_, root_scroll_layer->BaseScrollOffset());
EXPECT_EQ(1.f, impl->active_tree()->page_scale_delta());
EXPECT_EQ(1.f, impl->active_tree()->current_page_scale_factor());
- impl->SetPageScaleOnActiveTree(impl_scale_);
+ impl->active_tree()->SetPageScaleOnActiveTree(impl_scale_);
EXPECT_EQ(impl_scale_, impl->active_tree()->page_scale_delta());
EXPECT_EQ(impl_scale_, impl->active_tree()->current_page_scale_factor());
@@ -326,16 +318,16 @@ class LayerTreeHostScrollTestScrollAbortedCommit
// Test a second draw after an aborted commit.
// The scroll/scale values should be baked into the offset/scale factor
// since the main thread consumed but aborted the begin frame.
- EXPECT_VECTOR_EQ(root_scroll_layer->ScrollDelta(), gfx::Vector2d());
+ EXPECT_VECTOR_EQ(gfx::Vector2d(), root_scroll_layer->ScrollDelta());
root_scroll_layer->ScrollBy(impl_scroll_);
- EXPECT_VECTOR_EQ(root_scroll_layer->ScrollDelta(), impl_scroll_);
+ EXPECT_VECTOR_EQ(impl_scroll_, root_scroll_layer->ScrollDelta());
EXPECT_VECTOR_EQ(
- root_scroll_layer->BaseScrollOffset(),
- gfx::ScrollOffsetWithDelta(initial_scroll_, impl_scroll_));
+ gfx::ScrollOffsetWithDelta(initial_scroll_, impl_scroll_),
+ root_scroll_layer->BaseScrollOffset());
EXPECT_EQ(1.f, impl->active_tree()->page_scale_delta());
EXPECT_EQ(impl_scale_, impl->active_tree()->current_page_scale_factor());
- impl->SetPageScaleOnActiveTree(impl_scale_ * impl_scale_);
+ impl->active_tree()->SetPageScaleOnActiveTree(impl_scale_ * impl_scale_);
EXPECT_EQ(impl_scale_, impl->active_tree()->page_scale_delta());
EXPECT_EQ(impl_scale_ * impl_scale_,
impl->active_tree()->current_page_scale_factor());
@@ -350,18 +342,18 @@ class LayerTreeHostScrollTestScrollAbortedCommit
EXPECT_EQ(root_scroll_layer->ScrollDelta(), gfx::Vector2d());
root_scroll_layer->ScrollBy(impl_scroll_);
impl->SetNeedsCommit();
- EXPECT_VECTOR_EQ(root_scroll_layer->ScrollDelta(), impl_scroll_);
+ EXPECT_VECTOR_EQ(impl_scroll_, root_scroll_layer->ScrollDelta());
gfx::Vector2dF delta = impl_scroll_ + impl_scroll_ + second_main_scroll_;
- EXPECT_VECTOR_EQ(root_scroll_layer->BaseScrollOffset(),
- gfx::ScrollOffsetWithDelta(initial_scroll_, delta));
+ EXPECT_VECTOR_EQ(gfx::ScrollOffsetWithDelta(initial_scroll_, delta),
+ root_scroll_layer->BaseScrollOffset());
} else if (impl->active_tree()->source_frame_number() == 2 &&
impl->SourceAnimationFrameNumberForTesting() == 4) {
// Final draw after the second aborted commit.
- EXPECT_VECTOR_EQ(root_scroll_layer->ScrollDelta(), gfx::Vector2d());
+ EXPECT_VECTOR_EQ(gfx::Vector2d(), root_scroll_layer->ScrollDelta());
gfx::Vector2dF delta =
impl_scroll_ + impl_scroll_ + impl_scroll_ + second_main_scroll_;
- EXPECT_VECTOR_EQ(root_scroll_layer->BaseScrollOffset(),
- gfx::ScrollOffsetWithDelta(initial_scroll_, delta));
+ EXPECT_VECTOR_EQ(gfx::ScrollOffsetWithDelta(initial_scroll_, delta),
+ root_scroll_layer->BaseScrollOffset());
EndTest();
} else {
// Commit for source frame 3 is aborted.
@@ -409,49 +401,36 @@ class LayerTreeHostScrollTestFractionalScroll : public LayerTreeHostScrollTest {
void SetupTree() override {
LayerTreeHostScrollTest::SetupTree();
- Layer* root_layer = layer_tree_host()->root_layer();
- scoped_refptr<Layer> root_scroll_layer = Layer::Create(layer_settings());
- root_scroll_layer->SetScrollClipLayerId(root_layer->id());
- root_scroll_layer->SetBounds(
- gfx::Size(root_layer->bounds().width() + 100,
- root_layer->bounds().height() + 100));
- root_scroll_layer->SetIsDrawable(true);
- root_scroll_layer->SetIsContainerForFixedPositionLayers(true);
- root_layer->AddChild(root_scroll_layer);
-
- layer_tree_host()->RegisterViewportLayers(NULL, root_layer,
- root_scroll_layer, NULL);
layer_tree_host()->SetPageScaleFactorAndLimits(1.f, 0.01f, 100.f);
}
void BeginTest() override { PostSetNeedsCommitToMainThread(); }
void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
- LayerImpl* root = impl->active_tree()->root_layer();
- LayerImpl* scroll_layer = root->children()[0];
+ LayerImpl* scroll_layer = impl->OuterViewportScrollLayer();
// Check that a fractional scroll delta is correctly accumulated over
// multiple commits.
switch (impl->active_tree()->source_frame_number()) {
case 0:
- EXPECT_VECTOR_EQ(scroll_layer->BaseScrollOffset(), gfx::Vector2d(0, 0));
- EXPECT_VECTOR_EQ(scroll_layer->ScrollDelta(), gfx::Vector2d(0, 0));
+ EXPECT_VECTOR_EQ(gfx::Vector2d(0, 0), scroll_layer->BaseScrollOffset());
+ EXPECT_VECTOR_EQ(gfx::Vector2d(0, 0), scroll_layer->ScrollDelta());
PostSetNeedsCommitToMainThread();
break;
case 1:
- EXPECT_VECTOR_EQ(scroll_layer->BaseScrollOffset(),
- gfx::ToFlooredVector2d(scroll_amount_));
- EXPECT_VECTOR_EQ(scroll_layer->ScrollDelta(),
- gfx::Vector2dF(fmod(scroll_amount_.x(), 1.0f), 0.0f));
+ EXPECT_VECTOR_EQ(gfx::ToFlooredVector2d(scroll_amount_),
+ scroll_layer->BaseScrollOffset());
+ EXPECT_VECTOR_EQ(gfx::Vector2dF(fmod(scroll_amount_.x(), 1.0f), 0.0f),
+ scroll_layer->ScrollDelta());
PostSetNeedsCommitToMainThread();
break;
case 2:
EXPECT_VECTOR_EQ(
- scroll_layer->BaseScrollOffset(),
- gfx::ToFlooredVector2d(scroll_amount_ + scroll_amount_));
+ gfx::ToFlooredVector2d(scroll_amount_ + scroll_amount_),
+ scroll_layer->BaseScrollOffset());
EXPECT_VECTOR_EQ(
- scroll_layer->ScrollDelta(),
- gfx::Vector2dF(fmod(2.0f * scroll_amount_.x(), 1.0f), 0.0f));
+ gfx::Vector2dF(fmod(2.0f * scroll_amount_.x(), 1.0f), 0.0f),
+ scroll_layer->ScrollDelta());
EndTest();
break;
}
@@ -483,13 +462,16 @@ class LayerTreeHostScrollTestCaseWithChild : public LayerTreeHostScrollTest {
root_scroll_layer_ =
FakePictureLayer::Create(layer_settings(), &fake_content_layer_client_);
root_scroll_layer_->SetBounds(gfx::Size(110, 110));
-
root_scroll_layer_->SetPosition(gfx::Point());
-
root_scroll_layer_->SetIsDrawable(true);
- root_scroll_layer_->SetScrollClipLayerId(root_layer->id());
- root_scroll_layer_->SetIsContainerForFixedPositionLayers(true);
- root_layer->AddChild(root_scroll_layer_);
+
+ CreateVirtualViewportLayers(root_layer.get(),
+ root_scroll_layer_,
+ root_layer->bounds(),
+ root_layer->bounds(),
+ layer_tree_host(),
+ layer_settings());
+
child_layer_ =
FakePictureLayer::Create(layer_settings(), &fake_content_layer_client_);
@@ -508,8 +490,11 @@ class LayerTreeHostScrollTestCaseWithChild : public LayerTreeHostScrollTest {
child_layer_->SetPosition(gfx::Point(60, 5));
}
+ scoped_refptr<Layer> outer_container_layer =
+ layer_tree_host()->outer_viewport_scroll_layer()->parent();
+
child_layer_->SetIsDrawable(true);
- child_layer_->SetScrollClipLayerId(root_layer->id());
+ child_layer_->SetScrollClipLayerId(outer_container_layer->id());
child_layer_->SetBounds(root_scroll_layer_->bounds());
root_scroll_layer_->AddChild(child_layer_);
@@ -524,9 +509,7 @@ class LayerTreeHostScrollTestCaseWithChild : public LayerTreeHostScrollTest {
expected_scroll_layer_->SetScrollOffset(initial_offset_);
layer_tree_host()->SetRootLayer(root_layer);
- layer_tree_host()->RegisterViewportLayers(NULL, root_layer,
- root_scroll_layer_, NULL);
- LayerTreeHostScrollTest::SetupTree();
+ LayerTreeTest::SetupTree();
}
void BeginTest() override { PostSetNeedsCommitToMainThread(); }
@@ -577,9 +560,9 @@ class LayerTreeHostScrollTestCaseWithChild : public LayerTreeHostScrollTest {
}
void DidActivateTreeOnThread(LayerTreeHostImpl* impl) override {
- LayerImpl* root_impl = impl->active_tree()->root_layer();
+ LayerImpl* inner_scroll = impl->InnerViewportScrollLayer();
FakePictureLayerImpl* root_scroll_layer_impl =
- static_cast<FakePictureLayerImpl*>(root_impl->children()[0]);
+ static_cast<FakePictureLayerImpl*>(impl->OuterViewportScrollLayer());
FakePictureLayerImpl* child_layer_impl = static_cast<FakePictureLayerImpl*>(
root_scroll_layer_impl->children()[0]);
@@ -593,7 +576,7 @@ class LayerTreeHostScrollTestCaseWithChild : public LayerTreeHostScrollTest {
expected_no_scroll_layer_impl = child_layer_impl;
}
- EXPECT_VECTOR_EQ(gfx::Vector2d(), root_impl->ScrollDelta());
+ EXPECT_VECTOR_EQ(gfx::Vector2d(), inner_scroll->ScrollDelta());
EXPECT_VECTOR_EQ(gfx::Vector2d(),
expected_no_scroll_layer_impl->ScrollDelta());
@@ -772,29 +755,19 @@ class LayerTreeHostScrollTestSimple : public LayerTreeHostScrollTest {
void SetupTree() override {
LayerTreeHostScrollTest::SetupTree();
- Layer* root_layer = layer_tree_host()->root_layer();
- scoped_refptr<Layer> root_scroll_layer = Layer::Create(layer_settings());
- root_scroll_layer->SetScrollClipLayerId(root_layer->id());
- root_scroll_layer->SetScrollOffset(initial_scroll_);
- root_scroll_layer->SetBounds(
- gfx::Size(root_layer->bounds().width() + 100,
- root_layer->bounds().height() + 100));
- root_scroll_layer->SetIsDrawable(true);
- root_scroll_layer->SetIsContainerForFixedPositionLayers(true);
- root_layer->AddChild(root_scroll_layer);
-
- layer_tree_host()->RegisterViewportLayers(NULL, root_layer,
- root_scroll_layer, NULL);
layer_tree_host()->SetPageScaleFactorAndLimits(1.f, 0.01f, 100.f);
}
- void BeginTest() override { PostSetNeedsCommitToMainThread(); }
+ void BeginTest() override {
+ layer_tree_host()->outer_viewport_scroll_layer()->SetScrollOffset(
+ initial_scroll_);
+ PostSetNeedsCommitToMainThread();
+ }
void Layout() override {
- Layer* root = layer_tree_host()->root_layer();
- Layer* scroll_layer = root->children()[0].get();
+ Layer* scroll_layer = layer_tree_host()->outer_viewport_scroll_layer();
if (!layer_tree_host()->source_frame_number()) {
- EXPECT_VECTOR_EQ(scroll_layer->scroll_offset(), initial_scroll_);
+ EXPECT_VECTOR_EQ(initial_scroll_, scroll_layer->scroll_offset());
} else {
EXPECT_VECTOR_EQ(
scroll_layer->scroll_offset(),
@@ -820,7 +793,7 @@ class LayerTreeHostScrollTestSimple : public LayerTreeHostScrollTest {
impl->SetNeedsRedraw();
LayerImpl* root = impl->active_tree()->root_layer();
- LayerImpl* scroll_layer = root->children()[0];
+ LayerImpl* scroll_layer = impl->OuterViewportScrollLayer();
LayerImpl* pending_root =
impl->active_tree()->FindPendingTreeLayerById(root->id());
@@ -828,11 +801,11 @@ class LayerTreeHostScrollTestSimple : public LayerTreeHostScrollTest {
case 0:
if (!impl->pending_tree()) {
impl->BlockNotifyReadyToActivateForTesting(true);
- EXPECT_VECTOR_EQ(scroll_layer->ScrollDelta(), gfx::Vector2d());
+ EXPECT_VECTOR_EQ(gfx::Vector2d(), scroll_layer->ScrollDelta());
scroll_layer->ScrollBy(impl_thread_scroll1_);
- EXPECT_VECTOR_EQ(scroll_layer->BaseScrollOffset(), initial_scroll_);
- EXPECT_VECTOR_EQ(scroll_layer->ScrollDelta(), impl_thread_scroll1_);
+ EXPECT_VECTOR_EQ(initial_scroll_, scroll_layer->BaseScrollOffset());
+ EXPECT_VECTOR_EQ(impl_thread_scroll1_, scroll_layer->ScrollDelta());
PostSetNeedsCommitToMainThread();
// CommitCompleteOnThread will trigger this function again
@@ -843,26 +816,27 @@ class LayerTreeHostScrollTestSimple : public LayerTreeHostScrollTest {
EXPECT_EQ(impl->pending_tree()->source_frame_number(), 1);
scroll_layer->ScrollBy(impl_thread_scroll2_);
- EXPECT_VECTOR_EQ(scroll_layer->BaseScrollOffset(), initial_scroll_);
- EXPECT_VECTOR_EQ(scroll_layer->ScrollDelta(),
- impl_thread_scroll1_ + impl_thread_scroll2_);
+ EXPECT_VECTOR_EQ(initial_scroll_, scroll_layer->BaseScrollOffset());
+ EXPECT_VECTOR_EQ(impl_thread_scroll1_ + impl_thread_scroll2_,
+ scroll_layer->ScrollDelta());
- LayerImpl* pending_scroll_layer = pending_root->children()[0];
+ LayerImpl* pending_scroll_layer =
+ impl->pending_tree()->OuterViewportScrollLayer();
EXPECT_VECTOR_EQ(
- pending_scroll_layer->BaseScrollOffset(),
gfx::ScrollOffsetWithDelta(
- initial_scroll_, main_thread_scroll_ + impl_thread_scroll1_));
- EXPECT_VECTOR_EQ(pending_scroll_layer->ScrollDelta(),
- impl_thread_scroll2_);
+ initial_scroll_, main_thread_scroll_ + impl_thread_scroll1_),
+ pending_scroll_layer->BaseScrollOffset());
+ EXPECT_VECTOR_EQ(impl_thread_scroll2_,
+ pending_scroll_layer->ScrollDelta());
}
break;
case 1:
EXPECT_FALSE(impl->pending_tree());
EXPECT_VECTOR_EQ(
- scroll_layer->BaseScrollOffset(),
gfx::ScrollOffsetWithDelta(
- initial_scroll_, main_thread_scroll_ + impl_thread_scroll1_));
- EXPECT_VECTOR_EQ(scroll_layer->ScrollDelta(), impl_thread_scroll2_);
+ initial_scroll_, main_thread_scroll_ + impl_thread_scroll1_),
+ scroll_layer->BaseScrollOffset());
+ EXPECT_VECTOR_EQ(impl_thread_scroll2_, scroll_layer->ScrollDelta());
EndTest();
break;
}
@@ -900,27 +874,17 @@ class LayerTreeHostScrollTestImplOnlyScroll : public LayerTreeHostScrollTest {
void SetupTree() override {
LayerTreeHostScrollTest::SetupTree();
- Layer* root_layer = layer_tree_host()->root_layer();
- scoped_refptr<Layer> root_scroll_layer = Layer::Create(layer_settings());
- root_scroll_layer->SetScrollClipLayerId(root_layer->id());
- root_scroll_layer->SetScrollOffset(initial_scroll_);
- root_scroll_layer->SetBounds(
- gfx::Size(root_layer->bounds().width() + 100,
- root_layer->bounds().height() + 100));
- root_scroll_layer->SetIsDrawable(true);
- root_scroll_layer->SetIsContainerForFixedPositionLayers(true);
- root_layer->AddChild(root_scroll_layer);
-
- layer_tree_host()->RegisterViewportLayers(NULL, root_layer,
- root_scroll_layer, NULL);
layer_tree_host()->SetPageScaleFactorAndLimits(1.f, 0.01f, 100.f);
}
- void BeginTest() override { PostSetNeedsCommitToMainThread(); }
+ void BeginTest() override {
+ layer_tree_host()->outer_viewport_scroll_layer()->SetScrollOffset(
+ initial_scroll_);
+ PostSetNeedsCommitToMainThread();
+ }
void WillCommit() override {
- Layer* root = layer_tree_host()->root_layer();
- Layer* scroll_layer = root->children()[0].get();
+ Layer* scroll_layer = layer_tree_host()->outer_viewport_scroll_layer();
switch (layer_tree_host()->source_frame_number()) {
case 0:
EXPECT_TRUE(scroll_layer->needs_push_properties());
@@ -938,11 +902,11 @@ class LayerTreeHostScrollTestImplOnlyScroll : public LayerTreeHostScrollTest {
// Scroll after the 2nd commit has started.
if (impl->active_tree()->source_frame_number() == 0) {
LayerImpl* active_root = impl->active_tree()->root_layer();
- LayerImpl* active_scroll_layer = active_root->children()[0];
+ LayerImpl* active_scroll_layer = impl->OuterViewportScrollLayer();
ASSERT_TRUE(active_root);
ASSERT_TRUE(active_scroll_layer);
active_scroll_layer->ScrollBy(impl_thread_scroll_);
- impl->SetPageScaleOnActiveTree(impl_scale_);
+ impl->active_tree()->SetPageScaleOnActiveTree(impl_scale_);
}
}
@@ -951,38 +915,39 @@ class LayerTreeHostScrollTestImplOnlyScroll : public LayerTreeHostScrollTest {
// the second commit.
LayerImpl* active_root = impl->active_tree()->root_layer();
LayerImpl* active_scroll_layer =
- active_root ? active_root->children()[0] : NULL;
+ active_root ? impl->OuterViewportScrollLayer() : NULL;
LayerImpl* pending_root = impl->pending_tree()->root_layer();
- LayerImpl* pending_scroll_layer = pending_root->children()[0];
+ LayerImpl* pending_scroll_layer =
+ impl->pending_tree()->OuterViewportScrollLayer();
ASSERT_TRUE(pending_root);
ASSERT_TRUE(pending_scroll_layer);
switch (impl->pending_tree()->source_frame_number()) {
case 0:
- EXPECT_VECTOR_EQ(pending_scroll_layer->BaseScrollOffset(),
- initial_scroll_);
- EXPECT_VECTOR_EQ(pending_scroll_layer->ScrollDelta(), gfx::Vector2d());
+ EXPECT_VECTOR_EQ(initial_scroll_,
+ pending_scroll_layer->BaseScrollOffset());
+ EXPECT_VECTOR_EQ(gfx::Vector2d(), pending_scroll_layer->ScrollDelta());
EXPECT_FALSE(active_root);
break;
case 1:
// Even though the scroll happened during the commit, both layers
// should have the appropriate scroll delta.
- EXPECT_VECTOR_EQ(pending_scroll_layer->BaseScrollOffset(),
- initial_scroll_);
- EXPECT_VECTOR_EQ(pending_scroll_layer->ScrollDelta(),
- impl_thread_scroll_);
+ EXPECT_VECTOR_EQ(initial_scroll_,
+ pending_scroll_layer->BaseScrollOffset());
+ EXPECT_VECTOR_EQ(impl_thread_scroll_,
+ pending_scroll_layer->ScrollDelta());
ASSERT_TRUE(active_root);
- EXPECT_VECTOR_EQ(active_scroll_layer->BaseScrollOffset(),
- initial_scroll_);
- EXPECT_VECTOR_EQ(active_scroll_layer->ScrollDelta(),
- impl_thread_scroll_);
+ EXPECT_VECTOR_EQ(initial_scroll_,
+ active_scroll_layer->BaseScrollOffset());
+ EXPECT_VECTOR_EQ(impl_thread_scroll_,
+ active_scroll_layer->ScrollDelta());
break;
case 2:
// On the next commit, this delta should have been sent and applied.
EXPECT_VECTOR_EQ(
- pending_scroll_layer->BaseScrollOffset(),
- gfx::ScrollOffsetWithDelta(initial_scroll_, impl_thread_scroll_));
- EXPECT_VECTOR_EQ(pending_scroll_layer->ScrollDelta(), gfx::Vector2d());
+ gfx::ScrollOffsetWithDelta(initial_scroll_, impl_thread_scroll_),
+ pending_scroll_layer->BaseScrollOffset());
+ EXPECT_VECTOR_EQ(gfx::Vector2d(), pending_scroll_layer->ScrollDelta());
break;
}
}
@@ -991,20 +956,19 @@ class LayerTreeHostScrollTestImplOnlyScroll : public LayerTreeHostScrollTest {
if (impl->pending_tree())
impl->SetNeedsRedraw();
- LayerImpl* root = impl->active_tree()->root_layer();
- LayerImpl* scroll_layer = root->children()[0];
+ LayerImpl* scroll_layer = impl->OuterViewportScrollLayer();
switch (impl->active_tree()->source_frame_number()) {
case 0:
- EXPECT_VECTOR_EQ(scroll_layer->BaseScrollOffset(), initial_scroll_);
- EXPECT_VECTOR_EQ(scroll_layer->ScrollDelta(), gfx::Vector2d());
+ EXPECT_VECTOR_EQ(initial_scroll_, scroll_layer->BaseScrollOffset());
+ EXPECT_VECTOR_EQ(gfx::Vector2d(), scroll_layer->ScrollDelta());
EXPECT_EQ(1.f, impl->active_tree()->page_scale_delta());
EXPECT_EQ(1.f, impl->active_tree()->current_page_scale_factor());
PostSetNeedsCommitToMainThread();
break;
case 1:
- EXPECT_VECTOR_EQ(scroll_layer->BaseScrollOffset(), initial_scroll_);
- EXPECT_VECTOR_EQ(scroll_layer->ScrollDelta(), impl_thread_scroll_);
+ EXPECT_VECTOR_EQ(initial_scroll_, scroll_layer->BaseScrollOffset());
+ EXPECT_VECTOR_EQ(impl_thread_scroll_, scroll_layer->ScrollDelta());
EXPECT_EQ(impl_scale_, impl->active_tree()->page_scale_delta());
EXPECT_EQ(impl_scale_,
impl->active_tree()->current_page_scale_factor());
@@ -1035,17 +999,11 @@ class LayerTreeHostScrollTestScrollZeroMaxScrollOffset
public:
LayerTreeHostScrollTestScrollZeroMaxScrollOffset() {}
- void SetupTree() override {
- LayerTreeTest::SetupTree();
- scoped_refptr<Layer> scroll_layer = Layer::Create(layer_settings());
- layer_tree_host()->root_layer()->AddChild(scroll_layer);
- }
-
void BeginTest() override { PostSetNeedsCommitToMainThread(); }
void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
LayerImpl* root = impl->active_tree()->root_layer();
- LayerImpl* scroll_layer = root->children()[0];
+ LayerImpl* scroll_layer = impl->OuterViewportScrollLayer();
scroll_layer->SetScrollClipLayer(root->id());
// Set max_scroll_offset = (100, 100).
@@ -1108,6 +1066,19 @@ class ThreadCheckingInputHandlerClient : public InputHandlerClient {
}
}
+ void UpdateRootLayerStateForSynchronousInputHandler(
+ const gfx::ScrollOffset& total_scroll_offset,
+ const gfx::ScrollOffset& max_scroll_offset,
+ const gfx::SizeF& scrollable_size,
+ float page_scale_factor,
+ float min_page_scale_factor,
+ float max_page_scale_factor) override {
+ if (!task_runner_->BelongsToCurrentThread()) {
+ ADD_FAILURE() << "UpdateRootLayerStateForSynchronousInputHandler called "
+ << " on wrong thread";
+ }
+ }
+
private:
base::SingleThreadTaskRunner* task_runner_;
bool* received_stop_flinging_;
@@ -1161,22 +1132,30 @@ class LayerTreeHostScrollTestLayerStructureChange
: scroll_destroy_whole_tree_(false) {}
void SetupTree() override {
- scoped_refptr<Layer> root_layer = Layer::Create(layer_settings());
+ LayerTreeTest::SetupTree();
+ Layer* root_layer = layer_tree_host()->root_layer();
root_layer->SetBounds(gfx::Size(10, 10));
+ CreateVirtualViewportLayers(root_layer,
+ root_layer->bounds(),
+ root_layer->bounds(),
+ root_layer->bounds(),
+ layer_tree_host(),
+ layer_settings());
+
+ Layer* outer_scroll_layer =
+ layer_tree_host()->outer_viewport_scroll_layer();
+
Layer* root_scroll_layer =
- CreateScrollLayer(root_layer.get(), &root_scroll_layer_client_);
- CreateScrollLayer(root_layer.get(), &sibling_scroll_layer_client_);
+ CreateScrollLayer(outer_scroll_layer, &root_scroll_layer_client_);
+ CreateScrollLayer(outer_scroll_layer, &sibling_scroll_layer_client_);
CreateScrollLayer(root_scroll_layer, &child_scroll_layer_client_);
-
- layer_tree_host()->SetRootLayer(root_layer);
- LayerTreeHostScrollTest::SetupTree();
}
void BeginTest() override { PostSetNeedsCommitToMainThread(); }
void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
- LayerImpl* root = impl->active_tree()->root_layer();
+ LayerImpl* root = impl->OuterViewportScrollLayer();
switch (impl->active_tree()->source_frame_number()) {
case 0:
root->child_at(0)->SetScrollDelta(gfx::Vector2dF(5, 5));
@@ -1194,6 +1173,7 @@ class LayerTreeHostScrollTestLayerStructureChange
virtual void DidScroll(Layer* layer) {
if (scroll_destroy_whole_tree_) {
+ layer_tree_host()->RegisterViewportLayers(NULL, NULL, NULL, NULL);
layer_tree_host()->SetRootLayer(NULL);
EndTest();
return;
diff --git a/chromium/cc/trees/layer_tree_host_unittest_video.cc b/chromium/cc/trees/layer_tree_host_unittest_video.cc
index 31854ac68a9..2ae61bda512 100644
--- a/chromium/cc/trees/layer_tree_host_unittest_video.cc
+++ b/chromium/cc/trees/layer_tree_host_unittest_video.cc
@@ -49,19 +49,17 @@ class LayerTreeHostVideoTestSetNeedsDisplay
DrawResult draw_result) override {
LayerImpl* root_layer = host_impl->active_tree()->root_layer();
RenderSurfaceImpl* root_surface = root_layer->render_surface();
- gfx::RectF damage_rect =
+ gfx::Rect damage_rect =
root_surface->damage_tracker()->current_damage_rect();
switch (num_draws_) {
case 0:
// First frame the whole viewport is damaged.
- EXPECT_EQ(gfx::RectF(0.f, 0.f, 20.f, 20.f).ToString(),
- damage_rect.ToString());
+ EXPECT_EQ(gfx::Rect(0, 0, 20, 20), damage_rect);
break;
case 1:
// Second frame the video layer is damaged.
- EXPECT_EQ(gfx::RectF(6.f, 6.f, 8.f, 10.f).ToString(),
- damage_rect.ToString());
+ EXPECT_EQ(gfx::Rect(6, 6, 8, 10), damage_rect);
EndTest();
break;
}
diff --git a/chromium/cc/trees/layer_tree_impl.cc b/chromium/cc/trees/layer_tree_impl.cc
index d4d2dee7f23..7cf7ddbce64 100644
--- a/chromium/cc/trees/layer_tree_impl.cc
+++ b/chromium/cc/trees/layer_tree_impl.cc
@@ -19,7 +19,6 @@
#include "cc/base/synced_property.h"
#include "cc/debug/devtools_instrumentation.h"
#include "cc/debug/traced_value.h"
-#include "cc/input/layer_scroll_offset_delegate.h"
#include "cc/input/page_scale_animation.h"
#include "cc/layers/heads_up_display_layer_impl.h"
#include "cc/layers/layer.h"
@@ -47,19 +46,19 @@ LayerTreeImpl::LayerTreeImpl(
: layer_tree_host_impl_(layer_tree_host_impl),
source_frame_number_(-1),
hud_layer_(0),
- currently_scrolling_layer_(NULL),
- root_layer_scroll_offset_delegate_(NULL),
background_color_(0),
has_transparent_background_(false),
- overscroll_elasticity_layer_(NULL),
- page_scale_layer_(NULL),
- inner_viewport_scroll_layer_(NULL),
- outer_viewport_scroll_layer_(NULL),
+ currently_scrolling_layer_id_(Layer::INVALID_ID),
+ overscroll_elasticity_layer_id_(Layer::INVALID_ID),
+ page_scale_layer_id_(Layer::INVALID_ID),
+ inner_viewport_scroll_layer_id_(Layer::INVALID_ID),
+ outer_viewport_scroll_layer_id_(Layer::INVALID_ID),
page_scale_factor_(page_scale_factor),
min_page_scale_factor_(0),
max_page_scale_factor_(0),
+ hide_pinch_scrollbars_near_min_scale_(false),
+ device_scale_factor_(1.f),
elastic_overscroll_(elastic_overscroll),
- scrolling_layer_id_from_previous_tree_(0),
viewport_size_invalid_(false),
needs_update_draw_properties_(true),
needs_full_tree_sync_(true),
@@ -68,8 +67,7 @@ LayerTreeImpl::LayerTreeImpl(
render_surface_layer_list_id_(0),
top_controls_shrink_blink_size_(false),
top_controls_height_(0),
- top_controls_shown_ratio_(top_controls_shown_ratio) {
-}
+ top_controls_shown_ratio_(top_controls_shown_ratio) {}
LayerTreeImpl::~LayerTreeImpl() {
BreakSwapPromises(IsActiveTree() ? SwapPromise::SWAP_FAILS
@@ -114,53 +112,28 @@ void LayerTreeImpl::GatherFrameTimingRequestIds(
});
}
-bool LayerTreeImpl::IsExternalScrollActive() const {
- return root_layer_scroll_offset_delegate_ &&
- root_layer_scroll_offset_delegate_->IsExternalScrollActive();
-}
-
-void LayerTreeImpl::DidUpdateScrollOffset(int layer_id) {
- int inner_layer_id = InnerViewportScrollLayer()
- ? InnerViewportScrollLayer()->id()
- : Layer::INVALID_ID;
- int outer_layer_id = OuterViewportScrollLayer()
- ? OuterViewportScrollLayer()->id()
- : Layer::INVALID_ID;
- if (layer_id != outer_layer_id && layer_id != inner_layer_id)
- return;
-
- if (!root_layer_scroll_offset_delegate_)
- return;
-
- UpdateRootScrollOffsetDelegate();
-}
-
void LayerTreeImpl::SetRootLayer(scoped_ptr<LayerImpl> layer) {
root_layer_ = layer.Pass();
- currently_scrolling_layer_ = NULL;
- inner_viewport_scroll_layer_ = NULL;
- outer_viewport_scroll_layer_ = NULL;
- page_scale_layer_ = NULL;
layer_tree_host_impl_->OnCanDrawStateChangedForTree();
}
LayerImpl* LayerTreeImpl::InnerViewportScrollLayer() const {
- return inner_viewport_scroll_layer_;
+ return LayerById(inner_viewport_scroll_layer_id_);
}
LayerImpl* LayerTreeImpl::OuterViewportScrollLayer() const {
- return outer_viewport_scroll_layer_;
+ return LayerById(outer_viewport_scroll_layer_id_);
}
gfx::ScrollOffset LayerTreeImpl::TotalScrollOffset() const {
gfx::ScrollOffset offset;
- if (inner_viewport_scroll_layer_)
- offset += inner_viewport_scroll_layer_->CurrentScrollOffset();
+ if (InnerViewportScrollLayer())
+ offset += InnerViewportScrollLayer()->CurrentScrollOffset();
- if (outer_viewport_scroll_layer_)
- offset += outer_viewport_scroll_layer_->CurrentScrollOffset();
+ if (OuterViewportScrollLayer())
+ offset += OuterViewportScrollLayer()->CurrentScrollOffset();
return offset;
}
@@ -168,24 +141,16 @@ gfx::ScrollOffset LayerTreeImpl::TotalScrollOffset() const {
gfx::ScrollOffset LayerTreeImpl::TotalMaxScrollOffset() const {
gfx::ScrollOffset offset;
- if (inner_viewport_scroll_layer_)
- offset += inner_viewport_scroll_layer_->MaxScrollOffset();
+ if (InnerViewportScrollLayer())
+ offset += InnerViewportScrollLayer()->MaxScrollOffset();
- if (outer_viewport_scroll_layer_)
- offset += outer_viewport_scroll_layer_->MaxScrollOffset();
+ if (OuterViewportScrollLayer())
+ offset += OuterViewportScrollLayer()->MaxScrollOffset();
return offset;
}
scoped_ptr<LayerImpl> LayerTreeImpl::DetachLayerTree() {
- // Clear all data structures that have direct references to the layer tree.
- scrolling_layer_id_from_previous_tree_ =
- currently_scrolling_layer_ ? currently_scrolling_layer_->id() : 0;
- inner_viewport_scroll_layer_ = NULL;
- outer_viewport_scroll_layer_ = NULL;
- page_scale_layer_ = NULL;
- currently_scrolling_layer_ = NULL;
-
render_surface_layer_list_.clear();
set_needs_update_draw_properties();
return root_layer_.Pass();
@@ -197,7 +162,7 @@ static void UpdateClipTreeForBoundsDeltaOnLayer(LayerImpl* layer,
ClipNode* clip_node = clip_tree->Node(layer->clip_tree_index());
if (clip_node) {
DCHECK_EQ(layer->id(), clip_node->owner_id);
- gfx::Size bounds = layer->bounds();
+ gfx::SizeF bounds = gfx::SizeF(layer->bounds());
if (clip_node->data.clip.size() != bounds) {
clip_node->data.clip.set_size(bounds);
clip_tree->set_needs_update(true);
@@ -243,25 +208,22 @@ void LayerTreeImpl::PushPropertiesTo(LayerTreeImpl* target_tree) {
target_tree->set_top_controls_height(top_controls_height_);
target_tree->PushTopControls(nullptr);
+ target_tree->set_hide_pinch_scrollbars_near_min_scale(
+ hide_pinch_scrollbars_near_min_scale_);
+
// Active tree already shares the page_scale_factor object with pending
// tree so only the limits need to be provided.
target_tree->PushPageScaleFactorAndLimits(nullptr, min_page_scale_factor(),
max_page_scale_factor());
+ target_tree->SetDeviceScaleFactor(device_scale_factor());
target_tree->elastic_overscroll()->PushPendingToActive();
target_tree->pending_page_scale_animation_ =
pending_page_scale_animation_.Pass();
- if (page_scale_layer_ && inner_viewport_scroll_layer_) {
- target_tree->SetViewportLayersFromIds(
- overscroll_elasticity_layer_ ? overscroll_elasticity_layer_->id()
- : Layer::INVALID_ID,
- page_scale_layer_->id(), inner_viewport_scroll_layer_->id(),
- outer_viewport_scroll_layer_ ? outer_viewport_scroll_layer_->id()
- : Layer::INVALID_ID);
- } else {
- target_tree->ClearViewportLayers();
- }
+ target_tree->SetViewportLayersFromIds(
+ overscroll_elasticity_layer_id_, page_scale_layer_id_,
+ inner_viewport_scroll_layer_id_, outer_viewport_scroll_layer_id_);
target_tree->RegisterSelection(selection_);
@@ -287,38 +249,39 @@ void LayerTreeImpl::PushPropertiesTo(LayerTreeImpl* target_tree) {
}
LayerImpl* LayerTreeImpl::InnerViewportContainerLayer() const {
- return inner_viewport_scroll_layer_
- ? inner_viewport_scroll_layer_->scroll_clip_layer()
+ return InnerViewportScrollLayer()
+ ? InnerViewportScrollLayer()->scroll_clip_layer()
: NULL;
}
LayerImpl* LayerTreeImpl::OuterViewportContainerLayer() const {
- return outer_viewport_scroll_layer_
- ? outer_viewport_scroll_layer_->scroll_clip_layer()
+ return OuterViewportScrollLayer()
+ ? OuterViewportScrollLayer()->scroll_clip_layer()
: NULL;
}
LayerImpl* LayerTreeImpl::CurrentlyScrollingLayer() const {
DCHECK(IsActiveTree());
- return currently_scrolling_layer_;
+ return LayerById(currently_scrolling_layer_id_);
}
void LayerTreeImpl::SetCurrentlyScrollingLayer(LayerImpl* layer) {
- if (currently_scrolling_layer_ == layer)
+ DCHECK_IMPLIES(layer, layer != OuterViewportScrollLayer());
+
+ int new_id = layer ? layer->id() : Layer::INVALID_ID;
+ if (currently_scrolling_layer_id_ == new_id)
return;
- if (currently_scrolling_layer_ &&
- currently_scrolling_layer_->scrollbar_animation_controller())
- currently_scrolling_layer_->scrollbar_animation_controller()
- ->DidScrollEnd();
- currently_scrolling_layer_ = layer;
+ if (CurrentlyScrollingLayer() &&
+ CurrentlyScrollingLayer()->scrollbar_animation_controller())
+ CurrentlyScrollingLayer()->scrollbar_animation_controller()->DidScrollEnd();
+ currently_scrolling_layer_id_ = new_id;
if (layer && layer->scrollbar_animation_controller())
layer->scrollbar_animation_controller()->DidScrollBegin();
}
void LayerTreeImpl::ClearCurrentlyScrollingLayer() {
SetCurrentlyScrollingLayer(NULL);
- scrolling_layer_id_from_previous_tree_ = 0;
}
namespace {
@@ -463,34 +426,35 @@ void LayerTreeImpl::DidUpdatePageScale() {
set_needs_update_draw_properties();
- if (root_layer_scroll_offset_delegate_) {
- root_layer_scroll_offset_delegate_->UpdateRootLayerState(
- TotalScrollOffset(), TotalMaxScrollOffset(), ScrollableSize(),
- current_page_scale_factor(), min_page_scale_factor_,
- max_page_scale_factor_);
- }
-
- if (page_scale_layer() && page_scale_layer()->transform_tree_index() != -1) {
+ if (PageScaleLayer() && PageScaleLayer()->transform_tree_index() != -1) {
TransformNode* node = property_trees_.transform_tree.Node(
- page_scale_layer()->transform_tree_index());
+ PageScaleLayer()->transform_tree_index());
node->data.post_local_scale_factor = current_page_scale_factor();
node->data.needs_local_transform_update = true;
// TODO(enne): property trees can't ask the layer these things, but
// the page scale layer should *just* be the page scale.
- DCHECK_EQ(page_scale_layer()->position().ToString(),
+ DCHECK_EQ(PageScaleLayer()->position().ToString(),
gfx::PointF().ToString());
- DCHECK_EQ(page_scale_layer()->transform_origin().ToString(),
+ DCHECK_EQ(PageScaleLayer()->transform_origin().ToString(),
gfx::Point3F().ToString());
node->data.update_post_local_transform(gfx::PointF(), gfx::Point3F());
property_trees_.transform_tree.set_needs_update(true);
}
- ForceScrollbarParameterUpdateAfterScaleChange(page_scale_layer());
+ ForceScrollbarParameterUpdateAfterScaleChange(PageScaleLayer());
+ HideInnerViewportScrollbarsIfNeeded();
+}
+
+void LayerTreeImpl::SetDeviceScaleFactor(float device_scale_factor) {
+ if (device_scale_factor == device_scale_factor_)
+ return;
+ device_scale_factor_ = device_scale_factor;
- HideInnerViewportScrollbarsIfNearMinimumScale();
+ if (IsActiveTree())
+ layer_tree_host_impl_->SetFullRootLayerDamage();
}
-void LayerTreeImpl::HideInnerViewportScrollbarsIfNearMinimumScale() {
+void LayerTreeImpl::HideInnerViewportScrollbarsIfNeeded() {
if (!InnerViewportContainerLayer())
return;
@@ -500,15 +464,14 @@ void LayerTreeImpl::HideInnerViewportScrollbarsIfNearMinimumScale() {
if (!scrollbars)
return;
+ float minimum_scale_to_show_at = min_page_scale_factor() * 1.05f;
+ bool hide_scrollbars =
+ hide_pinch_scrollbars_near_min_scale_ &&
+ (current_page_scale_factor() < minimum_scale_to_show_at);
+
for (LayerImpl::ScrollbarSet::iterator it = scrollbars->begin();
- it != scrollbars->end();
- ++it) {
- ScrollbarLayerImplBase* scrollbar = *it;
- float minimum_scale_to_show_at =
- min_page_scale_factor() * settings().scrollbar_show_scale_threshold;
- scrollbar->SetHideLayerAndSubtree(
- current_page_scale_factor() < minimum_scale_to_show_at);
- }
+ it != scrollbars->end(); ++it)
+ (*it)->SetHideLayerAndSubtree(hide_scrollbars);
}
SyncedProperty<ScaleGroup>* LayerTreeImpl::page_scale_factor() {
@@ -559,29 +522,39 @@ void LayerTreeImpl::SetViewportLayersFromIds(
int page_scale_layer_id,
int inner_viewport_scroll_layer_id,
int outer_viewport_scroll_layer_id) {
- overscroll_elasticity_layer_ = LayerById(overscroll_elasticity_layer_id);
- page_scale_layer_ = LayerById(page_scale_layer_id);
- DCHECK(page_scale_layer_);
+ overscroll_elasticity_layer_id_ = overscroll_elasticity_layer_id;
+ page_scale_layer_id_ = page_scale_layer_id;
+ inner_viewport_scroll_layer_id_ = inner_viewport_scroll_layer_id;
+ outer_viewport_scroll_layer_id_ = outer_viewport_scroll_layer_id;
- inner_viewport_scroll_layer_ =
- LayerById(inner_viewport_scroll_layer_id);
- DCHECK(inner_viewport_scroll_layer_);
-
- outer_viewport_scroll_layer_ =
- LayerById(outer_viewport_scroll_layer_id);
- DCHECK(outer_viewport_scroll_layer_ ||
- outer_viewport_scroll_layer_id == Layer::INVALID_ID);
-
- HideInnerViewportScrollbarsIfNearMinimumScale();
+ HideInnerViewportScrollbarsIfNeeded();
}
void LayerTreeImpl::ClearViewportLayers() {
- page_scale_layer_ = NULL;
- inner_viewport_scroll_layer_ = NULL;
- outer_viewport_scroll_layer_ = NULL;
+ overscroll_elasticity_layer_id_ = Layer::INVALID_ID;
+ page_scale_layer_id_ = Layer::INVALID_ID;
+ inner_viewport_scroll_layer_id_ = Layer::INVALID_ID;
+ outer_viewport_scroll_layer_id_ = Layer::INVALID_ID;
+}
+
+#if DCHECK_IS_ON()
+int SanityCheckCopyRequestCounts(LayerImpl* layer) {
+ int count = layer->HasCopyRequest() ? 1 : 0;
+ for (size_t i = 0; i < layer->children().size(); ++i) {
+ count += SanityCheckCopyRequestCounts(layer->child_at(i));
+ }
+ DCHECK_EQ(count, layer->num_layer_or_descendants_with_copy_request())
+ << ", id: " << layer->id();
+ return count;
}
+#endif
bool LayerTreeImpl::UpdateDrawProperties(bool update_lcd_text) {
+#if DCHECK_IS_ON()
+ if (root_layer())
+ SanityCheckCopyRequestCounts(root_layer());
+#endif
+
if (!needs_update_draw_properties_)
return true;
@@ -606,8 +579,6 @@ bool LayerTreeImpl::UpdateDrawProperties(bool update_lcd_text) {
TRACE_EVENT2(
"cc", "LayerTreeImpl::UpdateDrawProperties::CalculateDrawProperties",
"IsActive", IsActiveTree(), "SourceFrameNumber", source_frame_number_);
- LayerImpl* page_scale_layer =
- page_scale_layer_ ? page_scale_layer_ : InnerViewportContainerLayer();
bool can_render_to_separate_surface =
(layer_tree_host_impl_->GetDrawMode() !=
DRAW_MODE_RESOURCELESS_SOFTWARE);
@@ -617,10 +588,10 @@ bool LayerTreeImpl::UpdateDrawProperties(bool update_lcd_text) {
LayerTreeHostCommon::CalcDrawPropsImplInputs inputs(
root_layer(), DrawViewportSize(),
layer_tree_host_impl_->DrawTransform(), device_scale_factor(),
- current_page_scale_factor(), page_scale_layer,
- inner_viewport_scroll_layer_, outer_viewport_scroll_layer_,
+ current_page_scale_factor(), PageScaleLayer(),
+ InnerViewportScrollLayer(), OuterViewportScrollLayer(),
elastic_overscroll()->Current(IsActiveTree()),
- overscroll_elasticity_layer_, resource_provider()->max_texture_size(),
+ OverscrollElasticityLayer(), resource_provider()->max_texture_size(),
settings().can_use_lcd_text, settings().layers_always_allowed_lcd_text,
can_render_to_separate_surface,
settings().layer_transforms_should_scale_layer_contents,
@@ -751,9 +722,10 @@ bool LayerTreeImpl::UpdateDrawProperties(bool update_lcd_text) {
}
void LayerTreeImpl::BuildPropertyTreesForTesting() {
+ LayerTreeHostCommon::PreCalculateMetaInformationForTesting(root_layer_.get());
PropertyTreeBuilder::BuildPropertyTrees(
- root_layer_.get(), page_scale_layer_, inner_viewport_scroll_layer_,
- outer_viewport_scroll_layer_, current_page_scale_factor(),
+ root_layer_.get(), PageScaleLayer(), InnerViewportScrollLayer(),
+ OuterViewportScrollLayer(), current_page_scale_factor(),
device_scale_factor(), gfx::Rect(DrawViewportSize()),
layer_tree_host_impl_->DrawTransform(), &property_trees_);
}
@@ -771,13 +743,20 @@ const Region& LayerTreeImpl::UnoccludedScreenSpaceRegion() const {
return unoccluded_screen_space_region_;
}
-gfx::Size LayerTreeImpl::ScrollableSize() const {
+gfx::SizeF LayerTreeImpl::ScrollableSize() const {
LayerImpl* root_scroll_layer = OuterViewportScrollLayer()
? OuterViewportScrollLayer()
: InnerViewportScrollLayer();
if (!root_scroll_layer || root_scroll_layer->children().empty())
- return gfx::Size();
- return root_scroll_layer->children()[0]->bounds();
+ return gfx::SizeF();
+
+ gfx::SizeF content_size =
+ root_scroll_layer->children()[0]->BoundsForScrolling();
+ gfx::SizeF viewport_size =
+ root_scroll_layer->scroll_clip_layer()->BoundsForScrolling();
+
+ content_size.SetToMax(viewport_size);
+ return content_size;
}
LayerImpl* LayerTreeImpl::LayerById(int id) const {
@@ -807,23 +786,12 @@ size_t LayerTreeImpl::NumLayers() {
return layer_id_map_.size();
}
-void LayerTreeImpl::PushPersistedState(LayerTreeImpl* pending_tree) {
- pending_tree->SetCurrentlyScrollingLayer(
- LayerTreeHostCommon::FindLayerInSubtree(pending_tree->root_layer(),
- currently_scrolling_layer_ ? currently_scrolling_layer_->id() : 0));
-}
-
void LayerTreeImpl::DidBecomeActive() {
if (next_activation_forces_redraw_) {
layer_tree_host_impl_->SetFullRootLayerDamage();
next_activation_forces_redraw_ = false;
}
- if (scrolling_layer_id_from_previous_tree_) {
- currently_scrolling_layer_ = LayerTreeHostCommon::FindLayerInSubtree(
- root_layer(), scrolling_layer_id_from_previous_tree_);
- }
-
// Always reset this flag on activation, as we would only have activated
// if we were in a good state.
layer_tree_host_impl_->ResetRequiresHighResToDraw();
@@ -893,10 +861,6 @@ FrameRateCounter* LayerTreeImpl::frame_rate_counter() const {
return layer_tree_host_impl_->fps_counter();
}
-PaintTimeCounter* LayerTreeImpl::paint_time_counter() const {
- return layer_tree_host_impl_->paint_time_counter();
-}
-
MemoryHistory* LayerTreeImpl::memory_history() const {
return layer_tree_host_impl_->memory_history();
}
@@ -905,10 +869,6 @@ gfx::Size LayerTreeImpl::device_viewport_size() const {
return layer_tree_host_impl_->device_viewport_size();
}
-float LayerTreeImpl::device_scale_factor() const {
- return layer_tree_host_impl_->device_scale_factor();
-}
-
DebugRectHistory* LayerTreeImpl::debug_rect_history() const {
return layer_tree_host_impl_->debug_rect_history();
}
@@ -1062,46 +1022,15 @@ void LayerTreeImpl::AsValueInto(base::trace_event::TracedValue* state) const {
for (auto* swap_promise : swap_promise_list_)
state->AppendDouble(swap_promise->TraceId());
state->EndArray();
-}
-
-void LayerTreeImpl::SetRootLayerScrollOffsetDelegate(
- LayerScrollOffsetDelegate* root_layer_scroll_offset_delegate) {
- if (root_layer_scroll_offset_delegate_ == root_layer_scroll_offset_delegate)
- return;
-
- root_layer_scroll_offset_delegate_ = root_layer_scroll_offset_delegate;
-
- if (root_layer_scroll_offset_delegate_) {
- root_layer_scroll_offset_delegate_->UpdateRootLayerState(
- TotalScrollOffset(), TotalMaxScrollOffset(), ScrollableSize(),
- current_page_scale_factor(), min_page_scale_factor(),
- max_page_scale_factor());
-
- DistributeRootScrollOffset();
- }
-}
-
-void LayerTreeImpl::UpdateRootScrollOffsetDelegate() {
- DCHECK(root_layer_scroll_offset_delegate_);
- gfx::ScrollOffset offset = InnerViewportScrollLayer()->CurrentScrollOffset();
-
- if (OuterViewportScrollLayer())
- offset += OuterViewportScrollLayer()->CurrentScrollOffset();
-
- root_layer_scroll_offset_delegate_->UpdateRootLayerState(
- offset, TotalMaxScrollOffset(), ScrollableSize(),
- current_page_scale_factor(), min_page_scale_factor(),
- max_page_scale_factor());
+ state->BeginArray("pinned_swap_promise_trace_ids");
+ for (auto* swap_promise : pinned_swap_promise_list_)
+ state->AppendDouble(swap_promise->TraceId());
+ state->EndArray();
}
-void LayerTreeImpl::DistributeRootScrollOffset() {
- if (!root_layer_scroll_offset_delegate_)
- return;
-
- gfx::ScrollOffset root_offset =
- root_layer_scroll_offset_delegate_->GetTotalScrollOffset();
-
+void LayerTreeImpl::DistributeRootScrollOffset(
+ const gfx::ScrollOffset& root_offset) {
if (!InnerViewportScrollLayer())
return;
@@ -1115,6 +1044,7 @@ void LayerTreeImpl::DistributeRootScrollOffset() {
OuterViewportScrollLayer()->CurrentScrollOffset();
// It may be nothing has changed.
+ DCHECK(inner_viewport_offset + outer_viewport_offset == TotalScrollOffset());
if (inner_viewport_offset + outer_viewport_offset == root_offset)
return;
@@ -1125,13 +1055,9 @@ void LayerTreeImpl::DistributeRootScrollOffset() {
outer_viewport_offset.SetToMin(max_outer_viewport_scroll_offset);
outer_viewport_offset.SetToMax(gfx::ScrollOffset());
- OuterViewportScrollLayer()->SetCurrentScrollOffsetFromDelegate(
- outer_viewport_offset);
+ OuterViewportScrollLayer()->SetCurrentScrollOffset(outer_viewport_offset);
inner_viewport_offset = root_offset - outer_viewport_offset;
- InnerViewportScrollLayer()->SetCurrentScrollOffsetFromDelegate(
- inner_viewport_offset);
-
- UpdateRootScrollOffsetDelegate();
+ InnerViewportScrollLayer()->SetCurrentScrollOffset(inner_viewport_offset);
}
void LayerTreeImpl::QueueSwapPromise(scoped_ptr<SwapPromise> swap_promise) {
@@ -1139,23 +1065,37 @@ void LayerTreeImpl::QueueSwapPromise(scoped_ptr<SwapPromise> swap_promise) {
swap_promise_list_.push_back(swap_promise.Pass());
}
+void LayerTreeImpl::QueuePinnedSwapPromise(
+ scoped_ptr<SwapPromise> swap_promise) {
+ DCHECK(IsActiveTree());
+ DCHECK(swap_promise);
+ pinned_swap_promise_list_.push_back(swap_promise.Pass());
+}
+
void LayerTreeImpl::PassSwapPromises(
ScopedPtrVector<SwapPromise>* new_swap_promise) {
- swap_promise_list_.insert_and_take(swap_promise_list_.end(),
- new_swap_promise);
- new_swap_promise->clear();
+ for (auto* swap_promise : swap_promise_list_)
+ swap_promise->DidNotSwap(SwapPromise::SWAP_FAILS);
+ swap_promise_list_.clear();
+ swap_promise_list_.swap(*new_swap_promise);
}
void LayerTreeImpl::FinishSwapPromises(CompositorFrameMetadata* metadata) {
for (auto* swap_promise : swap_promise_list_)
swap_promise->DidSwap(metadata);
swap_promise_list_.clear();
+ for (auto* swap_promise : pinned_swap_promise_list_)
+ swap_promise->DidSwap(metadata);
+ pinned_swap_promise_list_.clear();
}
void LayerTreeImpl::BreakSwapPromises(SwapPromise::DidNotSwapReason reason) {
for (auto* swap_promise : swap_promise_list_)
swap_promise->DidNotSwap(reason);
swap_promise_list_.clear();
+ for (auto* swap_promise : pinned_swap_promise_list_)
+ swap_promise->DidNotSwap(reason);
+ pinned_swap_promise_list_.clear();
}
void LayerTreeImpl::DidModifyTilePriorities() {
@@ -1262,7 +1202,7 @@ static inline bool LayerClipsSubtree(LayerType* layer) {
static bool PointHitsRect(
const gfx::PointF& screen_space_point,
const gfx::Transform& local_space_to_screen_space_transform,
- const gfx::RectF& local_space_rect,
+ const gfx::Rect& local_space_rect,
float* distance_to_camera) {
// If the transform is not invertible, then assume that this point doesn't hit
// this rect.
@@ -1285,7 +1225,7 @@ static bool PointHitsRect(
if (clipped)
return false;
- if (!local_space_rect.Contains(hit_test_point_in_local_space))
+ if (!gfx::RectF(local_space_rect).Contains(hit_test_point_in_local_space))
return false;
if (distance_to_camera) {
@@ -1361,7 +1301,7 @@ static bool PointIsClippedBySurfaceOrClipRect(
static bool PointHitsLayer(const LayerImpl* layer,
const gfx::PointF& screen_space_point,
float* distance_to_intersection) {
- gfx::RectF content_rect(layer->bounds());
+ gfx::Rect content_rect(layer->bounds());
if (!PointHitsRect(screen_space_point,
layer->screen_space_transform(),
content_rect,
@@ -1555,6 +1495,14 @@ static ViewportSelectionBound ComputeViewportSelectionBound(
gfx::PointF screen_bottom = MathUtil::MapPoint(
layer->screen_space_transform(), layer_bottom, &clipped);
+ // MapPoint can produce points with NaN components (even when no inputs are
+ // NaN). Since consumers of ViewportSelectionBounds may round |edge_top| or
+ // |edge_bottom| (and since rounding will crash on NaN), we return an empty
+ // bound instead.
+ if (std::isnan(screen_top.x()) || std::isnan(screen_top.y()) ||
+ std::isnan(screen_bottom.x()) || std::isnan(screen_bottom.y()))
+ return ViewportSelectionBound();
+
const float inv_scale = 1.f / device_scale_factor;
viewport_bound.edge_top = gfx::ScalePoint(screen_top, inv_scale);
viewport_bound.edge_bottom = gfx::ScalePoint(screen_bottom, inv_scale);
@@ -1627,39 +1575,71 @@ scoped_ptr<PendingPageScaleAnimation>
}
bool LayerTreeImpl::IsAnimatingFilterProperty(const LayerImpl* layer) const {
+ LayerTreeType tree_type =
+ IsActiveTree() ? LayerTreeType::ACTIVE : LayerTreeType::PENDING;
return layer_tree_host_impl_->animation_host()
? layer_tree_host_impl_->animation_host()
- ->IsAnimatingFilterProperty(layer->id())
+ ->IsAnimatingFilterProperty(layer->id(), tree_type)
: false;
}
bool LayerTreeImpl::IsAnimatingOpacityProperty(const LayerImpl* layer) const {
+ LayerTreeType tree_type =
+ IsActiveTree() ? LayerTreeType::ACTIVE : LayerTreeType::PENDING;
return layer_tree_host_impl_->animation_host()
? layer_tree_host_impl_->animation_host()
- ->IsAnimatingOpacityProperty(layer->id())
+ ->IsAnimatingOpacityProperty(layer->id(), tree_type)
: false;
}
bool LayerTreeImpl::IsAnimatingTransformProperty(const LayerImpl* layer) const {
+ LayerTreeType tree_type =
+ IsActiveTree() ? LayerTreeType::ACTIVE : LayerTreeType::PENDING;
+ return layer_tree_host_impl_->animation_host()
+ ? layer_tree_host_impl_->animation_host()
+ ->IsAnimatingTransformProperty(layer->id(), tree_type)
+ : false;
+}
+
+bool LayerTreeImpl::HasPotentiallyRunningFilterAnimation(
+ const LayerImpl* layer) const {
+ LayerTreeType tree_type =
+ IsActiveTree() ? LayerTreeType::ACTIVE : LayerTreeType::PENDING;
return layer_tree_host_impl_->animation_host()
? layer_tree_host_impl_->animation_host()
- ->IsAnimatingTransformProperty(layer->id())
+ ->HasPotentiallyRunningFilterAnimation(layer->id(),
+ tree_type)
: false;
}
bool LayerTreeImpl::HasPotentiallyRunningOpacityAnimation(
const LayerImpl* layer) const {
+ LayerTreeType tree_type =
+ IsActiveTree() ? LayerTreeType::ACTIVE : LayerTreeType::PENDING;
return layer_tree_host_impl_->animation_host()
? layer_tree_host_impl_->animation_host()
- ->HasPotentiallyRunningOpacityAnimation(layer->id())
+ ->HasPotentiallyRunningOpacityAnimation(layer->id(),
+ tree_type)
: false;
}
bool LayerTreeImpl::HasPotentiallyRunningTransformAnimation(
const LayerImpl* layer) const {
+ LayerTreeType tree_type =
+ IsActiveTree() ? LayerTreeType::ACTIVE : LayerTreeType::PENDING;
+ return layer_tree_host_impl_->animation_host()
+ ? layer_tree_host_impl_->animation_host()
+ ->HasPotentiallyRunningTransformAnimation(layer->id(),
+ tree_type)
+ : false;
+}
+
+bool LayerTreeImpl::HasAnyAnimationTargetingProperty(
+ const LayerImpl* layer,
+ Animation::TargetProperty property) const {
return layer_tree_host_impl_->animation_host()
? layer_tree_host_impl_->animation_host()
- ->HasPotentiallyRunningTransformAnimation(layer->id())
+ ->HasAnyAnimationTargetingProperty(layer->id(), property)
: false;
}
@@ -1686,27 +1666,33 @@ bool LayerTreeImpl::TransformIsAnimatingOnImplOnly(
}
bool LayerTreeImpl::HasOnlyTranslationTransforms(const LayerImpl* layer) const {
+ LayerTreeType tree_type =
+ IsActiveTree() ? LayerTreeType::ACTIVE : LayerTreeType::PENDING;
return layer_tree_host_impl_->animation_host()
? layer_tree_host_impl_->animation_host()
- ->HasOnlyTranslationTransforms(layer->id())
+ ->HasOnlyTranslationTransforms(layer->id(), tree_type)
: true;
}
bool LayerTreeImpl::MaximumTargetScale(const LayerImpl* layer,
float* max_scale) const {
*max_scale = 0.f;
+ LayerTreeType tree_type =
+ IsActiveTree() ? LayerTreeType::ACTIVE : LayerTreeType::PENDING;
return layer_tree_host_impl_->animation_host()
? layer_tree_host_impl_->animation_host()->MaximumTargetScale(
- layer->id(), max_scale)
+ layer->id(), tree_type, max_scale)
: true;
}
bool LayerTreeImpl::AnimationStartScale(const LayerImpl* layer,
float* start_scale) const {
*start_scale = 0.f;
+ LayerTreeType tree_type =
+ IsActiveTree() ? LayerTreeType::ACTIVE : LayerTreeType::PENDING;
return layer_tree_host_impl_->animation_host()
? layer_tree_host_impl_->animation_host()->AnimationStartScale(
- layer->id(), start_scale)
+ layer->id(), tree_type, start_scale)
: true;
}
diff --git a/chromium/cc/trees/layer_tree_impl.h b/chromium/cc/trees/layer_tree_impl.h
index 973df977733..ed4413a4e6e 100644
--- a/chromium/cc/trees/layer_tree_impl.h
+++ b/chromium/cc/trees/layer_tree_impl.h
@@ -42,7 +42,6 @@ class LayerTreeSettings;
class MemoryHistory;
class OutputSurface;
class PageScaleAnimation;
-class PaintTimeCounter;
class PictureLayerImpl;
class Proxy;
class ResourceProvider;
@@ -83,10 +82,8 @@ class CC_EXPORT LayerTreeImpl {
ResourceProvider* resource_provider() const;
TileManager* tile_manager() const;
FrameRateCounter* frame_rate_counter() const;
- PaintTimeCounter* paint_time_counter() const;
MemoryHistory* memory_history() const;
gfx::Size device_viewport_size() const;
- float device_scale_factor() const;
DebugRectHistory* debug_rect_history() const;
bool IsActiveTree() const;
bool IsPendingTree() const;
@@ -166,10 +163,10 @@ class CC_EXPORT LayerTreeImpl {
int inner_viewport_scroll_layer_id,
int outer_viewport_scroll_layer_id);
void ClearViewportLayers();
- LayerImpl* overscroll_elasticity_layer() {
- return overscroll_elasticity_layer_;
+ LayerImpl* OverscrollElasticityLayer() {
+ return LayerById(overscroll_elasticity_layer_id_);
}
- LayerImpl* page_scale_layer() { return page_scale_layer_; }
+ LayerImpl* PageScaleLayer() { return LayerById(page_scale_layer_id_); }
void ApplySentScrollAndScaleDeltasFromAbortedCommit();
SkColor background_color() const { return background_color_; }
@@ -198,6 +195,13 @@ class CC_EXPORT LayerTreeImpl {
SyncedProperty<ScaleGroup>* page_scale_factor();
const SyncedProperty<ScaleGroup>* page_scale_factor() const;
+ void SetDeviceScaleFactor(float device_scale_factor);
+ float device_scale_factor() const { return device_scale_factor_; }
+
+ void set_hide_pinch_scrollbars_near_min_scale(bool hide) {
+ hide_pinch_scrollbars_near_min_scale_ = hide;
+ }
+
SyncedElasticOverscroll* elastic_overscroll() {
return elastic_overscroll_.get();
}
@@ -242,7 +246,7 @@ class CC_EXPORT LayerTreeImpl {
// These return the size of the root scrollable area and the size of
// the user-visible scrolling viewport, in CSS layout coordinates.
- gfx::Size ScrollableSize() const;
+ gfx::SizeF ScrollableSize() const;
gfx::SizeF ScrollableViewportSize() const;
gfx::Rect RootScrollLayerDeviceViewportBounds() const;
@@ -257,8 +261,6 @@ class CC_EXPORT LayerTreeImpl {
AnimationRegistrar* GetAnimationRegistrar() const;
- void PushPersistedState(LayerTreeImpl* pending_tree);
-
void DidBecomeActive();
// Set on the active tree when the viewport size recently changed
@@ -270,17 +272,36 @@ class CC_EXPORT LayerTreeImpl {
// Useful for debug assertions, probably shouldn't be used for anything else.
Proxy* proxy() const;
- void SetRootLayerScrollOffsetDelegate(
- LayerScrollOffsetDelegate* root_layer_scroll_offset_delegate);
- void UpdateRootScrollOffsetDelegate();
- // Distribute the rool scroll between outer and inner viewport scroll layer.
+ // Distribute the root scroll between outer and inner viewport scroll layer.
// The outer viewport scroll layer scrolls first.
- void DistributeRootScrollOffset();
+ void DistributeRootScrollOffset(const gfx::ScrollOffset& root_offset);
+
+ void ApplyScroll(LayerImpl* layer, ScrollState* scroll_state) {
+ layer_tree_host_impl_->ApplyScroll(layer, scroll_state);
+ }
// Call this function when you expect there to be a swap buffer.
// See swap_promise.h for how to use SwapPromise.
+ //
+ // A swap promise queued by QueueSwapPromise travels with the layer
+ // information currently associated with the tree. For example, when
+ // a pending tree is activated, the swap promise is passed to the
+ // active tree along with the layer information. Similarly, when a
+ // new activation overwrites layer information on the active tree,
+ // queued swap promises are broken.
void QueueSwapPromise(scoped_ptr<SwapPromise> swap_promise);
+ // Queue a swap promise, pinned to this tree. Pinned swap promises
+ // may only be queued on the active tree.
+ //
+ // An active tree pinned swap promise will see only DidSwap() or
+ // DidNotSwap(SWAP_FAILS). No DidActivate() will be seen because
+ // that has already happened prior to queueing of the swap promise.
+ //
+ // Pinned active tree swap promises will not be broken prematurely
+ // on the active tree if a new tree is activated.
+ void QueuePinnedSwapPromise(scoped_ptr<SwapPromise> swap_promise);
+
// Take the |new_swap_promise| and append it to |swap_promise_list_|.
void PassSwapPromises(ScopedPtrVector<SwapPromise>* new_swap_promise);
void FinishSwapPromises(CompositorFrameMetadata* metadata);
@@ -342,16 +363,18 @@ class CC_EXPORT LayerTreeImpl {
void GatherFrameTimingRequestIds(std::vector<int64_t>* request_ids);
- bool IsExternalScrollActive() const;
- void DidUpdateScrollOffset(int layer_id);
-
bool IsAnimatingFilterProperty(const LayerImpl* layer) const;
bool IsAnimatingOpacityProperty(const LayerImpl* layer) const;
bool IsAnimatingTransformProperty(const LayerImpl* layer) const;
+ bool HasPotentiallyRunningFilterAnimation(const LayerImpl* layer) const;
bool HasPotentiallyRunningOpacityAnimation(const LayerImpl* layer) const;
bool HasPotentiallyRunningTransformAnimation(const LayerImpl* layer) const;
+ bool HasAnyAnimationTargetingProperty(
+ const LayerImpl* layer,
+ Animation::TargetProperty property) const;
+
bool FilterIsAnimatingOnImplOnly(const LayerImpl* layer) const;
bool OpacityIsAnimatingOnImplOnly(const LayerImpl* layer) const;
bool TransformIsAnimatingOnImplOnly(const LayerImpl* layer) const;
@@ -385,28 +408,30 @@ class CC_EXPORT LayerTreeImpl {
bool SetPageScaleFactorLimits(float min_page_scale_factor,
float max_page_scale_factor);
void DidUpdatePageScale();
- void HideInnerViewportScrollbarsIfNearMinimumScale();
+ void HideInnerViewportScrollbarsIfNeeded();
void PushTopControls(const float* top_controls_shown_ratio);
LayerTreeHostImpl* layer_tree_host_impl_;
int source_frame_number_;
scoped_ptr<LayerImpl> root_layer_;
HeadsUpDisplayLayerImpl* hud_layer_;
PropertyTrees property_trees_;
- LayerImpl* currently_scrolling_layer_;
- LayerScrollOffsetDelegate* root_layer_scroll_offset_delegate_;
SkColor background_color_;
bool has_transparent_background_;
- LayerImpl* overscroll_elasticity_layer_;
- LayerImpl* page_scale_layer_;
- LayerImpl* inner_viewport_scroll_layer_;
- LayerImpl* outer_viewport_scroll_layer_;
+ int currently_scrolling_layer_id_;
+ int overscroll_elasticity_layer_id_;
+ int page_scale_layer_id_;
+ int inner_viewport_scroll_layer_id_;
+ int outer_viewport_scroll_layer_id_;
LayerSelection selection_;
scoped_refptr<SyncedProperty<ScaleGroup>> page_scale_factor_;
float min_page_scale_factor_;
float max_page_scale_factor_;
+ bool hide_pinch_scrollbars_near_min_scale_;
+
+ float device_scale_factor_;
scoped_refptr<SyncedElasticOverscroll> elastic_overscroll_;
@@ -416,9 +441,6 @@ class CC_EXPORT LayerTreeImpl {
std::vector<PictureLayerImpl*> picture_layers_;
std::vector<LayerImpl*> layers_with_copy_output_request_;
- // Persisted state for non-impl-side-painting.
- int scrolling_layer_id_from_previous_tree_;
-
// List of visible layers for the most recently prepared frame.
LayerImplList render_surface_layer_list_;
// After drawing the |render_surface_layer_list_| the areas in this region
@@ -437,6 +459,7 @@ class CC_EXPORT LayerTreeImpl {
bool has_ever_been_drawn_;
ScopedPtrVector<SwapPromise> swap_promise_list_;
+ ScopedPtrVector<SwapPromise> pinned_swap_promise_list_;
UIResourceRequestQueue ui_resource_request_queue_;
diff --git a/chromium/cc/trees/layer_tree_impl_unittest.cc b/chromium/cc/trees/layer_tree_impl_unittest.cc
index 81a566fe7f3..ba5fc7b9eae 100644
--- a/chromium/cc/trees/layer_tree_impl_unittest.cc
+++ b/chromium/cc/trees/layer_tree_impl_unittest.cc
@@ -22,13 +22,13 @@ namespace {
class LayerTreeImplTest : public LayerTreeHostCommonTest {
public:
- LayerTreeImplTest() {
+ LayerTreeImplTest() : output_surface_(FakeOutputSurface::Create3d()) {
LayerTreeSettings settings;
settings.layer_transforms_should_scale_layer_contents = true;
- settings.scrollbar_show_scale_threshold = 1.1f;
+ settings.verify_property_trees = true;
host_impl_.reset(new FakeLayerTreeHostImpl(
settings, &proxy_, &shared_bitmap_manager_, &task_graph_runner_));
- EXPECT_TRUE(host_impl_->InitializeRenderer(FakeOutputSurface::Create3d()));
+ EXPECT_TRUE(host_impl_->InitializeRenderer(output_surface_.get()));
}
FakeLayerTreeHostImpl& host_impl() { return *host_impl_; }
@@ -43,6 +43,7 @@ class LayerTreeImplTest : public LayerTreeHostCommonTest {
TestSharedBitmapManager shared_bitmap_manager_;
TestTaskGraphRunner task_graph_runner_;
FakeImplProxy proxy_;
+ scoped_ptr<OutputSurface> output_surface_;
scoped_ptr<FakeLayerTreeHostImpl> host_impl_;
};
@@ -91,6 +92,49 @@ TEST_F(LayerTreeImplTest, HitTestingForSingleLayer) {
EXPECT_EQ(12345, result_layer->id());
}
+TEST_F(LayerTreeImplTest, UpdateViewportAndHitTest) {
+ // Ensures that the viewport rect is correctly updated by the clip tree.
+ TestSharedBitmapManager shared_bitmap_manager;
+ TestTaskGraphRunner task_graph_runner;
+ FakeImplProxy proxy;
+ LayerTreeSettings settings;
+ settings.verify_property_trees = true;
+ scoped_ptr<OutputSurface> output_surface = FakeOutputSurface::Create3d();
+ scoped_ptr<FakeLayerTreeHostImpl> host_impl;
+ host_impl.reset(new FakeLayerTreeHostImpl(
+ settings, &proxy, &shared_bitmap_manager, &task_graph_runner));
+ EXPECT_TRUE(host_impl->InitializeRenderer(output_surface.get()));
+ scoped_ptr<LayerImpl> root =
+ LayerImpl::Create(host_impl->active_tree(), 12345);
+
+ gfx::Transform identity_matrix;
+ gfx::Point3F transform_origin;
+ gfx::PointF position;
+ gfx::Size bounds(100, 100);
+ SetLayerPropertiesForTesting(root.get(), identity_matrix, transform_origin,
+ position, bounds, true, false, true);
+ root->SetDrawsContent(true);
+
+ host_impl->SetViewportSize(root->bounds());
+ host_impl->active_tree()->SetRootLayer(root.Pass());
+ host_impl->UpdateNumChildrenAndDrawPropertiesForActiveTree();
+ EXPECT_EQ(
+ gfx::RectF(gfx::SizeF(bounds)),
+ host_impl->active_tree()->property_trees()->clip_tree.ViewportClip());
+ EXPECT_EQ(gfx::Rect(bounds),
+ host_impl->RootLayer()->visible_rect_from_property_trees());
+
+ gfx::Size new_bounds(50, 50);
+ host_impl->SetViewportSize(new_bounds);
+ gfx::Point test_point(51, 51);
+ host_impl->active_tree()->FindLayerThatIsHitByPoint(test_point);
+ EXPECT_EQ(
+ gfx::RectF(gfx::SizeF(new_bounds)),
+ host_impl->active_tree()->property_trees()->clip_tree.ViewportClip());
+ EXPECT_EQ(gfx::Rect(new_bounds),
+ host_impl->RootLayer()->visible_rect_from_property_trees());
+}
+
TEST_F(LayerTreeImplTest, HitTestingForSingleLayerAndHud) {
scoped_ptr<LayerImpl> root =
LayerImpl::Create(host_impl().active_tree(), 12345);
@@ -972,6 +1016,9 @@ TEST_F(LayerTreeImplTest, HitTestingRespectsScrollParents) {
// This should cause scroll child and its descendants to be affected by
// |child|'s clip.
scroll_child->SetScrollParent(child.get());
+ scoped_ptr<std::set<LayerImpl*>> scroll_children(new std::set<LayerImpl*>);
+ scroll_children->insert(scroll_child.get());
+ child->SetScrollChildren(scroll_children.release());
SetLayerPropertiesForTesting(grand_child.get(), identity_matrix,
transform_origin, position, bounds, true,
@@ -1293,6 +1340,7 @@ TEST_F(LayerTreeImplTest, MakeScrollbarsInvisibleNearMinPageScale) {
const bool kIsOverlayScrollbar = true;
LayerTreeImpl* active_tree = host_impl().active_tree();
+ active_tree->set_hide_pinch_scrollbars_near_min_scale(true);
scoped_ptr<LayerImpl> scroll_layer = LayerImpl::Create(active_tree, 1);
scoped_ptr<SolidColorScrollbarLayerImpl> vertical_scrollbar_layer =
@@ -1340,11 +1388,11 @@ TEST_F(LayerTreeImplTest, MakeScrollbarsInvisibleNearMinPageScale) {
EXPECT_TRUE(vertical_scrollbar_layer->hide_layer_and_subtree());
EXPECT_TRUE(horizontal_scrollbar_layer->hide_layer_and_subtree());
- active_tree->PushPageScaleFromMainThread(1.05f, 1.0f, 4.0f);
+ active_tree->PushPageScaleFromMainThread(1.04f, 1.0f, 4.0f);
EXPECT_TRUE(vertical_scrollbar_layer->hide_layer_and_subtree());
EXPECT_TRUE(horizontal_scrollbar_layer->hide_layer_and_subtree());
- active_tree->PushPageScaleFromMainThread(1.1f, 1.0f, 4.0f);
+ active_tree->PushPageScaleFromMainThread(1.06f, 1.0f, 4.0f);
EXPECT_FALSE(vertical_scrollbar_layer->hide_layer_and_subtree());
EXPECT_FALSE(horizontal_scrollbar_layer->hide_layer_and_subtree());
@@ -1448,14 +1496,14 @@ TEST_F(LayerTreeImplTest,
float device_scale_factor = 3.f;
float page_scale_factor = 5.f;
- gfx::Size scaled_bounds_for_root = gfx::ToCeiledSize(
- gfx::ScaleSize(root->bounds(), device_scale_factor * page_scale_factor));
+ gfx::Size scaled_bounds_for_root = gfx::ScaleToCeiledSize(
+ root->bounds(), device_scale_factor * page_scale_factor);
host_impl().SetViewportSize(scaled_bounds_for_root);
- host_impl().SetDeviceScaleFactor(device_scale_factor);
+ host_impl().active_tree()->SetDeviceScaleFactor(device_scale_factor);
host_impl().active_tree()->PushPageScaleFromMainThread(
page_scale_factor, page_scale_factor, page_scale_factor);
- host_impl().SetPageScaleOnActiveTree(page_scale_factor);
+ host_impl().active_tree()->SetPageScaleOnActiveTree(page_scale_factor);
host_impl().active_tree()->SetRootLayer(root.Pass());
host_impl().active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 1,
Layer::INVALID_ID);
@@ -1907,14 +1955,14 @@ TEST_F(LayerTreeImplTest, SelectionBoundsForScaledLayers) {
float device_scale_factor = 3.f;
float page_scale_factor = 5.f;
- gfx::Size scaled_bounds_for_root = gfx::ToCeiledSize(
- gfx::ScaleSize(root->bounds(), device_scale_factor * page_scale_factor));
+ gfx::Size scaled_bounds_for_root = gfx::ScaleToCeiledSize(
+ root->bounds(), device_scale_factor * page_scale_factor);
host_impl().SetViewportSize(scaled_bounds_for_root);
- host_impl().SetDeviceScaleFactor(device_scale_factor);
+ host_impl().active_tree()->SetDeviceScaleFactor(device_scale_factor);
host_impl().active_tree()->PushPageScaleFromMainThread(
page_scale_factor, page_scale_factor, page_scale_factor);
- host_impl().SetPageScaleOnActiveTree(page_scale_factor);
+ host_impl().active_tree()->SetPageScaleOnActiveTree(page_scale_factor);
host_impl().active_tree()->SetRootLayer(root.Pass());
host_impl().active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 1,
Layer::INVALID_ID);
@@ -1960,6 +2008,69 @@ TEST_F(LayerTreeImplTest, SelectionBoundsForScaledLayers) {
EXPECT_TRUE(output.end.visible);
}
+TEST_F(LayerTreeImplTest, SelectionBoundsWithLargeTransforms) {
+ int root_id = 1;
+ int child_id = 2;
+ int grand_child_id = 3;
+
+ scoped_ptr<LayerImpl> root =
+ LayerImpl::Create(host_impl().active_tree(), root_id);
+ gfx::Size bounds(100, 100);
+ gfx::Transform identity_matrix;
+ gfx::Point3F transform_origin;
+ gfx::PointF position;
+
+ SetLayerPropertiesForTesting(root.get(), identity_matrix, transform_origin,
+ position, bounds, true, false, true);
+
+ gfx::Transform large_transform;
+ large_transform.Scale(SkDoubleToMScalar(1e37), SkDoubleToMScalar(1e37));
+ large_transform.RotateAboutYAxis(30);
+
+ {
+ scoped_ptr<LayerImpl> child =
+ LayerImpl::Create(host_impl().active_tree(), child_id);
+ SetLayerPropertiesForTesting(child.get(), large_transform, transform_origin,
+ position, bounds, true, false, false);
+
+ scoped_ptr<LayerImpl> grand_child =
+ LayerImpl::Create(host_impl().active_tree(), grand_child_id);
+ SetLayerPropertiesForTesting(grand_child.get(), large_transform,
+ transform_origin, position, bounds, true,
+ false, false);
+ grand_child->SetDrawsContent(true);
+
+ child->AddChild(grand_child.Pass());
+ root->AddChild(child.Pass());
+ }
+
+ host_impl().SetViewportSize(root->bounds());
+ host_impl().active_tree()->SetRootLayer(root.Pass());
+ host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree();
+
+ LayerSelection input;
+
+ input.start.type = SELECTION_BOUND_LEFT;
+ input.start.edge_top = gfx::PointF(10, 10);
+ input.start.edge_bottom = gfx::PointF(10, 20);
+ input.start.layer_id = grand_child_id;
+
+ input.end.type = SELECTION_BOUND_RIGHT;
+ input.end.edge_top = gfx::PointF(50, 10);
+ input.end.edge_bottom = gfx::PointF(50, 30);
+ input.end.layer_id = grand_child_id;
+
+ host_impl().active_tree()->RegisterSelection(input);
+
+ ViewportSelection output;
+ host_impl().active_tree()->GetViewportSelection(&output);
+
+ // edge_bottom and edge_top aren't allowed to have NaNs, so the selection
+ // should be empty.
+ EXPECT_EQ(ViewportSelectionBound(), output.start);
+ EXPECT_EQ(ViewportSelectionBound(), output.end);
+}
+
TEST_F(LayerTreeImplTest, NumLayersTestOne) {
EXPECT_EQ(0u, host_impl().active_tree()->NumLayers());
scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl().active_tree(), 1);
diff --git a/chromium/cc/trees/layer_tree_settings.cc b/chromium/cc/trees/layer_tree_settings.cc
index 92d7dda7040..414abb3fab3 100644
--- a/chromium/cc/trees/layer_tree_settings.cc
+++ b/chromium/cc/trees/layer_tree_settings.cc
@@ -10,6 +10,7 @@
#include "base/command_line.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
+#include "ui/gfx/buffer_types.h"
namespace cc {
@@ -24,7 +25,6 @@ LayerTreeSettings::LayerTreeSettings()
use_external_begin_frame_source(false),
main_frame_before_activation_enabled(false),
using_synchronous_renderer_compositor(false),
- report_overscroll_only_for_scrollable_axes(false),
accelerated_animation_enabled(true),
can_use_lcd_text(true),
use_distance_field_text(false),
@@ -37,7 +37,6 @@ LayerTreeSettings::LayerTreeSettings()
scrollbar_fade_delay_ms(0),
scrollbar_fade_resize_delay_ms(0),
scrollbar_fade_duration_ms(0),
- scrollbar_show_scale_threshold(1.0f),
solid_color_scrollbar_color(SK_ColorWHITE),
timeout_and_draw_when_animation_checkerboards(true),
layer_transforms_should_scale_layer_contents(false),
@@ -47,33 +46,30 @@ LayerTreeSettings::LayerTreeSettings()
top_controls_show_threshold(0.5f),
top_controls_hide_threshold(0.5f),
background_animation_rate(1.0),
- max_partial_texture_updates(std::numeric_limits<size_t>::max()),
default_tile_size(gfx::Size(256, 256)),
max_untiled_layer_size(gfx::Size(512, 512)),
- default_tile_grid_size(gfx::Size(256, 256)),
minimum_occlusion_tracking_size(gfx::Size(160, 160)),
- // At 256x256 tiles, 128 tiles cover an area of 2048x4096 pixels.
- max_tiles_for_interest_area(128),
+ // 3000 pixels should give sufficient area for prepainting.
+ tiling_interest_area_padding(3000),
skewport_target_time_in_seconds(1.0f),
skewport_extrapolation_limit_in_content_pixels(2000),
- max_unused_resource_memory_percentage(100),
max_memory_for_prepaint_percentage(100),
strict_layer_property_change_checking(false),
- use_one_copy(true),
use_zero_copy(false),
use_persistent_map_for_gpu_memory_buffers(false),
enable_elastic_overscroll(false),
- use_image_texture_target(GL_TEXTURE_2D),
+ use_image_texture_targets(
+ static_cast<size_t>(gfx::BufferFormat::LAST) + 1,
+ GL_TEXTURE_2D),
ignore_root_layer_flings(false),
scheduled_raster_task_limit(32),
use_occlusion_for_tile_prioritization(false),
record_full_layer(false),
- use_display_lists(false),
verify_property_trees(false),
- gather_pixel_refs(false),
+ image_decode_tasks_enabled(false),
use_compositor_animation_timelines(false),
- invert_viewport_scroll_order(false) {
-}
+ wait_for_beginframe_interval(true),
+ max_staging_buffer_usage_in_bytes(32 * 1024 * 1024) {}
LayerTreeSettings::~LayerTreeSettings() {}
@@ -87,8 +83,7 @@ SchedulerSettings LayerTreeSettings::ToSchedulerSettings() const {
timeout_and_draw_when_animation_checkerboards;
scheduler_settings.using_synchronous_renderer_compositor =
using_synchronous_renderer_compositor;
- scheduler_settings.throttle_frame_production =
- !renderer_settings.disable_gpu_vsync;
+ scheduler_settings.throttle_frame_production = wait_for_beginframe_interval;
scheduler_settings.background_frame_interval =
base::TimeDelta::FromSecondsD(1.0 / background_animation_rate);
return scheduler_settings;
diff --git a/chromium/cc/trees/layer_tree_settings.h b/chromium/cc/trees/layer_tree_settings.h
index 6334f94bb13..f6656d5bf55 100644
--- a/chromium/cc/trees/layer_tree_settings.h
+++ b/chromium/cc/trees/layer_tree_settings.h
@@ -5,6 +5,8 @@
#ifndef CC_TREES_LAYER_TREE_SETTINGS_H_
#define CC_TREES_LAYER_TREE_SETTINGS_H_
+#include <vector>
+
#include "base/basictypes.h"
#include "cc/base/cc_export.h"
#include "cc/debug/layer_tree_debug_state.h"
@@ -33,7 +35,6 @@ class CC_EXPORT LayerTreeSettings {
bool use_external_begin_frame_source;
bool main_frame_before_activation_enabled;
bool using_synchronous_renderer_compositor;
- bool report_overscroll_only_for_scrollable_axes;
bool accelerated_animation_enabled;
bool can_use_lcd_text;
bool use_distance_field_text;
@@ -52,7 +53,6 @@ class CC_EXPORT LayerTreeSettings {
int scrollbar_fade_delay_ms;
int scrollbar_fade_resize_delay_ms;
int scrollbar_fade_duration_ms;
- float scrollbar_show_scale_threshold;
SkColor solid_color_scrollbar_color;
bool timeout_and_draw_when_animation_checkerboards;
bool layer_transforms_should_scale_layer_contents;
@@ -62,31 +62,28 @@ class CC_EXPORT LayerTreeSettings {
float top_controls_show_threshold;
float top_controls_hide_threshold;
double background_animation_rate;
- size_t max_partial_texture_updates;
gfx::Size default_tile_size;
gfx::Size max_untiled_layer_size;
- gfx::Size default_tile_grid_size;
gfx::Size minimum_occlusion_tracking_size;
- size_t max_tiles_for_interest_area;
+ size_t tiling_interest_area_padding;
float skewport_target_time_in_seconds;
int skewport_extrapolation_limit_in_content_pixels;
- size_t max_unused_resource_memory_percentage;
size_t max_memory_for_prepaint_percentage;
bool strict_layer_property_change_checking;
- bool use_one_copy;
bool use_zero_copy;
bool use_persistent_map_for_gpu_memory_buffers;
bool enable_elastic_overscroll;
- unsigned use_image_texture_target;
+ // An array of image texture targets for each GpuMemoryBuffer format.
+ std::vector<unsigned> use_image_texture_targets;
bool ignore_root_layer_flings;
size_t scheduled_raster_task_limit;
bool use_occlusion_for_tile_prioritization;
bool record_full_layer;
- bool use_display_lists;
bool verify_property_trees;
- bool gather_pixel_refs;
+ bool image_decode_tasks_enabled;
bool use_compositor_animation_timelines;
- bool invert_viewport_scroll_order;
+ bool wait_for_beginframe_interval;
+ int max_staging_buffer_usage_in_bytes;
LayerTreeDebugState initial_debug_state;
diff --git a/chromium/cc/trees/mutator_host_client.h b/chromium/cc/trees/mutator_host_client.h
index 56123b4a62a..93f8f1334d8 100644
--- a/chromium/cc/trees/mutator_host_client.h
+++ b/chromium/cc/trees/mutator_host_client.h
@@ -36,6 +36,11 @@ class MutatorHostClient {
LayerTreeType tree_type,
const gfx::ScrollOffset& scroll_offset) = 0;
+ virtual void LayerTransformIsPotentiallyAnimatingChanged(
+ int layer_id,
+ LayerTreeType tree_type,
+ bool is_animating) = 0;
+
virtual void ScrollOffsetAnimationFinished() = 0;
virtual gfx::ScrollOffset GetScrollOffsetForAnimation(int layer_id) const = 0;
};
diff --git a/chromium/cc/trees/occlusion.cc b/chromium/cc/trees/occlusion.cc
index 6a714962747..e86a1a05e32 100644
--- a/chromium/cc/trees/occlusion.cc
+++ b/chromium/cc/trees/occlusion.cc
@@ -58,7 +58,10 @@ gfx::Rect Occlusion::GetUnoccludedContentRect(
gfx::Transform inverse_draw_transform(gfx::Transform::kSkipInitialization);
bool ok = draw_transform_.GetInverse(&inverse_draw_transform);
- DCHECK(ok);
+ // TODO(ajuma): Skip drawing layers with uninvertible draw transforms, and
+ // change this to a DCHECK. crbug.com/517170
+ if (!ok)
+ return content_rect;
gfx::Rect unoccluded_rect = MathUtil::ProjectEnclosingClippedRect(
inverse_draw_transform, unoccluded_rect_in_target_surface);
diff --git a/chromium/cc/trees/occlusion_tracker.cc b/chromium/cc/trees/occlusion_tracker.cc
index 996adc895af..b86f8547db8 100644
--- a/chromium/cc/trees/occlusion_tracker.cc
+++ b/chromium/cc/trees/occlusion_tracker.cc
@@ -10,7 +10,6 @@
#include "cc/base/region.h"
#include "cc/layers/layer.h"
#include "cc/layers/layer_impl.h"
-#include "cc/layers/render_surface.h"
#include "cc/layers/render_surface_impl.h"
#include "ui/gfx/geometry/quad_f.h"
#include "ui/gfx/geometry/rect_conversions.h"
diff --git a/chromium/cc/trees/occlusion_tracker_perftest.cc b/chromium/cc/trees/occlusion_tracker_perftest.cc
index 209399dce11..01b63de6279 100644
--- a/chromium/cc/trees/occlusion_tracker_perftest.cc
+++ b/chromium/cc/trees/occlusion_tracker_perftest.cc
@@ -35,13 +35,14 @@ class OcclusionTrackerPerfTest : public testing::Test {
base::TimeDelta::FromMilliseconds(kTimeLimitMillis),
kTimeCheckInterval),
proxy_(base::ThreadTaskRunnerHandle::Get(), nullptr),
- impl_(&proxy_) {}
+ impl_(&proxy_),
+ output_surface_(FakeOutputSurface::Create3d()) {}
void CreateHost() {
LayerTreeSettings settings;
host_impl_ = LayerTreeHostImpl::Create(settings, &client_, &proxy_, &stats_,
&shared_bitmap_manager_, nullptr,
&task_graph_runner_, 1);
- host_impl_->InitializeRenderer(FakeOutputSurface::Create3d());
+ host_impl_->InitializeRenderer(output_surface_.get());
scoped_ptr<LayerImpl> root_layer = LayerImpl::Create(active_tree(), 1);
root_layer->SetHasRenderSurface(true);
@@ -71,6 +72,7 @@ class OcclusionTrackerPerfTest : public testing::Test {
FakeRenderingStatsInstrumentation stats_;
TestSharedBitmapManager shared_bitmap_manager_;
TestTaskGraphRunner task_graph_runner_;
+ scoped_ptr<OutputSurface> output_surface_;
scoped_ptr<LayerTreeHostImpl> host_impl_;
};
diff --git a/chromium/cc/trees/occlusion_tracker_unittest.cc b/chromium/cc/trees/occlusion_tracker_unittest.cc
index 08cfcf7290e..88779d018c3 100644
--- a/chromium/cc/trees/occlusion_tracker_unittest.cc
+++ b/chromium/cc/trees/occlusion_tracker_unittest.cc
@@ -195,7 +195,6 @@ class OcclusionTrackerTest : public testing::Test {
void DestroyLayers() {
root_ = nullptr;
- render_surface_layer_list_ = nullptr;
render_surface_layer_list_impl_.clear();
replica_layers_.clear();
mask_layers_.clear();
@@ -310,7 +309,6 @@ class OcclusionTrackerTest : public testing::Test {
scoped_ptr<FakeLayerTreeHost> host_;
// These hold ownership of the layers for the duration of the test.
scoped_ptr<LayerImpl> root_;
- scoped_ptr<RenderSurfaceLayerList> render_surface_layer_list_;
LayerImplList render_surface_layer_list_impl_;
LayerIterator layer_iterator_begin_;
LayerIterator layer_iterator_;
diff --git a/chromium/cc/trees/property_tree.cc b/chromium/cc/trees/property_tree.cc
index 05fa3947f0c..d45d065279c 100644
--- a/chromium/cc/trees/property_tree.cc
+++ b/chromium/cc/trees/property_tree.cc
@@ -23,8 +23,7 @@ template <typename T>
PropertyTree<T>::~PropertyTree() {
}
-TransformTree::TransformTree() : source_to_parent_updates_allowed_(true) {
-}
+TransformTree::TransformTree() : source_to_parent_updates_allowed_(true) {}
TransformTree::~TransformTree() {
}
@@ -49,7 +48,7 @@ void PropertyTree<T>::clear() {
template class PropertyTree<TransformNode>;
template class PropertyTree<ClipNode>;
-template class PropertyTree<OpacityNode>;
+template class PropertyTree<EffectNode>;
TransformNodeData::TransformNodeData()
: target_id(-1),
@@ -60,6 +59,8 @@ TransformNodeData::TransformNodeData()
ancestors_are_invertible(true),
is_animated(false),
to_screen_is_animated(false),
+ has_only_translation_animations(true),
+ to_screen_has_scale_animation(false),
flattens_inherited_transform(false),
node_and_ancestors_are_flat(true),
node_and_ancestors_have_only_integer_translation(true),
@@ -70,8 +71,11 @@ TransformNodeData::TransformNodeData()
affected_by_outer_viewport_bounds_delta_x(false),
affected_by_outer_viewport_bounds_delta_y(false),
layer_scale_factor(1.0f),
- post_local_scale_factor(1.0f) {
-}
+ post_local_scale_factor(1.0f),
+ local_maximum_animation_target_scale(0.f),
+ local_starting_animation_scale(0.f),
+ combined_maximum_animation_target_scale(0.f),
+ combined_starting_animation_scale(0.f) {}
TransformNodeData::~TransformNodeData() {
}
@@ -94,11 +98,21 @@ void TransformNodeData::update_post_local_transform(
transform_origin.z());
}
-ClipNodeData::ClipNodeData() : transform_id(-1), target_id(-1) {
-}
+ClipNodeData::ClipNodeData()
+ : transform_id(-1),
+ target_id(-1),
+ use_only_parent_clip(false),
+ layer_clipping_uses_only_local_clip(false),
+ layer_visibility_uses_only_local_clip(false),
+ render_surface_is_clipped(false),
+ layers_are_clipped(false) {}
-OpacityNodeData::OpacityNodeData() : opacity(1.f), screen_space_opacity(1.f) {
-}
+EffectNodeData::EffectNodeData()
+ : opacity(1.f),
+ screen_space_opacity(1.f),
+ has_render_surface(false),
+ transform_id(0),
+ clip_id(0) {}
void TransformTree::clear() {
PropertyTree<TransformNode>::clear();
@@ -147,6 +161,10 @@ bool TransformTree::ComputeTransformWithSourceSublayerScale(
if (!source_node->data.needs_sublayer_scale)
return success;
+ if (source_node->data.sublayer_scale.x() == 0 ||
+ source_node->data.sublayer_scale.y() == 0)
+ return false;
+
transform->Scale(1.f / source_node->data.sublayer_scale.x(),
1.f / source_node->data.sublayer_scale.y());
return success;
@@ -170,10 +188,12 @@ void TransformTree::UpdateTransforms(int id) {
if (node->data.needs_local_transform_update ||
NeedsSourceToParentUpdate(node))
UpdateLocalTransform(node);
+ else
+ UndoSnapping(node);
UpdateScreenSpaceTransform(node, parent_node, target_node);
UpdateSublayerScale(node);
UpdateTargetSpaceTransform(node, target_node);
- UpdateIsAnimated(node, parent_node);
+ UpdateAnimationProperties(node, parent_node);
UpdateSnapping(node);
UpdateNodeAndAncestorsHaveIntegerTranslations(node, parent_node);
}
@@ -380,10 +400,9 @@ void TransformTree::UpdateTargetSpaceTransform(TransformNode* node,
node->data.to_target.Scale(node->data.sublayer_scale.x(),
node->data.sublayer_scale.y());
} else {
- const bool target_is_root_surface = target_node->id == 1;
// In order to include the root transform for the root surface, we walk up
// to the root of the transform tree in ComputeTransform.
- int target_id = target_is_root_surface ? 0 : target_node->id;
+ int target_id = target_node->id;
ComputeTransformWithDestinationSublayerScale(node->id, target_id,
&node->data.to_target);
}
@@ -392,12 +411,101 @@ void TransformTree::UpdateTargetSpaceTransform(TransformNode* node,
node->data.ancestors_are_invertible = false;
}
-void TransformTree::UpdateIsAnimated(TransformNode* node,
- TransformNode* parent_node) {
+void TransformTree::UpdateAnimationProperties(TransformNode* node,
+ TransformNode* parent_node) {
+ bool ancestor_is_animating = false;
+ bool ancestor_is_animating_scale = false;
+ float ancestor_maximum_target_scale = 0.f;
+ float ancestor_starting_animation_scale = 0.f;
if (parent_node) {
- node->data.to_screen_is_animated =
- node->data.is_animated || parent_node->data.to_screen_is_animated;
+ ancestor_is_animating = parent_node->data.to_screen_is_animated;
+ ancestor_is_animating_scale =
+ parent_node->data.to_screen_has_scale_animation;
+ ancestor_maximum_target_scale =
+ parent_node->data.combined_maximum_animation_target_scale;
+ ancestor_starting_animation_scale =
+ parent_node->data.combined_starting_animation_scale;
+ }
+ node->data.to_screen_is_animated =
+ node->data.is_animated || ancestor_is_animating;
+ node->data.to_screen_has_scale_animation =
+ !node->data.has_only_translation_animations ||
+ ancestor_is_animating_scale;
+
+ // Once we've failed to compute a maximum animated scale at an ancestor, we
+ // continue to fail.
+ bool failed_at_ancestor =
+ ancestor_is_animating_scale && ancestor_maximum_target_scale == 0.f;
+
+ // Computing maximum animated scale in the presence of non-scale/translation
+ // transforms isn't supported.
+ bool failed_for_non_scale_or_translation =
+ !node->data.to_target.IsScaleOrTranslation();
+
+ // We don't attempt to accumulate animation scale from multiple nodes with
+ // scale animations, because of the risk of significant overestimation. For
+ // example, one node might be increasing scale from 1 to 10 at the same time
+ // as another node is decreasing scale from 10 to 1. Naively combining these
+ // scales would produce a scale of 100.
+ bool failed_for_multiple_scale_animations =
+ ancestor_is_animating_scale &&
+ !node->data.has_only_translation_animations;
+
+ if (failed_at_ancestor || failed_for_non_scale_or_translation ||
+ failed_for_multiple_scale_animations) {
+ node->data.combined_maximum_animation_target_scale = 0.f;
+ node->data.combined_starting_animation_scale = 0.f;
+
+ // This ensures that descendants know we've failed to compute a maximum
+ // animated scale.
+ node->data.to_screen_has_scale_animation = true;
+ return;
+ }
+
+ if (!node->data.to_screen_has_scale_animation) {
+ node->data.combined_maximum_animation_target_scale = 0.f;
+ node->data.combined_starting_animation_scale = 0.f;
+ return;
+ }
+
+ // At this point, we know exactly one of this node or an ancestor is animating
+ // scale.
+ if (node->data.has_only_translation_animations) {
+ // An ancestor is animating scale.
+ gfx::Vector2dF local_scales =
+ MathUtil::ComputeTransform2dScaleComponents(node->data.local, 0.f);
+ float max_local_scale = std::max(local_scales.x(), local_scales.y());
+ node->data.combined_maximum_animation_target_scale =
+ max_local_scale * ancestor_maximum_target_scale;
+ node->data.combined_starting_animation_scale =
+ max_local_scale * ancestor_starting_animation_scale;
+ return;
}
+
+ if (node->data.local_starting_animation_scale == 0.f ||
+ node->data.local_maximum_animation_target_scale == 0.f) {
+ node->data.combined_maximum_animation_target_scale = 0.f;
+ node->data.combined_starting_animation_scale = 0.f;
+ return;
+ }
+
+ gfx::Vector2dF ancestor_scales =
+ parent_node ? MathUtil::ComputeTransform2dScaleComponents(
+ parent_node->data.to_target, 0.f)
+ : gfx::Vector2dF(1.f, 1.f);
+ float max_ancestor_scale = std::max(ancestor_scales.x(), ancestor_scales.y());
+ node->data.combined_maximum_animation_target_scale =
+ max_ancestor_scale * node->data.local_maximum_animation_target_scale;
+ node->data.combined_starting_animation_scale =
+ max_ancestor_scale * node->data.local_starting_animation_scale;
+}
+
+void TransformTree::UndoSnapping(TransformNode* node) {
+ // to_parent transform has the scroll snap from previous frame baked in.
+ // We need to undo it and use the un-snapped transform to compute current
+ // target and screen space transforms.
+ node->data.to_parent.Translate(-node->data.scroll_snap.x(),
+ -node->data.scroll_snap.y());
}
void TransformTree::UpdateSnapping(TransformNode* node) {
@@ -424,8 +532,8 @@ void TransformTree::UpdateSnapping(TransformNode* node) {
// Now that we have our scroll delta, we must apply it to each of our
// combined, to/from matrices.
+ node->data.to_target = rounded;
node->data.to_parent.Translate(translation.x(), translation.y());
- node->data.to_target.Translate(translation.x(), translation.y());
node->data.from_target.matrix().postTranslate(-translation.x(),
-translation.y(), 0);
node->data.to_screen.Translate(translation.x(), translation.y());
@@ -479,11 +587,11 @@ bool TransformTree::HasNodesAffectedByOuterViewportBoundsDelta() const {
return !nodes_affected_by_outer_viewport_bounds_delta_.empty();
}
-void OpacityTree::UpdateOpacities(int id) {
- OpacityNode* node = Node(id);
+void EffectTree::UpdateOpacities(int id) {
+ EffectNode* node = Node(id);
node->data.screen_space_opacity = node->data.opacity;
- OpacityNode* parent_node = parent(node);
+ EffectNode* parent_node = parent(node);
if (parent_node)
node->data.screen_space_opacity *= parent_node->data.screen_space_opacity;
}
@@ -499,6 +607,22 @@ void TransformTree::UpdateNodeAndAncestorsHaveIntegerTranslations(
parent_node->data.node_and_ancestors_have_only_integer_translation;
}
+void ClipTree::SetViewportClip(gfx::RectF viewport_rect) {
+ if (size() < 2)
+ return;
+ ClipNode* node = Node(1);
+ if (viewport_rect == node->data.clip)
+ return;
+ node->data.clip = viewport_rect;
+ set_needs_update(true);
+}
+
+gfx::RectF ClipTree::ViewportClip() {
+ const unsigned long min_size = 1;
+ DCHECK_GT(size(), min_size);
+ return Node(1)->data.clip;
+}
+
PropertyTrees::PropertyTrees() : needs_rebuild(true), sequence_number(0) {
}
diff --git a/chromium/cc/trees/property_tree.h b/chromium/cc/trees/property_tree.h
index 0ec77bc5bbe..49d159e2a5d 100644
--- a/chromium/cc/trees/property_tree.h
+++ b/chromium/cc/trees/property_tree.h
@@ -9,7 +9,7 @@
#include "base/basictypes.h"
#include "cc/base/cc_export.h"
-#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/geometry/scroll_offset.h"
#include "ui/gfx/transform.h"
@@ -75,6 +75,8 @@ struct CC_EXPORT TransformNodeData {
bool is_animated : 1;
bool to_screen_is_animated : 1;
+ bool has_only_translation_animations : 1;
+ bool to_screen_has_scale_animation : 1;
// Flattening, when needed, is only applied to a node's inherited transform,
// never to its local transform.
@@ -105,6 +107,24 @@ struct CC_EXPORT TransformNodeData {
// TODO(vollick): will be moved when accelerated effects are implemented.
float post_local_scale_factor;
+ // The maximum scale that that node's |local| transform will have during
+ // current animations, considering only scales at keyframes not including the
+ // starting keyframe of each animation.
+ float local_maximum_animation_target_scale;
+
+ // The maximum scale that this node's |local| transform will have during
+ // current animatons, considering only the starting scale of each animation.
+ float local_starting_animation_scale;
+
+ // The maximum scale that this node's |to_target| transform will have during
+ // current animations, considering only scales at keyframes not incuding the
+ // starting keyframe of each animation.
+ float combined_maximum_animation_target_scale;
+
+ // The maximum scale that this node's |to_target| transform will have during
+ // current animations, considering only the starting scale of each animation.
+ float combined_starting_animation_scale;
+
gfx::Vector2dF sublayer_scale;
// TODO(vollick): will be moved when accelerated effects are implemented.
@@ -136,21 +156,31 @@ struct CC_EXPORT ClipNodeData {
ClipNodeData();
gfx::RectF clip;
- gfx::RectF combined_clip;
+ gfx::RectF combined_clip_in_target_space;
+ gfx::RectF clip_in_target_space;
int transform_id;
int target_id;
+ bool use_only_parent_clip : 1;
+ bool layer_clipping_uses_only_local_clip : 1;
+ bool layer_visibility_uses_only_local_clip : 1;
+ bool render_surface_is_clipped : 1;
+ bool layers_are_clipped : 1;
};
typedef TreeNode<ClipNodeData> ClipNode;
-struct CC_EXPORT OpacityNodeData {
- OpacityNodeData();
+struct CC_EXPORT EffectNodeData {
+ EffectNodeData();
float opacity;
float screen_space_opacity;
+
+ bool has_render_surface;
+ int transform_id;
+ int clip_id;
};
-typedef TreeNode<OpacityNodeData> OpacityNode;
+typedef TreeNode<EffectNodeData> EffectNode;
template <typename T>
class CC_EXPORT PropertyTree {
@@ -185,6 +215,8 @@ class CC_EXPORT PropertyTree {
void set_needs_update(bool needs_update) { needs_update_ = needs_update; }
bool needs_update() const { return needs_update_; }
+ int next_available_id() const { return static_cast<int>(size()); }
+
private:
// Copy and assign are permitted. This is how we do tree sync.
std::vector<T> nodes_;
@@ -293,7 +325,9 @@ class CC_EXPORT TransformTree final : public PropertyTree<TransformNode> {
void UpdateSublayerScale(TransformNode* node);
void UpdateTargetSpaceTransform(TransformNode* node,
TransformNode* target_node);
- void UpdateIsAnimated(TransformNode* node, TransformNode* parent_node);
+ void UpdateAnimationProperties(TransformNode* node,
+ TransformNode* parent_node);
+ void UndoSnapping(TransformNode* node);
void UpdateSnapping(TransformNode* node);
void UpdateNodeAndAncestorsHaveIntegerTranslations(
TransformNode* node,
@@ -307,9 +341,13 @@ class CC_EXPORT TransformTree final : public PropertyTree<TransformNode> {
std::vector<int> nodes_affected_by_outer_viewport_bounds_delta_;
};
-class CC_EXPORT ClipTree final : public PropertyTree<ClipNode> {};
+class CC_EXPORT ClipTree final : public PropertyTree<ClipNode> {
+ public:
+ void SetViewportClip(gfx::RectF viewport_rect);
+ gfx::RectF ViewportClip();
+};
-class CC_EXPORT OpacityTree final : public PropertyTree<OpacityNode> {
+class CC_EXPORT EffectTree final : public PropertyTree<EffectNode> {
public:
void UpdateOpacities(int id);
};
@@ -319,7 +357,7 @@ class CC_EXPORT PropertyTrees final {
PropertyTrees();
TransformTree transform_tree;
- OpacityTree opacity_tree;
+ EffectTree effect_tree;
ClipTree clip_tree;
bool needs_rebuild;
int sequence_number;
diff --git a/chromium/cc/trees/property_tree_builder.cc b/chromium/cc/trees/property_tree_builder.cc
index 28ad43f3091..a5e209c7303 100644
--- a/chromium/cc/trees/property_tree_builder.cc
+++ b/chromium/cc/trees/property_tree_builder.cc
@@ -20,16 +20,20 @@ class LayerTreeHost;
namespace {
+static const int kInvalidPropertyTreeNodeId = -1;
+static const int kRootPropertyTreeNodeId = 0;
+static const int kUnclippedRootClipTreeNodeId = 0;
+
template <typename LayerType>
struct DataForRecursion {
TransformTree* transform_tree;
ClipTree* clip_tree;
- OpacityTree* opacity_tree;
+ EffectTree* effect_tree;
LayerType* transform_tree_parent;
LayerType* transform_fixed_parent;
- LayerType* render_target;
+ int render_target;
int clip_tree_parent;
- int opacity_tree_parent;
+ int effect_tree_parent;
const LayerType* page_scale_layer;
const LayerType* inner_viewport_scroll_layer;
const LayerType* outer_viewport_scroll_layer;
@@ -39,7 +43,6 @@ struct DataForRecursion {
bool affected_by_inner_viewport_bounds_delta;
bool affected_by_outer_viewport_bounds_delta;
bool should_flatten;
- bool ancestor_clips_subtree;
const gfx::Transform* device_transform;
gfx::Vector2dF scroll_compensation_adjustment;
int sequence_number;
@@ -68,9 +71,9 @@ static bool RequiresClipNode(LayerType* layer,
int parent_transform_id,
bool is_clipped) {
const bool render_surface_applies_clip =
- layer->render_surface() && is_clipped;
+ layer->has_render_surface() && is_clipped;
const bool render_surface_may_grow_due_to_clip_children =
- layer->render_surface() && layer->num_unclipped_descendants() > 0;
+ layer->has_render_surface() && layer->num_unclipped_descendants() > 0;
if (layer->masks_to_bounds() || layer->mask_layer() ||
render_surface_may_grow_due_to_clip_children)
@@ -79,11 +82,7 @@ static bool RequiresClipNode(LayerType* layer,
if (!render_surface_applies_clip)
return false;
- bool axis_aligned_with_respect_to_parent =
- data.transform_tree->Are2DAxisAligned(layer->transform_tree_index(),
- parent_transform_id);
-
- return !axis_aligned_with_respect_to_parent;
+ return true;
}
template <typename LayerType>
@@ -94,36 +93,42 @@ static bool LayerClipsSubtree(LayerType* layer) {
template <typename LayerType>
void AddClipNodeIfNeeded(const DataForRecursion<LayerType>& data_from_ancestor,
LayerType* layer,
+ bool created_render_surface,
bool created_transform_node,
DataForRecursion<LayerType>* data_for_children) {
ClipNode* parent = GetClipParent(data_from_ancestor, layer);
int parent_id = parent->id;
- bool ancestor_clips_subtree =
- data_from_ancestor.ancestor_clips_subtree || layer->clip_parent();
+ bool is_root = !layer->parent();
+ bool ancestor_clips_subtree = is_root || parent->data.layers_are_clipped;
- data_for_children->ancestor_clips_subtree = false;
+ bool layers_are_clipped = false;
bool has_unclipped_surface = false;
if (layer->has_render_surface()) {
if (ancestor_clips_subtree && layer->num_unclipped_descendants() > 0)
- data_for_children->ancestor_clips_subtree = true;
- else if (!ancestor_clips_subtree && !layer->num_unclipped_descendants())
+ layers_are_clipped = true;
+ else if (!ancestor_clips_subtree)
has_unclipped_surface = true;
} else {
- data_for_children->ancestor_clips_subtree = ancestor_clips_subtree;
+ layers_are_clipped = ancestor_clips_subtree;
}
- if (LayerClipsSubtree(layer))
- data_for_children->ancestor_clips_subtree = true;
-
- if (has_unclipped_surface)
- parent_id = 0;
+ bool layer_clips_subtree = LayerClipsSubtree(layer);
+ if (layer_clips_subtree)
+ layers_are_clipped = true;
+ if (has_unclipped_surface) {
+ parent_id = kUnclippedRootClipTreeNodeId;
+ data_for_children->effect_tree->Node(data_for_children->render_target)
+ ->data.clip_id = kUnclippedRootClipTreeNodeId;
+ }
if (!RequiresClipNode(layer, data_from_ancestor, parent->data.transform_id,
- data_for_children->ancestor_clips_subtree)) {
+ ancestor_clips_subtree)) {
// Unclipped surfaces reset the clip rect.
data_for_children->clip_tree_parent = parent_id;
+ DCHECK_EQ(layers_are_clipped, data_for_children->clip_tree->Node(parent_id)
+ ->data.layers_are_clipped);
} else {
LayerType* transform_parent = data_for_children->transform_tree_parent;
if (layer->position_constraint().is_fixed_position() &&
@@ -131,19 +136,48 @@ void AddClipNodeIfNeeded(const DataForRecursion<LayerType>& data_from_ancestor,
transform_parent = data_for_children->transform_fixed_parent;
}
ClipNode node;
- node.data.clip = gfx::RectF(
- gfx::PointF() + layer->offset_to_transform_parent(), layer->bounds());
+ node.data.clip =
+ gfx::RectF(gfx::PointF() + layer->offset_to_transform_parent(),
+ gfx::SizeF(layer->bounds()));
node.data.transform_id = transform_parent->transform_tree_index();
- node.data.target_id =
- data_for_children->render_target->transform_tree_index();
+ if (layer->has_render_surface()) {
+ node.data.target_id =
+ data_from_ancestor.effect_tree->Node(data_for_children->render_target)
+ ->data.transform_id;
+ } else {
+ node.data.target_id =
+ data_for_children->effect_tree->Node(data_for_children->render_target)
+ ->data.transform_id;
+ }
node.owner_id = layer->id();
+ if (ancestor_clips_subtree) {
+ node.data.use_only_parent_clip = !layer_clips_subtree;
+ // If the layer has render surface, the target has changed and so we use
+ // only the local clip for layer clipping.
+ node.data.layer_clipping_uses_only_local_clip =
+ layer->has_render_surface();
+ } else {
+ node.data.use_only_parent_clip = false;
+ node.data.layer_clipping_uses_only_local_clip = true;
+ }
+
+ // If render surface clips subtree and has unclipped descendants, the
+ // surface isn't clipped and we don't want to use ancestor's clips while
+ // calculating visible rect.
+ node.data.layer_visibility_uses_only_local_clip =
+ layer->has_render_surface() && layer->num_unclipped_descendants() &&
+ layer_clips_subtree;
+ node.data.render_surface_is_clipped = layer->has_render_surface() &&
+ ancestor_clips_subtree &&
+ !layer->num_unclipped_descendants();
+ node.data.layers_are_clipped = layers_are_clipped;
+
data_for_children->clip_tree_parent =
data_for_children->clip_tree->Insert(node, parent_id);
}
- layer->SetClipTreeIndex(
- has_unclipped_surface ? 0 : data_for_children->clip_tree_parent);
+ layer->SetClipTreeIndex(data_for_children->clip_tree_parent);
// TODO(awoloszyn): Right now when we hit a node with a replica, we reset the
// clip for all children since we may need to draw. We need to figure out a
@@ -154,6 +188,7 @@ template <typename LayerType>
bool AddTransformNodeIfNeeded(
const DataForRecursion<LayerType>& data_from_ancestor,
LayerType* layer,
+ bool created_render_surface,
DataForRecursion<LayerType>* data_for_children) {
const bool is_root = !layer->parent();
const bool is_page_scale_layer = layer == data_from_ancestor.page_scale_layer;
@@ -165,18 +200,24 @@ bool AddTransformNodeIfNeeded(
const bool has_potentially_animated_transform =
layer->HasPotentiallyRunningTransformAnimation();
- const bool has_animated_transform = layer->TransformIsAnimating();
- const bool has_surface = !!layer->render_surface();
+ // A transform node is needed even for a finished animation, since differences
+ // in the timing of animation state updates can mean that an animation that's
+ // in the Finished state at tree-building time on the main thread is still in
+ // the Running state right after commit on the compositor thread.
+ const bool has_any_transform_animation =
+ layer->HasAnyAnimationTargetingProperty(Animation::TRANSFORM);
+
+ const bool has_surface = layer->has_render_surface();
bool requires_node = is_root || is_scrollable || has_significant_transform ||
- has_potentially_animated_transform || has_surface ||
- is_fixed || is_page_scale_layer;
+ has_any_transform_animation || has_surface || is_fixed ||
+ is_page_scale_layer;
LayerType* transform_parent = GetTransformParent(data_from_ancestor, layer);
DCHECK_IMPLIES(!is_root, transform_parent);
- int parent_index = 0;
+ int parent_index = kRootPropertyTreeNodeId;
if (transform_parent)
parent_index = transform_parent->transform_tree_index();
@@ -247,12 +288,32 @@ bool AddTransformNodeIfNeeded(
// Surfaces inherently flatten transforms.
data_for_children->should_flatten =
layer->should_flatten_transform() || has_surface;
+ DCHECK_GT(data_from_ancestor.effect_tree->size(), 0u);
+
node->data.target_id =
- data_from_ancestor.render_target->transform_tree_index();
+ data_for_children->effect_tree->Node(data_from_ancestor.render_target)
+ ->data.transform_id;
node->data.content_target_id =
- data_for_children->render_target->transform_tree_index();
- DCHECK_NE(node->data.target_id, -1);
- node->data.is_animated = has_animated_transform;
+ data_for_children->effect_tree->Node(data_for_children->render_target)
+ ->data.transform_id;
+ DCHECK_NE(node->data.target_id, kInvalidPropertyTreeNodeId);
+
+ node->data.is_animated = has_potentially_animated_transform;
+ if (has_potentially_animated_transform) {
+ float maximum_animation_target_scale = 0.f;
+ if (layer->MaximumTargetScale(&maximum_animation_target_scale)) {
+ node->data.local_maximum_animation_target_scale =
+ maximum_animation_target_scale;
+ }
+
+ float starting_animation_scale = 0.f;
+ if (layer->AnimationStartScale(&starting_animation_scale)) {
+ node->data.local_starting_animation_scale = starting_animation_scale;
+ }
+
+ node->data.has_only_translation_animations =
+ layer->HasOnlyTranslationTransforms();
+ }
float post_local_scale_factor = 1.0f;
if (is_root) {
@@ -339,34 +400,53 @@ bool IsAnimatingOpacity(LayerImpl* layer) {
}
template <typename LayerType>
-void AddOpacityNodeIfNeeded(
+bool AddEffectNodeIfNeeded(
const DataForRecursion<LayerType>& data_from_ancestor,
LayerType* layer,
DataForRecursion<LayerType>* data_for_children) {
const bool is_root = !layer->parent();
const bool has_transparency = layer->opacity() != 1.f;
const bool has_animated_opacity = IsAnimatingOpacity(layer);
- bool requires_node = is_root || has_transparency || has_animated_opacity;
+ const bool has_render_surface = layer->has_render_surface();
+ bool requires_node =
+ is_root || has_transparency || has_animated_opacity || has_render_surface;
- int parent_id = data_from_ancestor.opacity_tree_parent;
+ int parent_id = data_from_ancestor.effect_tree_parent;
if (!requires_node) {
- layer->SetOpacityTreeIndex(parent_id);
- data_for_children->opacity_tree_parent = parent_id;
- return;
+ layer->SetEffectTreeIndex(parent_id);
+ data_for_children->effect_tree_parent = parent_id;
+ return false;
}
- OpacityNode node;
+ EffectNode node;
node.owner_id = layer->id();
node.data.opacity = layer->opacity();
node.data.screen_space_opacity = layer->opacity();
- if (!is_root)
+ node.data.has_render_surface = has_render_surface;
+ if (!is_root) {
+ // For every effect node, we create a transform node, so it's safe to use
+ // the next available id from the transform tree as this effect node's
+ // transform id.
+ node.data.transform_id =
+ data_from_ancestor.transform_tree->next_available_id();
+ node.data.clip_id = data_from_ancestor.clip_tree_parent;
+
node.data.screen_space_opacity *=
- data_from_ancestor.opacity_tree->Node(parent_id)
+ data_from_ancestor.effect_tree->Node(parent_id)
->data.screen_space_opacity;
- data_for_children->opacity_tree_parent =
- data_for_children->opacity_tree->Insert(node, parent_id);
- layer->SetOpacityTreeIndex(data_for_children->opacity_tree_parent);
+ } else {
+ // Root render surface acts the unbounded and untransformed to draw content
+ // into. Transform node created from root layer (includes device scale
+ // factor) and clip node created from root layer (include viewports) applies
+ // to root render surface's content, but not root render surface itself.
+ node.data.transform_id = kRootPropertyTreeNodeId;
+ node.data.clip_id = kUnclippedRootClipTreeNodeId;
+ }
+ data_for_children->effect_tree_parent =
+ data_for_children->effect_tree->Insert(node, parent_id);
+ layer->SetEffectTreeIndex(data_for_children->effect_tree_parent);
+ return has_render_surface;
}
template <typename LayerType>
@@ -375,16 +455,21 @@ void BuildPropertyTreesInternal(
const DataForRecursion<LayerType>& data_from_parent) {
layer->set_property_tree_sequence_number(data_from_parent.sequence_number);
DataForRecursion<LayerType> data_for_children(data_from_parent);
- if (layer->render_surface())
- data_for_children.render_target = layer;
- bool created_transform_node =
- AddTransformNodeIfNeeded(data_from_parent, layer, &data_for_children);
- AddClipNodeIfNeeded(data_from_parent, layer, created_transform_node,
- &data_for_children);
+ bool created_render_surface =
+ AddEffectNodeIfNeeded(data_from_parent, layer, &data_for_children);
+
+ if (created_render_surface) {
+ data_for_children.render_target = data_for_children.effect_tree_parent;
+ layer->set_draw_blend_mode(SkXfermode::kSrcOver_Mode);
+ } else {
+ layer->set_draw_blend_mode(layer->blend_mode());
+ }
- if (data_from_parent.opacity_tree)
- AddOpacityNodeIfNeeded(data_from_parent, layer, &data_for_children);
+ bool created_transform_node = AddTransformNodeIfNeeded(
+ data_from_parent, layer, created_render_surface, &data_for_children);
+ AddClipNodeIfNeeded(data_from_parent, layer, created_render_surface,
+ created_transform_node, &data_for_children);
if (layer == data_from_parent.page_scale_layer)
data_for_children.in_subtree_of_page_scale_layer = true;
@@ -432,12 +517,12 @@ void BuildPropertyTreesTopLevelInternal(
DataForRecursion<LayerType> data_for_recursion;
data_for_recursion.transform_tree = &property_trees->transform_tree;
data_for_recursion.clip_tree = &property_trees->clip_tree;
- data_for_recursion.opacity_tree = &property_trees->opacity_tree;
+ data_for_recursion.effect_tree = &property_trees->effect_tree;
data_for_recursion.transform_tree_parent = nullptr;
data_for_recursion.transform_fixed_parent = nullptr;
- data_for_recursion.render_target = root_layer;
- data_for_recursion.clip_tree_parent = 0;
- data_for_recursion.opacity_tree_parent = -1;
+ data_for_recursion.render_target = kRootPropertyTreeNodeId;
+ data_for_recursion.clip_tree_parent = kUnclippedRootClipTreeNodeId;
+ data_for_recursion.effect_tree_parent = kInvalidPropertyTreeNodeId;
data_for_recursion.page_scale_layer = page_scale_layer;
data_for_recursion.inner_viewport_scroll_layer = inner_viewport_scroll_layer;
data_for_recursion.outer_viewport_scroll_layer = outer_viewport_scroll_layer;
@@ -447,19 +532,18 @@ void BuildPropertyTreesTopLevelInternal(
data_for_recursion.affected_by_inner_viewport_bounds_delta = false;
data_for_recursion.affected_by_outer_viewport_bounds_delta = false;
data_for_recursion.should_flatten = false;
- data_for_recursion.ancestor_clips_subtree = true;
data_for_recursion.device_transform = &device_transform;
data_for_recursion.transform_tree->clear();
data_for_recursion.clip_tree->clear();
- data_for_recursion.opacity_tree->clear();
+ data_for_recursion.effect_tree->clear();
data_for_recursion.sequence_number = property_trees->sequence_number;
ClipNode root_clip;
- root_clip.data.clip = viewport;
- root_clip.data.transform_id = 0;
- data_for_recursion.clip_tree_parent =
- data_for_recursion.clip_tree->Insert(root_clip, 0);
+ root_clip.data.clip = gfx::RectF(viewport);
+ root_clip.data.transform_id = kRootPropertyTreeNodeId;
+ data_for_recursion.clip_tree_parent = data_for_recursion.clip_tree->Insert(
+ root_clip, kUnclippedRootClipTreeNodeId);
BuildPropertyTreesInternal(root_layer, data_for_recursion);
property_trees->needs_rebuild = false;
@@ -468,7 +552,7 @@ void BuildPropertyTreesTopLevelInternal(
// building.
property_trees->transform_tree.set_needs_update(false);
property_trees->clip_tree.set_needs_update(true);
- property_trees->opacity_tree.set_needs_update(false);
+ property_trees->effect_tree.set_needs_update(false);
}
void PropertyTreeBuilder::BuildPropertyTrees(
diff --git a/chromium/cc/trees/property_tree_builder.h b/chromium/cc/trees/property_tree_builder.h
index f877aebe3dd..a6cc52b4c6d 100644
--- a/chromium/cc/trees/property_tree_builder.h
+++ b/chromium/cc/trees/property_tree_builder.h
@@ -16,8 +16,6 @@ class LayerTreeHost;
class PropertyTreeBuilder {
public:
- // Building an opacity tree is optional, and can be skipped by passing
- // in a null |opacity_tree|.
static void BuildPropertyTrees(Layer* root_layer,
const Layer* page_scale_layer,
const Layer* inner_viewport_scroll_layer,
diff --git a/chromium/cc/trees/property_tree_unittest.cc b/chromium/cc/trees/property_tree_unittest.cc
index 8497dca6af1..e72a9ad83a8 100644
--- a/chromium/cc/trees/property_tree_unittest.cc
+++ b/chromium/cc/trees/property_tree_unittest.cc
@@ -529,10 +529,10 @@ TEST(PropertyTreeTest, FlatteningWhenDestinationHasOnlyFlatAncestors) {
TEST(PropertyTreeTest, ScreenSpaceOpacityUpdateTest) {
// This tests that screen space opacity is updated for the subtree when
// opacity of a node changes.
- OpacityTree tree;
+ EffectTree tree;
- int parent = tree.Insert(OpacityNode(), 0);
- int child = tree.Insert(OpacityNode(), parent);
+ int parent = tree.Insert(EffectNode(), 0);
+ int child = tree.Insert(EffectNode(), parent);
EXPECT_EQ(tree.Node(child)->data.screen_space_opacity, 1.f);
tree.Node(parent)->data.opacity = 0.5f;
diff --git a/chromium/cc/trees/proxy.h b/chromium/cc/trees/proxy.h
index d403ae0eb6d..b40bb2f93e4 100644
--- a/chromium/cc/trees/proxy.h
+++ b/chromium/cc/trees/proxy.h
@@ -60,7 +60,9 @@ class CC_EXPORT Proxy {
// Will call LayerTreeHost::OnCreateAndInitializeOutputSurfaceAttempted
// with the result of this function.
- virtual void SetOutputSurface(scoped_ptr<OutputSurface> output_surface) = 0;
+ virtual void SetOutputSurface(OutputSurface* output_surface) = 0;
+
+ virtual void ReleaseOutputSurface() = 0;
// Indicates that the compositing surface associated with our context is
// ready to use.
@@ -93,14 +95,8 @@ class CC_EXPORT Proxy {
virtual void Start() = 0;
virtual void Stop() = 0; // Must be called before deleting the proxy.
- // Forces 3D commands on all contexts to wait for all previous SwapBuffers
- // to finish before executing in the GPU process.
- virtual void ForceSerializeOnSwapBuffers() = 0;
-
virtual bool SupportsImplScrolling() const = 0;
- virtual void SetDebugState(const LayerTreeDebugState& debug_state) = 0;
-
virtual void SetChildrenNeedBeginFrames(bool children_need_begin_frames) = 0;
virtual void SetAuthoritativeVSyncInterval(
diff --git a/chromium/cc/trees/proxy_impl.h b/chromium/cc/trees/proxy_impl.h
new file mode 100644
index 00000000000..3a6c82bd50b
--- /dev/null
+++ b/chromium/cc/trees/proxy_impl.h
@@ -0,0 +1,34 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_TREES_PROXY_IMPL_H_
+#define CC_TREES_PROXY_IMPL_H_
+
+#include "base/memory/weak_ptr.h"
+#include "cc/base/cc_export.h"
+
+namespace cc {
+
+// TODO(khushalsagar): The impl side of ThreadProxy. It is currently defined as
+// an interface with the implementation provided by ThreadProxy and will be
+// made an independent class.
+// The methods added to this interface should only use the CompositorThreadOnly
+// variables from ThreadProxy.
+// See crbug/527200
+class CC_EXPORT ProxyImpl {
+ public:
+ // Callback for impl side commands received from the channel.
+ virtual void SetThrottleFrameProductionOnImpl(bool throttle) = 0;
+ virtual void SetLayerTreeHostClientReadyOnImpl() = 0;
+
+ // TODO(khushalsagar): Rename as GetWeakPtr() once ThreadProxy is split.
+ virtual base::WeakPtr<ProxyImpl> GetImplWeakPtr() = 0;
+
+ protected:
+ virtual ~ProxyImpl() {}
+};
+
+} // namespace cc
+
+#endif // CC_TREES_PROXY_IMPL_H_
diff --git a/chromium/cc/trees/proxy_main.h b/chromium/cc/trees/proxy_main.h
new file mode 100644
index 00000000000..71230b43055
--- /dev/null
+++ b/chromium/cc/trees/proxy_main.h
@@ -0,0 +1,40 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_TREES_PROXY_MAIN_H_
+#define CC_TREES_PROXY_MAIN_H_
+
+#include "base/memory/weak_ptr.h"
+#include "cc/base/cc_export.h"
+
+namespace cc {
+class ThreadedChannel;
+
+// TODO(khushalsagar): The main side of ThreadProxy. It is currently defined as
+// an interface with the implementation provided by ThreadProxy and will be
+// made an independent class.
+// The methods added to this interface should only use the MainThreadOnly or
+// BlockedMainThread variables from ThreadProxy.
+// See crbug/527200.
+class CC_EXPORT ProxyMain {
+ public:
+ // TODO(khushalsagar): Make this ChannelMain*. When ProxyMain and
+ // ProxyImpl are split, ProxyImpl will be passed a reference to ChannelImpl
+ // at creation. Right now we just set it directly from ThreadedChannel
+ // when the impl side is initialized.
+ virtual void SetChannel(scoped_ptr<ThreadedChannel> threaded_channel) = 0;
+
+ // Callback for main side commands received from the Channel.
+ virtual void DidCompleteSwapBuffers() = 0;
+
+ // TODO(khushalsagar): Rename as GetWeakPtr() once ThreadProxy is split.
+ virtual base::WeakPtr<ProxyMain> GetMainWeakPtr() = 0;
+
+ protected:
+ virtual ~ProxyMain() {}
+};
+
+} // namespace cc
+
+#endif // CC_TREES_PROXY_MAIN_H_
diff --git a/chromium/cc/trees/single_thread_proxy.cc b/chromium/cc/trees/single_thread_proxy.cc
index b6d120b4805..49f614c5220 100644
--- a/chromium/cc/trees/single_thread_proxy.cc
+++ b/chromium/cc/trees/single_thread_proxy.cc
@@ -66,6 +66,7 @@ SingleThreadProxy::SingleThreadProxy(
scoped_ptr<CompositorTimingHistory> compositor_timing_history(
new CompositorTimingHistory(
+ CompositorTimingHistory::BROWSER_UMA,
layer_tree_host->rendering_stats_instrumentation()));
scheduler_on_impl_thread_ = Scheduler::Create(
@@ -122,10 +123,11 @@ void SingleThreadProxy::SetLayerTreeHostClientReady() {
void SingleThreadProxy::SetVisible(bool visible) {
TRACE_EVENT1("cc", "SingleThreadProxy::SetVisible", "visible", visible);
DebugScopedSetImplThread impl(this);
+
layer_tree_host_impl_->SetVisible(visible);
+
if (scheduler_on_impl_thread_)
scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible());
- // Changing visibility could change ShouldComposite().
}
void SingleThreadProxy::SetThrottleFrameProduction(bool throttle) {
@@ -146,8 +148,16 @@ void SingleThreadProxy::RequestNewOutputSurface() {
layer_tree_host_->RequestNewOutputSurface();
}
-void SingleThreadProxy::SetOutputSurface(
- scoped_ptr<OutputSurface> output_surface) {
+void SingleThreadProxy::ReleaseOutputSurface() {
+ // |layer_tree_host_| should already be aware of this.
+ DCHECK(layer_tree_host_->output_surface_lost());
+
+ if (scheduler_on_impl_thread_)
+ scheduler_on_impl_thread_->DidLoseOutputSurface();
+ return layer_tree_host_impl_->ReleaseOutputSurface();
+}
+
+void SingleThreadProxy::SetOutputSurface(OutputSurface* output_surface) {
DCHECK(Proxy::IsMainThread());
DCHECK(layer_tree_host_->output_surface_lost());
DCHECK(output_surface_creation_requested_);
@@ -157,7 +167,7 @@ void SingleThreadProxy::SetOutputSurface(
{
DebugScopedSetMainThreadBlocked main_thread_blocked(this);
DebugScopedSetImplThread impl(this);
- success = layer_tree_host_impl_->InitializeRenderer(output_surface.Pass());
+ success = layer_tree_host_impl_->InitializeRenderer(output_surface);
}
if (success) {
@@ -189,7 +199,7 @@ void SingleThreadProxy::SetNeedsAnimate() {
animate_requested_ = true;
DebugScopedSetImplThread impl(this);
if (scheduler_on_impl_thread_)
- scheduler_on_impl_thread_->SetNeedsCommit();
+ scheduler_on_impl_thread_->SetNeedsBeginMainFrame();
}
void SingleThreadProxy::SetNeedsUpdateLayers() {
@@ -198,24 +208,6 @@ void SingleThreadProxy::SetNeedsUpdateLayers() {
SetNeedsCommit();
}
-void SingleThreadProxy::DoAnimate() {
- // Don't animate if there is no root layer.
- // TODO(mithro): Both Animate and UpdateAnimationState already have a
- // "!active_tree_->root_layer()" check?
- if (!layer_tree_host_impl_->active_tree()->root_layer()) {
- return;
- }
-
- layer_tree_host_impl_->Animate(
- layer_tree_host_impl_->CurrentBeginFrameArgs().frame_time);
-
- // If animations are not visible, update the animation state now as it
- // won't happen in DoComposite.
- if (!layer_tree_host_impl_->AnimationsAreVisible()) {
- layer_tree_host_impl_->UpdateAnimationState(true);
- }
-}
-
void SingleThreadProxy::DoCommit() {
TRACE_EVENT0("cc", "SingleThreadProxy::DoCommit");
DCHECK(Proxy::IsMainThread());
@@ -245,7 +237,6 @@ void SingleThreadProxy::DoCommit() {
blocking_main_thread_task_runner()));
layer_tree_host_impl_->BeginCommit();
- layer_tree_host_->BeginCommitOnImplThread(layer_tree_host_impl_.get());
// TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
// is fixed.
@@ -271,6 +262,11 @@ void SingleThreadProxy::DoCommit() {
DCHECK_EQ(1.f, scroll_info->page_scale_delta);
#endif
+ if (scheduler_on_impl_thread_)
+ scheduler_on_impl_thread_->DidCommit();
+
+ layer_tree_host_impl_->CommitComplete();
+
// TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
// is fixed.
tracked_objects::ScopedTracker tracking_profile8(
@@ -286,17 +282,12 @@ void SingleThreadProxy::DoCommit() {
}
void SingleThreadProxy::CommitComplete() {
+ // Commit complete happens on the main side after activate to satisfy any
+ // SetNextCommitWaitsForActivation calls.
DCHECK(!layer_tree_host_impl_->pending_tree())
<< "Activation is expected to have synchronously occurred by now.";
DCHECK(commit_blocking_task_runner_);
- if (scheduler_on_impl_thread_)
- scheduler_on_impl_thread_->DidCommit();
-
- // Notify commit complete on the impl side after activate to satisfy any
- // SetNextCommitWaitsForActivation calls.
- layer_tree_host_impl_->CommitComplete();
-
DebugScopedSetMainThread main(this);
commit_blocking_task_runner_.reset();
layer_tree_host_->CommitComplete();
@@ -313,7 +304,7 @@ void SingleThreadProxy::SetNeedsCommit() {
commit_requested_ = true;
DebugScopedSetImplThread impl(this);
if (scheduler_on_impl_thread_)
- scheduler_on_impl_thread_->SetNeedsCommit();
+ scheduler_on_impl_thread_->SetNeedsBeginMainFrame();
}
void SingleThreadProxy::SetNeedsRedraw(const gfx::Rect& damage_rect) {
@@ -424,7 +415,7 @@ void SingleThreadProxy::SetNeedsRedrawRectOnImplThread(
void SingleThreadProxy::SetNeedsCommitOnImplThread() {
client_->ScheduleComposite();
if (scheduler_on_impl_thread_)
- scheduler_on_impl_thread_->SetNeedsCommit();
+ scheduler_on_impl_thread_->SetNeedsBeginMainFrame();
}
void SingleThreadProxy::SetVideoNeedsBeginFrames(bool needs_begin_frames) {
@@ -447,11 +438,6 @@ void SingleThreadProxy::PostAnimationEventsToMainThreadOnImplThread(
bool SingleThreadProxy::IsInsideDraw() { return inside_draw_; }
void SingleThreadProxy::DidActivateSyncTree() {
- // This is required because NotifyReadyToActivate gets called immediately
- // after commit since single thread commits directly to the active tree.
- if (scheduler_on_impl_thread_)
- scheduler_on_impl_thread_->SetWaitForReadyToDraw();
-
// Synchronously call to CommitComplete. Resetting
// |commit_blocking_task_runner| would make sure all tasks posted during
// commit/activation before CommitComplete.
@@ -595,7 +581,8 @@ void SingleThreadProxy::CompositeImmediately(base::TimeTicks frame_begin_time) {
layer_tree_host_impl_->PrepareTiles();
layer_tree_host_impl_->SynchronouslyInitializeAllTiles();
- DoAnimate();
+ // TODO(danakj): Don't do this last... we prepared the wrong things. D:
+ layer_tree_host_impl_->Animate();
LayerTreeHostImpl::FrameData frame;
DoComposite(&frame);
@@ -609,16 +596,6 @@ void SingleThreadProxy::CompositeImmediately(base::TimeTicks frame_begin_time) {
}
}
-void SingleThreadProxy::ForceSerializeOnSwapBuffers() {
- {
- DebugScopedSetImplThread impl(this);
- if (layer_tree_host_impl_->renderer()) {
- DCHECK(!layer_tree_host_->output_surface_lost());
- layer_tree_host_impl_->renderer()->DoNoOp();
- }
- }
-}
-
bool SingleThreadProxy::SupportsImplScrolling() const {
return false;
}
@@ -883,7 +860,7 @@ void SingleThreadProxy::ScheduledActionCommit() {
void SingleThreadProxy::ScheduledActionAnimate() {
TRACE_EVENT0("cc", "ScheduledActionAnimate");
DebugScopedSetImplThread impl(this);
- DoAnimate();
+ layer_tree_host_impl_->Animate();
}
void SingleThreadProxy::ScheduledActionActivateSyncTree() {
diff --git a/chromium/cc/trees/single_thread_proxy.h b/chromium/cc/trees/single_thread_proxy.h
index 8bec2b133f9..3caf1399bf1 100644
--- a/chromium/cc/trees/single_thread_proxy.h
+++ b/chromium/cc/trees/single_thread_proxy.h
@@ -38,7 +38,8 @@ class CC_EXPORT SingleThreadProxy : public Proxy,
void FinishAllRendering() override;
bool IsStarted() const override;
bool CommitToActiveTree() const override;
- void SetOutputSurface(scoped_ptr<OutputSurface>) override;
+ void SetOutputSurface(OutputSurface* output_surface) override;
+ void ReleaseOutputSurface() override;
void SetLayerTreeHostClientReady() override;
void SetVisible(bool visible) override;
void SetThrottleFrameProduction(bool throttle) override;
@@ -55,7 +56,6 @@ class CC_EXPORT SingleThreadProxy : public Proxy,
void MainThreadHasStoppedFlinging() override {}
void Start() override;
void Stop() override;
- void ForceSerializeOnSwapBuffers() override;
bool SupportsImplScrolling() const override;
bool MainFrameWillHappenForTesting() override;
void SetChildrenNeedBeginFrames(bool children_need_begin_frames) override;
@@ -110,8 +110,6 @@ class CC_EXPORT SingleThreadProxy : public Proxy,
scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events)
override;
- void SetDebugState(const LayerTreeDebugState& debug_state) override {}
-
void RequestNewOutputSurface();
// Called by the legacy path where RenderWidget does the scheduling.
@@ -128,7 +126,6 @@ class CC_EXPORT SingleThreadProxy : public Proxy,
private:
void BeginMainFrame(const BeginFrameArgs& begin_frame_args);
void BeginMainFrameAbortedOnImplThread(CommitEarlyOutReason reason);
- void DoAnimate();
void DoBeginMainFrame(const BeginFrameArgs& begin_frame_args);
void DoCommit();
DrawResult DoComposite(LayerTreeHostImpl::FrameData* frame);
diff --git a/chromium/cc/trees/thread_proxy.cc b/chromium/cc/trees/thread_proxy.cc
index 533c4906a01..ca6eb73d5cd 100644
--- a/chromium/cc/trees/thread_proxy.cc
+++ b/chromium/cc/trees/thread_proxy.cc
@@ -71,20 +71,22 @@ ThreadProxy::ThreadProxy(
TRACE_EVENT0("cc", "ThreadProxy::ThreadProxy");
DCHECK(IsMainThread());
DCHECK(this->layer_tree_host());
+ // TODO(khushalsagar): Move this to LayerTreeHost#InitializeThreaded once
+ // ThreadProxy is split. LayerTreeHost creates the channel and passes it to
+ // ProxyMain#SetChannel.
+ SetChannel(ThreadedChannel::Create(this, main_task_runner, impl_task_runner));
}
ThreadProxy::MainThreadOnly::MainThreadOnly(ThreadProxy* proxy,
int layer_tree_host_id)
: layer_tree_host_id(layer_tree_host_id),
- animate_requested(false),
- commit_requested(false),
- commit_request_sent_to_impl_thread(false),
+ max_requested_pipeline_stage(NO_PIPELINE_STAGE),
+ current_pipeline_stage(NO_PIPELINE_STAGE),
+ final_pipeline_stage(NO_PIPELINE_STAGE),
started(false),
prepare_tiles_pending(false),
- can_cancel_commit(true),
defer_commits(false),
- weak_factory(proxy) {
-}
+ weak_factory(proxy) {}
ThreadProxy::MainThreadOnly::~MainThreadOnly() {}
@@ -125,6 +127,11 @@ ThreadProxy::~ThreadProxy() {
DCHECK(!main().started);
}
+void ThreadProxy::SetChannel(scoped_ptr<ThreadedChannel> threaded_channel) {
+ threaded_channel_ = threaded_channel.Pass();
+ main().channel_main = threaded_channel_.get();
+}
+
void ThreadProxy::FinishAllRendering() {
DCHECK(Proxy::IsMainThread());
DCHECK(!main().defer_commits);
@@ -153,13 +160,10 @@ bool ThreadProxy::CommitToActiveTree() const {
void ThreadProxy::SetLayerTreeHostClientReady() {
TRACE_EVENT0("cc", "ThreadProxy::SetLayerTreeHostClientReady");
- Proxy::ImplThreadTaskRunner()->PostTask(
- FROM_HERE,
- base::Bind(&ThreadProxy::SetLayerTreeHostClientReadyOnImplThread,
- impl_thread_weak_ptr_));
+ main().channel_main->SetLayerTreeHostClientReadyOnImpl();
}
-void ThreadProxy::SetLayerTreeHostClientReadyOnImplThread() {
+void ThreadProxy::SetLayerTreeHostClientReadyOnImpl() {
TRACE_EVENT0("cc", "ThreadProxy::SetLayerTreeHostClientReadyOnImplThread");
impl().scheduler->SetCanStart();
}
@@ -189,13 +193,10 @@ void ThreadProxy::SetVisibleOnImplThread(CompletionEvent* completion,
void ThreadProxy::SetThrottleFrameProduction(bool throttle) {
TRACE_EVENT1("cc", "ThreadProxy::SetThrottleFrameProduction", "throttle",
throttle);
- Proxy::ImplThreadTaskRunner()->PostTask(
- FROM_HERE,
- base::Bind(&ThreadProxy::SetThrottleFrameProductionOnImplThread,
- impl_thread_weak_ptr_, throttle));
+ main().channel_main->SetThrottleFrameProductionOnImpl(throttle);
}
-void ThreadProxy::SetThrottleFrameProductionOnImplThread(bool throttle) {
+void ThreadProxy::SetThrottleFrameProductionOnImpl(bool throttle) {
TRACE_EVENT1("cc", "ThreadProxy::SetThrottleFrameProductionOnImplThread",
"throttle", throttle);
impl().scheduler->SetThrottleFrameProduction(throttle);
@@ -212,11 +213,22 @@ void ThreadProxy::RequestNewOutputSurface() {
layer_tree_host()->RequestNewOutputSurface();
}
-void ThreadProxy::SetOutputSurface(scoped_ptr<OutputSurface> output_surface) {
+void ThreadProxy::SetOutputSurface(OutputSurface* output_surface) {
Proxy::ImplThreadTaskRunner()->PostTask(
- FROM_HERE,
- base::Bind(&ThreadProxy::InitializeOutputSurfaceOnImplThread,
- impl_thread_weak_ptr_, base::Passed(&output_surface)));
+ FROM_HERE, base::Bind(&ThreadProxy::InitializeOutputSurfaceOnImplThread,
+ impl_thread_weak_ptr_, output_surface));
+}
+
+void ThreadProxy::ReleaseOutputSurface() {
+ DCHECK(IsMainThread());
+ DCHECK(layer_tree_host()->output_surface_lost());
+
+ DebugScopedSetMainThreadBlocked main_thread_blocked(this);
+ CompletionEvent completion;
+ Proxy::ImplThreadTaskRunner()->PostTask(
+ FROM_HERE, base::Bind(&ThreadProxy::ReleaseOutputSurfaceOnImplThread,
+ impl_thread_weak_ptr_, &completion));
+ completion.Wait();
}
void ThreadProxy::DidInitializeOutputSurface(
@@ -238,15 +250,21 @@ void ThreadProxy::SetRendererCapabilitiesMainThreadCopy(
main().renderer_capabilities_main_thread_copy = capabilities;
}
-void ThreadProxy::SendCommitRequestToImplThreadIfNeeded() {
+bool ThreadProxy::SendCommitRequestToImplThreadIfNeeded(
+ CommitPipelineStage required_stage) {
DCHECK(IsMainThread());
- if (main().commit_request_sent_to_impl_thread)
- return;
- main().commit_request_sent_to_impl_thread = true;
+ DCHECK_NE(NO_PIPELINE_STAGE, required_stage);
+ bool already_posted =
+ main().max_requested_pipeline_stage != NO_PIPELINE_STAGE;
+ main().max_requested_pipeline_stage =
+ std::max(main().max_requested_pipeline_stage, required_stage);
+ if (already_posted)
+ return false;
Proxy::ImplThreadTaskRunner()->PostTask(
FROM_HERE,
base::Bind(&ThreadProxy::SetNeedsCommitOnImplThread,
impl_thread_weak_ptr_));
+ return true;
}
void ThreadProxy::DidCompletePageScaleAnimation() {
@@ -262,35 +280,40 @@ const RendererCapabilities& ThreadProxy::GetRendererCapabilities() const {
void ThreadProxy::SetNeedsAnimate() {
DCHECK(IsMainThread());
- if (main().animate_requested)
- return;
-
- TRACE_EVENT0("cc", "ThreadProxy::SetNeedsAnimate");
- main().animate_requested = true;
- SendCommitRequestToImplThreadIfNeeded();
+ if (SendCommitRequestToImplThreadIfNeeded(ANIMATE_PIPELINE_STAGE)) {
+ TRACE_EVENT_INSTANT0("cc", "ThreadProxy::SetNeedsAnimate",
+ TRACE_EVENT_SCOPE_THREAD);
+ }
}
void ThreadProxy::SetNeedsUpdateLayers() {
DCHECK(IsMainThread());
-
- if (main().commit_request_sent_to_impl_thread)
+ // If we are currently animating, make sure we also update the layers.
+ if (main().current_pipeline_stage == ANIMATE_PIPELINE_STAGE) {
+ main().final_pipeline_stage =
+ std::max(main().final_pipeline_stage, UPDATE_LAYERS_PIPELINE_STAGE);
return;
- TRACE_EVENT0("cc", "ThreadProxy::SetNeedsUpdateLayers");
-
- SendCommitRequestToImplThreadIfNeeded();
+ }
+ if (SendCommitRequestToImplThreadIfNeeded(UPDATE_LAYERS_PIPELINE_STAGE)) {
+ TRACE_EVENT_INSTANT0("cc", "ThreadProxy::SetNeedsUpdateLayers",
+ TRACE_EVENT_SCOPE_THREAD);
+ }
}
void ThreadProxy::SetNeedsCommit() {
DCHECK(IsMainThread());
- // Unconditionally set here to handle SetNeedsCommit calls during a commit.
- main().can_cancel_commit = false;
-
- if (main().commit_requested)
+ // If we are currently animating, make sure we don't skip the commit. Note
+ // that requesting a commit during the layer update stage means we need to
+ // schedule another full commit.
+ if (main().current_pipeline_stage == ANIMATE_PIPELINE_STAGE) {
+ main().final_pipeline_stage =
+ std::max(main().final_pipeline_stage, COMMIT_PIPELINE_STAGE);
return;
- TRACE_EVENT0("cc", "ThreadProxy::SetNeedsCommit");
- main().commit_requested = true;
-
- SendCommitRequestToImplThreadIfNeeded();
+ }
+ if (SendCommitRequestToImplThreadIfNeeded(COMMIT_PIPELINE_STAGE)) {
+ TRACE_EVENT_INSTANT0("cc", "ThreadProxy::SetNeedsCommit",
+ TRACE_EVENT_SCOPE_THREAD);
+ }
}
void ThreadProxy::UpdateRendererCapabilitiesOnImplThread() {
@@ -335,9 +358,7 @@ void ThreadProxy::DidSwapBuffersCompleteOnImplThread() {
"ThreadProxy::DidSwapBuffersCompleteOnImplThread");
DCHECK(IsImplThread());
impl().scheduler->DidSwapBuffersComplete();
- Proxy::MainThreadTaskRunner()->PostTask(
- FROM_HERE,
- base::Bind(&ThreadProxy::DidCompleteSwapBuffers, main_thread_weak_ptr_));
+ impl().channel_impl->DidCompleteSwapBuffers();
}
void ThreadProxy::WillBeginImplFrame(const BeginFrameArgs& args) {
@@ -374,7 +395,7 @@ void ThreadProxy::NotifyReadyToDraw() {
void ThreadProxy::SetNeedsCommitOnImplThread() {
TRACE_EVENT0("cc", "ThreadProxy::SetNeedsCommitOnImplThread");
DCHECK(IsImplThread());
- impl().scheduler->SetNeedsCommit();
+ impl().scheduler->SetNeedsBeginMainFrame();
}
void ThreadProxy::SetVideoNeedsBeginFrames(bool needs_begin_frames) {
@@ -441,12 +462,15 @@ void ThreadProxy::SetDeferCommitsOnImplThread(bool defer_commits) const {
bool ThreadProxy::CommitRequested() const {
DCHECK(IsMainThread());
- return main().commit_requested;
+ // TODO(skyostil): Split this into something like CommitRequested() and
+ // CommitInProgress().
+ return main().current_pipeline_stage != NO_PIPELINE_STAGE ||
+ main().max_requested_pipeline_stage >= COMMIT_PIPELINE_STAGE;
}
bool ThreadProxy::BeginMainFrameRequested() const {
DCHECK(IsMainThread());
- return main().commit_request_sent_to_impl_thread;
+ return main().max_requested_pipeline_stage != NO_PIPELINE_STAGE;
}
void ThreadProxy::SetNeedsRedrawOnImplThread() {
@@ -596,42 +620,10 @@ void ThreadProxy::Stop() {
main().started = false;
}
-void ThreadProxy::ForceSerializeOnSwapBuffers() {
- DebugScopedSetMainThreadBlocked main_thread_blocked(this);
- CompletionEvent completion;
- Proxy::ImplThreadTaskRunner()->PostTask(
- FROM_HERE,
- base::Bind(&ThreadProxy::ForceSerializeOnSwapBuffersOnImplThread,
- impl_thread_weak_ptr_,
- &completion));
- completion.Wait();
-}
-
-void ThreadProxy::ForceSerializeOnSwapBuffersOnImplThread(
- CompletionEvent* completion) {
- if (impl().layer_tree_host_impl->renderer())
- impl().layer_tree_host_impl->renderer()->DoNoOp();
- completion->Signal();
-}
-
bool ThreadProxy::SupportsImplScrolling() const {
return true;
}
-void ThreadProxy::SetDebugState(const LayerTreeDebugState& debug_state) {
- Proxy::ImplThreadTaskRunner()->PostTask(
- FROM_HERE,
- base::Bind(&ThreadProxy::SetDebugStateOnImplThread,
- impl_thread_weak_ptr_,
- debug_state));
-}
-
-void ThreadProxy::SetDebugStateOnImplThread(
- const LayerTreeDebugState& debug_state) {
- DCHECK(IsImplThread());
- impl().scheduler->SetContinuousPainting(debug_state.continuous_painting);
-}
-
void ThreadProxy::FinishAllRenderingOnImplThread(CompletionEvent* completion) {
TRACE_EVENT0("cc", "ThreadProxy::FinishAllRenderingOnImplThread");
DCHECK(IsImplThread());
@@ -680,6 +672,7 @@ void ThreadProxy::BeginMainFrame(
begin_main_frame_state->begin_frame_id);
TRACE_EVENT_SYNTHETIC_DELAY_BEGIN("cc.BeginMainFrame");
DCHECK(IsMainThread());
+ DCHECK_EQ(NO_PIPELINE_STAGE, main().current_pipeline_stage);
if (main().defer_commits) {
TRACE_EVENT_INSTANT0("cc", "EarlyOut_DeferCommit",
@@ -696,9 +689,8 @@ void ThreadProxy::BeginMainFrame(
// remaining swap promises.
ScopedAbortRemainingSwapPromises swap_promise_checker(layer_tree_host());
- main().commit_requested = false;
- main().commit_request_sent_to_impl_thread = false;
- main().animate_requested = false;
+ main().final_pipeline_stage = main().max_requested_pipeline_stage;
+ main().max_requested_pipeline_stage = NO_PIPELINE_STAGE;
if (!layer_tree_host()->visible()) {
TRACE_EVENT_INSTANT0("cc", "EarlyOut_NotVisible", TRACE_EVENT_SCOPE_THREAD);
@@ -720,16 +712,7 @@ void ThreadProxy::BeginMainFrame(
return;
}
- // Do not notify the impl thread of commit requests that occur during
- // the apply/animate/layout part of the BeginMainFrameAndCommit process since
- // those commit requests will get painted immediately. Once we have done
- // the paint, main().commit_requested will be set to false to allow new commit
- // requests to be scheduled.
- // On the other hand, the animate_requested flag should remain cleared
- // here so that any animation requests generated by the apply or animate
- // callbacks will trigger another frame.
- main().commit_requested = true;
- main().commit_request_sent_to_impl_thread = true;
+ main().current_pipeline_stage = ANIMATE_PIPELINE_STAGE;
layer_tree_host()->ApplyScrollAndScale(
begin_main_frame_state->scroll_info.get());
@@ -748,32 +731,20 @@ void ThreadProxy::BeginMainFrame(
layer_tree_host()->Layout();
TRACE_EVENT_SYNTHETIC_DELAY_END("cc.BeginMainFrame");
- // Clear the commit flag after updating animations and layout here --- objects
- // that only layout when painted will trigger another SetNeedsCommit inside
- // UpdateLayers.
- main().commit_requested = false;
- main().commit_request_sent_to_impl_thread = false;
bool can_cancel_this_commit =
- main().can_cancel_commit && !begin_main_frame_state->evicted_ui_resources;
- main().can_cancel_commit = true;
+ main().final_pipeline_stage < COMMIT_PIPELINE_STAGE &&
+ !begin_main_frame_state->evicted_ui_resources;
- bool updated = layer_tree_host()->UpdateLayers();
+ main().current_pipeline_stage = UPDATE_LAYERS_PIPELINE_STAGE;
+ bool should_update_layers =
+ main().final_pipeline_stage >= UPDATE_LAYERS_PIPELINE_STAGE;
+ bool updated = should_update_layers && layer_tree_host()->UpdateLayers();
layer_tree_host()->WillCommit();
devtools_instrumentation::ScopedCommitTrace commit_task(
layer_tree_host()->id());
- // Before calling animate, we set main().animate_requested to false. If it is
- // true now, it means SetNeedAnimate was called again, but during a state when
- // main().commit_request_sent_to_impl_thread = true. We need to force that
- // call to happen again now so that the commit request is sent to the impl
- // thread.
- if (main().animate_requested) {
- // Forces SetNeedsAnimate to consider posting a commit task.
- main().animate_requested = false;
- SetNeedsAnimate();
- }
-
+ main().current_pipeline_stage = COMMIT_PIPELINE_STAGE;
if (!updated && can_cancel_this_commit) {
TRACE_EVENT_INSTANT0("cc", "EarlyOut_NoUpdates", TRACE_EVENT_SCOPE_THREAD);
Proxy::ImplThreadTaskRunner()->PostTask(
@@ -784,6 +755,7 @@ void ThreadProxy::BeginMainFrame(
// Although the commit is internally aborted, this is because it has been
// detected to be a no-op. From the perspective of an embedder, this commit
// went through, and input should no longer be throttled, etc.
+ main().current_pipeline_stage = NO_PIPELINE_STAGE;
layer_tree_host()->CommitComplete();
layer_tree_host()->DidBeginMainFrame();
layer_tree_host()->BreakSwapPromises(SwapPromise::COMMIT_NO_UPDATE);
@@ -812,6 +784,7 @@ void ThreadProxy::BeginMainFrame(
completion.Wait();
}
+ main().current_pipeline_stage = NO_PIPELINE_STAGE;
layer_tree_host()->CommitComplete();
layer_tree_host()->DidBeginMainFrame();
}
@@ -865,22 +838,7 @@ void ThreadProxy::ScheduledActionAnimate() {
TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionAnimate");
DCHECK(IsImplThread());
- // Don't animate if there is no root layer.
- // TODO(mithro): Both Animate and UpdateAnimationState already have a
- // "!active_tree_->root_layer()" check?
- if (!impl().layer_tree_host_impl->active_tree()->root_layer()) {
- return;
- }
-
- impl().animation_time =
- impl().layer_tree_host_impl->CurrentBeginFrameArgs().frame_time;
- impl().layer_tree_host_impl->Animate(impl().animation_time);
-
- // If animations are not visible, update the state now as
- // ScheduledActionDrawAndSwapIfPossible will never be called.
- if (!impl().layer_tree_host_impl->AnimationsAreVisible()) {
- impl().layer_tree_host_impl->UpdateAnimationState(true);
- }
+ impl().layer_tree_host_impl->Animate();
}
void ThreadProxy::ScheduledActionCommit() {
@@ -891,7 +849,6 @@ void ThreadProxy::ScheduledActionCommit() {
blocked_main().main_thread_inside_commit = true;
impl().layer_tree_host_impl->BeginCommit();
- layer_tree_host()->BeginCommitOnImplThread(impl().layer_tree_host_impl.get());
layer_tree_host()->FinishCommitOnImplThread(
impl().layer_tree_host_impl.get());
blocked_main().main_thread_inside_commit = false;
@@ -1060,6 +1017,11 @@ void ThreadProxy::SetAnimationEvents(scoped_ptr<AnimationEventsVector> events) {
void ThreadProxy::InitializeImplOnImplThread(CompletionEvent* completion) {
TRACE_EVENT0("cc", "ThreadProxy::InitializeImplOnImplThread");
DCHECK(IsImplThread());
+
+ // TODO(khushalsagar): ThreadedChannel will create ProxyImpl here and pass a
+ // reference to itself.
+ impl().channel_impl = threaded_channel_.get();
+
impl().layer_tree_host_impl =
layer_tree_host()->CreateLayerTreeHostImpl(this);
@@ -1067,7 +1029,8 @@ void ThreadProxy::InitializeImplOnImplThread(CompletionEvent* completion) {
layer_tree_host()->settings().ToSchedulerSettings());
scoped_ptr<CompositorTimingHistory> compositor_timing_history(
- new CompositorTimingHistory(impl().rendering_stats_instrumentation));
+ new CompositorTimingHistory(CompositorTimingHistory::RENDERER_UMA,
+ impl().rendering_stats_instrumentation));
impl().scheduler = Scheduler::Create(
this, scheduler_settings, impl().layer_tree_host_id,
@@ -1080,12 +1043,12 @@ void ThreadProxy::InitializeImplOnImplThread(CompletionEvent* completion) {
}
void ThreadProxy::InitializeOutputSurfaceOnImplThread(
- scoped_ptr<OutputSurface> output_surface) {
+ OutputSurface* output_surface) {
TRACE_EVENT0("cc", "ThreadProxy::InitializeOutputSurfaceOnImplThread");
DCHECK(IsImplThread());
LayerTreeHostImpl* host_impl = impl().layer_tree_host_impl.get();
- bool success = host_impl->InitializeRenderer(output_surface.Pass());
+ bool success = host_impl->InitializeRenderer(output_surface);
RendererCapabilities capabilities;
if (success) {
capabilities =
@@ -1103,6 +1066,17 @@ void ThreadProxy::InitializeOutputSurfaceOnImplThread(
impl().scheduler->DidCreateAndInitializeOutputSurface();
}
+void ThreadProxy::ReleaseOutputSurfaceOnImplThread(
+ CompletionEvent* completion) {
+ DCHECK(IsImplThread());
+
+ // Unlike DidLoseOutputSurfaceOnImplThread, we don't need to call
+ // LayerTreeHost::DidLoseOutputSurface since it already knows.
+ impl().scheduler->DidLoseOutputSurface();
+ impl().layer_tree_host_impl->ReleaseOutputSurface();
+ completion->Signal();
+}
+
void ThreadProxy::FinishGLOnImplThread(CompletionEvent* completion) {
TRACE_EVENT0("cc", "ThreadProxy::FinishGLOnImplThread");
DCHECK(IsImplThread());
@@ -1281,4 +1255,12 @@ void ThreadProxy::PostFrameTimingEvents(
main_frame_events.Pass());
}
+base::WeakPtr<ProxyMain> ThreadProxy::GetMainWeakPtr() {
+ return main_thread_weak_ptr_;
+}
+
+base::WeakPtr<ProxyImpl> ThreadProxy::GetImplWeakPtr() {
+ return impl_thread_weak_ptr_;
+}
+
} // namespace cc
diff --git a/chromium/cc/trees/thread_proxy.h b/chromium/cc/trees/thread_proxy.h
index ca76e42669b..a6b3cf735dc 100644
--- a/chromium/cc/trees/thread_proxy.h
+++ b/chromium/cc/trees/thread_proxy.h
@@ -17,6 +17,7 @@
#include "cc/scheduler/scheduler.h"
#include "cc/trees/layer_tree_host_impl.h"
#include "cc/trees/proxy.h"
+#include "cc/trees/threaded_channel.h"
namespace base {
class SingleThreadTaskRunner;
@@ -25,13 +26,20 @@ class SingleThreadTaskRunner;
namespace cc {
class BeginFrameSource;
+class ChannelImpl;
+class ChannelMain;
class ContextProvider;
class InputHandlerClient;
class LayerTreeHost;
+class ProxyImpl;
+class ProxyMain;
class Scheduler;
class ScopedThreadProxy;
+class ThreadedChannel;
class CC_EXPORT ThreadProxy : public Proxy,
+ public ProxyMain,
+ public ProxyImpl,
NON_EXPORTED_BASE(LayerTreeHostImplClient),
NON_EXPORTED_BASE(SchedulerClient) {
public:
@@ -54,26 +62,42 @@ class CC_EXPORT ThreadProxy : public Proxy,
bool evicted_ui_resources;
};
+ // Commits between the main and impl threads are processed through a pipeline
+ // with the following stages. For efficiency we can early out at any stage if
+ // we decide that no further processing is necessary.
+ enum CommitPipelineStage {
+ NO_PIPELINE_STAGE,
+ ANIMATE_PIPELINE_STAGE,
+ UPDATE_LAYERS_PIPELINE_STAGE,
+ COMMIT_PIPELINE_STAGE,
+ };
+
struct MainThreadOnly {
MainThreadOnly(ThreadProxy* proxy, int layer_tree_host_id);
~MainThreadOnly();
const int layer_tree_host_id;
- // Set only when SetNeedsAnimate is called.
- bool animate_requested;
- // Set only when SetNeedsCommit is called.
- bool commit_requested;
- // Set by SetNeedsAnimate, SetNeedsUpdateLayers, and SetNeedsCommit.
- bool commit_request_sent_to_impl_thread;
+ // The furthest pipeline stage which has been requested for the next
+ // commit.
+ CommitPipelineStage max_requested_pipeline_stage;
+ // The commit pipeline stage that is currently being processed.
+ CommitPipelineStage current_pipeline_stage;
+ // The commit pipeline stage at which processing for the current commit
+ // will stop. Only valid while we are executing the pipeline (i.e.,
+ // |current_pipeline_stage| is set to a pipeline stage).
+ CommitPipelineStage final_pipeline_stage;
bool started;
bool prepare_tiles_pending;
- bool can_cancel_commit;
bool defer_commits;
RendererCapabilities renderer_capabilities_main_thread_copy;
+ // TODO(khushalsagar): Make this scoped_ptr<ChannelMain> when ProxyMain
+ // and ProxyImpl are split.
+ ChannelMain* channel_main;
+
base::WeakPtrFactory<ThreadProxy> weak_factory;
};
@@ -117,8 +141,6 @@ class CC_EXPORT ThreadProxy : public Proxy,
bool input_throttled_until_commit;
- base::TimeTicks animation_time;
-
// Whether a commit has been completed since the last time animations were
// ticked. If this happens, we need to animate again.
bool did_commit_after_animating;
@@ -134,6 +156,9 @@ class CC_EXPORT ThreadProxy : public Proxy,
BeginFrameArgs last_processed_begin_main_frame_args;
scoped_ptr<LayerTreeHostImpl> layer_tree_host_impl;
+
+ ChannelImpl* channel_impl;
+
base::WeakPtrFactory<ThreadProxy> weak_factory;
};
@@ -145,7 +170,7 @@ class CC_EXPORT ThreadProxy : public Proxy,
void FinishAllRendering() override;
bool IsStarted() const override;
bool CommitToActiveTree() const override;
- void SetOutputSurface(scoped_ptr<OutputSurface>) override;
+ void SetOutputSurface(OutputSurface* output_surface) override;
void SetLayerTreeHostClientReady() override;
void SetVisible(bool visible) override;
void SetThrottleFrameProduction(bool throttle) override;
@@ -162,12 +187,11 @@ class CC_EXPORT ThreadProxy : public Proxy,
void MainThreadHasStoppedFlinging() override;
void Start() override;
void Stop() override;
- void ForceSerializeOnSwapBuffers() override;
bool SupportsImplScrolling() const override;
- void SetDebugState(const LayerTreeDebugState& debug_state) override;
bool MainFrameWillHappenForTesting() override;
void SetChildrenNeedBeginFrames(bool children_need_begin_frames) override;
void SetAuthoritativeVSyncInterval(const base::TimeDelta& interval) override;
+ void ReleaseOutputSurface() override;
// LayerTreeHostImplClient implementation
void UpdateRendererCapabilitiesOnImplThread() override;
@@ -222,6 +246,16 @@ class CC_EXPORT ThreadProxy : public Proxy,
void SendBeginFramesToChildren(const BeginFrameArgs& args) override;
void SendBeginMainFrameNotExpectedSoon() override;
+ // ProxyMain implementation
+ base::WeakPtr<ProxyMain> GetMainWeakPtr() override;
+ void SetChannel(scoped_ptr<ThreadedChannel> threaded_channel) override;
+ void DidCompleteSwapBuffers() override;
+
+ // ProxyImpl implementation
+ base::WeakPtr<ProxyImpl> GetImplWeakPtr() override;
+ void SetThrottleFrameProductionOnImpl(bool throttle) override;
+ void SetLayerTreeHostClientReadyOnImpl() override;
+
protected:
ThreadProxy(
LayerTreeHost* layer_tree_host,
@@ -237,13 +271,15 @@ class CC_EXPORT ThreadProxy : public Proxy,
scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state);
void BeginMainFrameNotExpectedSoon();
void DidCommitAndDrawFrame();
- void DidCompleteSwapBuffers();
void SetAnimationEvents(scoped_ptr<AnimationEventsVector> queue);
void DidLoseOutputSurface();
void RequestNewOutputSurface();
void DidInitializeOutputSurface(bool success,
const RendererCapabilities& capabilities);
- void SendCommitRequestToImplThreadIfNeeded();
+ // Returns |true| if the request was actually sent, |false| if one was
+ // already outstanding.
+ bool SendCommitRequestToImplThreadIfNeeded(
+ CommitPipelineStage required_stage);
void DidCompletePageScaleAnimation();
// Called on impl thread.
@@ -253,25 +289,21 @@ class CC_EXPORT ThreadProxy : public Proxy,
void BeginMainFrameAbortedOnImplThread(CommitEarlyOutReason reason);
void FinishAllRenderingOnImplThread(CompletionEvent* completion);
void InitializeImplOnImplThread(CompletionEvent* completion);
- void SetLayerTreeHostClientReadyOnImplThread();
void SetVisibleOnImplThread(CompletionEvent* completion, bool visible);
- void SetThrottleFrameProductionOnImplThread(bool throttle);
void HasInitializedOutputSurfaceOnImplThread(
CompletionEvent* completion,
bool* has_initialized_output_surface);
void DeleteContentsTexturesOnImplThread(CompletionEvent* completion);
- void InitializeOutputSurfaceOnImplThread(
- scoped_ptr<OutputSurface> output_surface);
+ void InitializeOutputSurfaceOnImplThread(OutputSurface* output_surface);
+ void ReleaseOutputSurfaceOnImplThread(CompletionEvent* completion);
void FinishGLOnImplThread(CompletionEvent* completion);
void LayerTreeHostClosedOnImplThread(CompletionEvent* completion);
DrawResult DrawSwapInternal(bool forced_draw);
- void ForceSerializeOnSwapBuffersOnImplThread(CompletionEvent* completion);
void MainFrameWillHappenOnImplThreadForTesting(CompletionEvent* completion,
bool* main_frame_will_happen);
void SetSwapUsedIncompleteTileOnImplThread(bool used_incomplete_tile);
void MainThreadHasStoppedFlingingOnImplThread();
void SetInputThrottledUntilCommitOnImplThread(bool is_throttled);
- void SetDebugStateOnImplThread(const LayerTreeDebugState& debug_state);
void SetDeferCommitsOnImplThread(bool defer_commits) const;
void PostFrameTimingEvents(
scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events,
@@ -292,6 +324,9 @@ class CC_EXPORT ThreadProxy : public Proxy,
CompositorThreadOnly compositor_thread_vars_unsafe_;
CompositorThreadOnly& impl();
+ // TODO(khushalsagar): Remove this. Temporary variable to hold the channel.
+ scoped_ptr<ThreadedChannel> threaded_channel_;
+
base::WeakPtr<ThreadProxy> main_thread_weak_ptr_;
base::WeakPtr<ThreadProxy> impl_thread_weak_ptr_;
diff --git a/chromium/cc/trees/threaded_channel.cc b/chromium/cc/trees/threaded_channel.cc
new file mode 100644
index 00000000000..3bc44c93efa
--- /dev/null
+++ b/chromium/cc/trees/threaded_channel.cc
@@ -0,0 +1,60 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/trees/threaded_channel.h"
+
+#include "base/bind.h"
+#include "base/single_thread_task_runner.h"
+#include "base/trace_event/trace_event.h"
+
+namespace cc {
+
+scoped_ptr<ThreadedChannel> ThreadedChannel::Create(
+ ThreadProxy* thread_proxy,
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner) {
+ return make_scoped_ptr(
+ new ThreadedChannel(thread_proxy, main_task_runner, impl_task_runner));
+}
+
+ThreadedChannel::ThreadedChannel(
+ ThreadProxy* thread_proxy,
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner)
+ : proxy_main_(thread_proxy),
+ proxy_impl_(thread_proxy),
+ main_task_runner_(main_task_runner),
+ impl_task_runner_(impl_task_runner) {}
+
+void ThreadedChannel::SetThrottleFrameProductionOnImpl(bool throttle) {
+ ImplThreadTaskRunner()->PostTask(
+ FROM_HERE, base::Bind(&ProxyImpl::SetThrottleFrameProductionOnImpl,
+ proxy_impl_->GetImplWeakPtr(), throttle));
+}
+
+void ThreadedChannel::SetLayerTreeHostClientReadyOnImpl() {
+ ImplThreadTaskRunner()->PostTask(
+ FROM_HERE, base::Bind(&ProxyImpl::SetLayerTreeHostClientReadyOnImpl,
+ proxy_impl_->GetImplWeakPtr()));
+}
+
+void ThreadedChannel::DidCompleteSwapBuffers() {
+ MainThreadTaskRunner()->PostTask(
+ FROM_HERE, base::Bind(&ProxyMain::DidCompleteSwapBuffers,
+ proxy_main_->GetMainWeakPtr()));
+}
+
+ThreadedChannel::~ThreadedChannel() {
+ TRACE_EVENT0("cc", "ThreadChannel::~ThreadChannel");
+}
+
+base::SingleThreadTaskRunner* ThreadedChannel::MainThreadTaskRunner() const {
+ return main_task_runner_.get();
+}
+
+base::SingleThreadTaskRunner* ThreadedChannel::ImplThreadTaskRunner() const {
+ return impl_task_runner_.get();
+}
+
+} // namespace cc
diff --git a/chromium/cc/trees/threaded_channel.h b/chromium/cc/trees/threaded_channel.h
new file mode 100644
index 00000000000..70238f3ded5
--- /dev/null
+++ b/chromium/cc/trees/threaded_channel.h
@@ -0,0 +1,106 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_TREES_THREADED_CHANNEL_H_
+#define CC_TREES_THREADED_CHANNEL_H_
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "cc/base/cc_export.h"
+#include "cc/trees/channel_impl.h"
+#include "cc/trees/channel_main.h"
+#include "cc/trees/proxy_impl.h"
+#include "cc/trees/proxy_main.h"
+#include "cc/trees/thread_proxy.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+}
+
+namespace cc {
+class ChannelImpl;
+class ChannelMain;
+class ProxyImpl;
+class ProxyMain;
+class ThreadProxy;
+
+// An implementation of ChannelMain and ChannelImpl that sends commands between
+// ProxyMain and ProxyImpl across thread boundaries.
+//
+// LayerTreeHost creates ThreadedChannel and passes the ownership to ProxyMain.
+// The object life cycle and communication across threads is as follows:
+//
+//
+// Main Thread | Impl Thread
+// LayerTreeHost->InitializeProxy |
+// | |
+// ProxyMain->Start() |
+// | ThreadedChannel
+// ---------------------------------------------------------------------------
+// ChannelMain::InitializeImpl ---PostTask---> ThreadedChannel::
+// InitializeImplOnImplThread
+// |
+// ProxyImpl::Create
+// |
+// ProxyImpl->Initialize()
+// .
+// .
+// ProxyImpl::ScheduledActionBegin
+// OutputSurfaceCreation
+// |
+// ChannelImpl::RequestNewOutputSurface
+// ----------------------------------------------------------------------------
+// |
+// ProxyMain->RequestNewOutputSurface()<----PostTask--------
+// .
+// .
+// ProxyMain->LayerTreeHostClosed
+// |
+// ---------------------------------------------------------------------------
+// ChannelMain::SetLayerTreeClosedOnImpl---PostTask---> ProxyImpl->
+// SetLayerTreeClosed
+// ----------------------------------------------------------------------------
+
+class CC_EXPORT ThreadedChannel : public ChannelMain, public ChannelImpl {
+ public:
+ static scoped_ptr<ThreadedChannel> Create(
+ // TODO(khushalsagar): Make this ProxyMain* and write the initialization
+ // sequence. Currently ThreadProxy implements both so we pass the pointer
+ // and set ProxyImpl.
+ ThreadProxy* thread_proxy,
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner);
+
+ ~ThreadedChannel() override;
+
+ // ChannelMain Implementation
+ void SetThrottleFrameProductionOnImpl(bool throttle) override;
+ void SetLayerTreeHostClientReadyOnImpl() override;
+
+ // ChannelImpl Implementation
+ void DidCompleteSwapBuffers() override;
+
+ protected:
+ ThreadedChannel(ThreadProxy* thread_proxy,
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner);
+
+ private:
+ base::SingleThreadTaskRunner* MainThreadTaskRunner() const;
+ base::SingleThreadTaskRunner* ImplThreadTaskRunner() const;
+
+ ProxyMain* proxy_main_;
+
+ ProxyImpl* proxy_impl_;
+
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
+
+ scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(ThreadedChannel);
+};
+
+} // namespace cc
+
+#endif // CC_TREES_THREADED_CHANNEL_H_