summaryrefslogtreecommitdiff
path: root/chromium/cc
diff options
context:
space:
mode:
authorAndras Becsi <andras.becsi@digia.com>2014-03-18 13:16:26 +0100
committerFrederik Gladhorn <frederik.gladhorn@digia.com>2014-03-20 15:55:39 +0100
commit3f0f86b0caed75241fa71c95a5d73bc0164348c5 (patch)
tree92b9fb00f2e9e90b0be2262093876d4f43b6cd13 /chromium/cc
parente90d7c4b152c56919d963987e2503f9909a666d2 (diff)
downloadqtwebengine-chromium-3f0f86b0caed75241fa71c95a5d73bc0164348c5.tar.gz
Update to new stable branch 1750
This also includes an updated ninja and chromium dependencies needed on Windows. Change-Id: Icd597d80ed3fa4425933c9f1334c3c2e31291c42 Reviewed-by: Zoltan Arvai <zarvai@inf.u-szeged.hu> Reviewed-by: Zeno Albisser <zeno.albisser@digia.com>
Diffstat (limited to 'chromium/cc')
-rw-r--r--chromium/cc/DEPS5
-rw-r--r--chromium/cc/PRESUBMIT.py105
-rw-r--r--chromium/cc/animation/animation.cc24
-rw-r--r--chromium/cc/animation/animation.h36
-rw-r--r--chromium/cc/animation/animation_curve.cc19
-rw-r--r--chromium/cc/animation/animation_curve.h18
-rw-r--r--chromium/cc/animation/animation_delegate.h15
-rw-r--r--chromium/cc/animation/animation_events.h4
-rw-r--r--chromium/cc/animation/animation_unittest.cc47
-rw-r--r--chromium/cc/animation/keyframed_animation_curve.cc91
-rw-r--r--chromium/cc/animation/keyframed_animation_curve.h46
-rw-r--r--chromium/cc/animation/keyframed_animation_curve_unittest.cc102
-rw-r--r--chromium/cc/animation/layer_animation_controller.cc347
-rw-r--r--chromium/cc/animation/layer_animation_controller.h48
-rw-r--r--chromium/cc/animation/layer_animation_controller_unittest.cc966
-rw-r--r--chromium/cc/animation/layer_animation_value_observer.h3
-rw-r--r--chromium/cc/animation/layer_animation_value_provider.h25
-rw-r--r--chromium/cc/animation/scroll_offset_animation_curve.cc80
-rw-r--r--chromium/cc/animation/scroll_offset_animation_curve.h47
-rw-r--r--chromium/cc/animation/scroll_offset_animation_curve_unittest.cc123
-rw-r--r--chromium/cc/animation/scrollbar_animation_controller.h2
-rw-r--r--chromium/cc/animation/scrollbar_animation_controller_linear_fade.cc11
-rw-r--r--chromium/cc/animation/scrollbar_animation_controller_linear_fade.h2
-rw-r--r--chromium/cc/animation/scrollbar_animation_controller_thinning.cc126
-rw-r--r--chromium/cc/animation/scrollbar_animation_controller_thinning.h32
-rw-r--r--chromium/cc/animation/scrollbar_animation_controller_thinning_unittest.cc207
-rw-r--r--chromium/cc/animation/transform_operation.cc311
-rw-r--r--chromium/cc/animation/transform_operations_unittest.cc391
-rw-r--r--chromium/cc/base/float_quad_unittest.cc38
-rw-r--r--chromium/cc/base/invalidation_region.cc11
-rw-r--r--chromium/cc/base/invalidation_region.h1
-rw-r--r--chromium/cc/base/latency_info_swap_promise.cc50
-rw-r--r--chromium/cc/base/latency_info_swap_promise.h28
-rw-r--r--chromium/cc/base/latency_info_swap_promise_monitor.cc43
-rw-r--r--chromium/cc/base/latency_info_swap_promise_monitor.h36
-rw-r--r--chromium/cc/base/math_util.cc28
-rw-r--r--chromium/cc/base/math_util.h10
-rw-r--r--chromium/cc/base/math_util_unittest.cc8
-rw-r--r--chromium/cc/base/ref_counted_managed.h65
-rw-r--r--chromium/cc/base/scoped_ptr_vector.h7
-rw-r--r--chromium/cc/base/scoped_ptr_vector_unittest.cc33
-rw-r--r--chromium/cc/base/swap_promise.h50
-rw-r--r--chromium/cc/base/swap_promise_monitor.cc31
-rw-r--r--chromium/cc/base/swap_promise_monitor.h44
-rw-r--r--chromium/cc/base/switches.cc55
-rw-r--r--chromium/cc/base/switches.h8
-rw-r--r--chromium/cc/base/util.h33
-rw-r--r--chromium/cc/cc.gyp60
-rw-r--r--chromium/cc/cc_tests.gyp97
-rw-r--r--chromium/cc/debug/OWNERS3
-rw-r--r--chromium/cc/debug/benchmark_instrumentation.cc30
-rw-r--r--chromium/cc/debug/benchmark_instrumentation.h30
-rw-r--r--chromium/cc/debug/debug_colors.cc9
-rw-r--r--chromium/cc/debug/debug_colors.h4
-rw-r--r--chromium/cc/debug/debug_rect_history.cc30
-rw-r--r--chromium/cc/debug/debug_rect_history.h3
-rw-r--r--chromium/cc/debug/devtools_instrumentation.h27
-rw-r--r--chromium/cc/debug/fake_web_graphics_context_3d.cc347
-rw-r--r--chromium/cc/debug/fake_web_graphics_context_3d.h608
-rw-r--r--chromium/cc/debug/layer_tree_debug_state.cc7
-rw-r--r--chromium/cc/debug/layer_tree_debug_state.h1
-rw-r--r--chromium/cc/debug/micro_benchmark.cc54
-rw-r--r--chromium/cc/debug/micro_benchmark.h54
-rw-r--r--chromium/cc/debug/micro_benchmark_controller.cc106
-rw-r--r--chromium/cc/debug/micro_benchmark_controller.h49
-rw-r--r--chromium/cc/debug/micro_benchmark_controller_impl.cc59
-rw-r--r--chromium/cc/debug/micro_benchmark_controller_impl.h37
-rw-r--r--chromium/cc/debug/micro_benchmark_controller_unittest.cc141
-rw-r--r--chromium/cc/debug/micro_benchmark_impl.cc48
-rw-r--r--chromium/cc/debug/micro_benchmark_impl.h48
-rw-r--r--chromium/cc/debug/picture_record_benchmark.cc126
-rw-r--r--chromium/cc/debug/picture_record_benchmark.h39
-rw-r--r--chromium/cc/debug/rasterize_and_record_benchmark.cc142
-rw-r--r--chromium/cc/debug/rasterize_and_record_benchmark.h66
-rw-r--r--chromium/cc/debug/rasterize_and_record_benchmark_impl.cc120
-rw-r--r--chromium/cc/debug/rasterize_and_record_benchmark_impl.h49
-rw-r--r--chromium/cc/debug/rendering_stats.cc207
-rw-r--r--chromium/cc/debug/rendering_stats.h31
-rw-r--r--chromium/cc/debug/rendering_stats_instrumentation.cc117
-rw-r--r--chromium/cc/debug/rendering_stats_instrumentation.h39
-rw-r--r--chromium/cc/debug/test_context_provider.cc240
-rw-r--r--chromium/cc/debug/test_context_provider.h90
-rw-r--r--chromium/cc/debug/test_web_graphics_context_3d.cc632
-rw-r--r--chromium/cc/debug/test_web_graphics_context_3d.h292
-rw-r--r--chromium/cc/debug/traced_picture.cc14
-rw-r--r--chromium/cc/debug/traced_picture.h8
-rw-r--r--chromium/cc/debug/traced_value.cc7
-rw-r--r--chromium/cc/debug/traced_value.h5
-rw-r--r--chromium/cc/debug/unittest_only_benchmark.cc55
-rw-r--r--chromium/cc/debug/unittest_only_benchmark.h35
-rw-r--r--chromium/cc/debug/unittest_only_benchmark_impl.cc24
-rw-r--r--chromium/cc/debug/unittest_only_benchmark_impl.h31
-rw-r--r--chromium/cc/input/input_handler.h12
-rw-r--r--chromium/cc/input/layer_scroll_offset_delegate.h20
-rw-r--r--chromium/cc/input/top_controls_manager.cc27
-rw-r--r--chromium/cc/input/top_controls_manager.h7
-rw-r--r--chromium/cc/input/top_controls_manager_unittest.cc96
-rw-r--r--chromium/cc/layers/append_quads_data.h8
-rw-r--r--chromium/cc/layers/compositing_reasons.h2
-rw-r--r--chromium/cc/layers/content_layer.cc6
-rw-r--r--chromium/cc/layers/content_layer.h6
-rw-r--r--chromium/cc/layers/delegated_frame_provider.cc110
-rw-r--r--chromium/cc/layers/delegated_frame_provider.h75
-rw-r--r--chromium/cc/layers/delegated_frame_provider_unittest.cc395
-rw-r--r--chromium/cc/layers/delegated_frame_resource_collection.cc133
-rw-r--r--chromium/cc/layers/delegated_frame_resource_collection.h71
-rw-r--r--chromium/cc/layers/delegated_frame_resource_collection_unittest.cc160
-rw-r--r--chromium/cc/layers/delegated_renderer_layer.cc138
-rw-r--r--chromium/cc/layers/delegated_renderer_layer.h40
-rw-r--r--chromium/cc/layers/delegated_renderer_layer_client.h23
-rw-r--r--chromium/cc/layers/delegated_renderer_layer_impl.cc59
-rw-r--r--chromium/cc/layers/delegated_renderer_layer_impl.h2
-rw-r--r--chromium/cc/layers/delegated_renderer_layer_impl_unittest.cc169
-rw-r--r--chromium/cc/layers/draw_properties.h38
-rw-r--r--chromium/cc/layers/heads_up_display_layer_impl.cc31
-rw-r--r--chromium/cc/layers/heads_up_display_layer_impl.h3
-rw-r--r--chromium/cc/layers/heads_up_display_layer_impl_unittest.cc55
-rw-r--r--chromium/cc/layers/image_layer.cc6
-rw-r--r--chromium/cc/layers/image_layer.h1
-rw-r--r--chromium/cc/layers/io_surface_layer_impl.cc25
-rw-r--r--chromium/cc/layers/layer.cc203
-rw-r--r--chromium/cc/layers/layer.h99
-rw-r--r--chromium/cc/layers/layer_client.h13
-rw-r--r--chromium/cc/layers/layer_impl.cc184
-rw-r--r--chromium/cc/layers/layer_impl.h124
-rw-r--r--chromium/cc/layers/layer_impl_unittest.cc88
-rw-r--r--chromium/cc/layers/layer_iterator.cc95
-rw-r--r--chromium/cc/layers/layer_iterator.h35
-rw-r--r--chromium/cc/layers/layer_iterator_unittest.cc51
-rw-r--r--chromium/cc/layers/layer_lists.cc7
-rw-r--r--chromium/cc/layers/layer_lists.h2
-rw-r--r--chromium/cc/layers/layer_perftest.cc120
-rw-r--r--chromium/cc/layers/layer_position_constraint_unittest.cc115
-rw-r--r--chromium/cc/layers/layer_unittest.cc87
-rw-r--r--chromium/cc/layers/nine_patch_layer.cc96
-rw-r--r--chromium/cc/layers/nine_patch_layer.h21
-rw-r--r--chromium/cc/layers/nine_patch_layer_impl.cc89
-rw-r--r--chromium/cc/layers/nine_patch_layer_impl.h17
-rw-r--r--chromium/cc/layers/nine_patch_layer_impl_unittest.cc40
-rw-r--r--chromium/cc/layers/nine_patch_layer_unittest.cc55
-rw-r--r--chromium/cc/layers/painted_scrollbar_layer.cc32
-rw-r--r--chromium/cc/layers/painted_scrollbar_layer.h9
-rw-r--r--chromium/cc/layers/painted_scrollbar_layer_impl.cc5
-rw-r--r--chromium/cc/layers/painted_scrollbar_layer_impl.h2
-rw-r--r--chromium/cc/layers/picture_image_layer_impl.cc33
-rw-r--r--chromium/cc/layers/picture_image_layer_impl.h15
-rw-r--r--chromium/cc/layers/picture_image_layer_impl_unittest.cc85
-rw-r--r--chromium/cc/layers/picture_layer.cc42
-rw-r--r--chromium/cc/layers/picture_layer.h8
-rw-r--r--chromium/cc/layers/picture_layer_impl.cc280
-rw-r--r--chromium/cc/layers/picture_layer_impl.h21
-rw-r--r--chromium/cc/layers/picture_layer_impl_unittest.cc394
-rw-r--r--chromium/cc/layers/render_surface.cc2
-rw-r--r--chromium/cc/layers/render_surface.h13
-rw-r--r--chromium/cc/layers/render_surface_impl.cc10
-rw-r--r--chromium/cc/layers/render_surface_impl.h27
-rw-r--r--chromium/cc/layers/scrollbar_layer_impl_base.cc7
-rw-r--r--chromium/cc/layers/scrollbar_layer_impl_base.h4
-rw-r--r--chromium/cc/layers/scrollbar_layer_unittest.cc9
-rw-r--r--chromium/cc/layers/texture_layer.cc45
-rw-r--r--chromium/cc/layers/texture_layer.h9
-rw-r--r--chromium/cc/layers/texture_layer_client.h6
-rw-r--r--chromium/cc/layers/texture_layer_impl.cc14
-rw-r--r--chromium/cc/layers/texture_layer_impl.h2
-rw-r--r--chromium/cc/layers/texture_layer_unittest.cc263
-rw-r--r--chromium/cc/layers/tiled_layer.cc55
-rw-r--r--chromium/cc/layers/tiled_layer.h16
-rw-r--r--chromium/cc/layers/tiled_layer_impl.cc26
-rw-r--r--chromium/cc/layers/tiled_layer_impl_unittest.cc10
-rw-r--r--chromium/cc/layers/tiled_layer_unittest.cc18
-rw-r--r--chromium/cc/layers/ui_resource_layer.cc165
-rw-r--r--chromium/cc/layers/ui_resource_layer.h73
-rw-r--r--chromium/cc/layers/ui_resource_layer_impl.cc157
-rw-r--r--chromium/cc/layers/ui_resource_layer_impl.h73
-rw-r--r--chromium/cc/layers/ui_resource_layer_impl_unittest.cc152
-rw-r--r--chromium/cc/layers/ui_resource_layer_unittest.cc114
-rw-r--r--chromium/cc/layers/video_layer_impl.cc24
-rw-r--r--chromium/cc/output/begin_frame_args.cc7
-rw-r--r--chromium/cc/output/context_provider.cc24
-rw-r--r--chromium/cc/output/context_provider.h58
-rw-r--r--chromium/cc/output/copy_output_request.cc25
-rw-r--r--chromium/cc/output/copy_output_request.h28
-rw-r--r--chromium/cc/output/delegating_renderer.cc67
-rw-r--r--chromium/cc/output/delegating_renderer.h11
-rw-r--r--chromium/cc/output/direct_renderer.cc101
-rw-r--r--chromium/cc/output/direct_renderer.h38
-rw-r--r--chromium/cc/output/filter_operation.cc114
-rw-r--r--chromium/cc/output/filter_operation.h28
-rw-r--r--chromium/cc/output/filter_operations.cc66
-rw-r--r--chromium/cc/output/filter_operations.h21
-rw-r--r--chromium/cc/output/filter_operations_unittest.cc81
-rw-r--r--chromium/cc/output/geometry_binding.cc141
-rw-r--r--chromium/cc/output/geometry_binding.h20
-rw-r--r--chromium/cc/output/gl_renderer.cc2162
-rw-r--r--chromium/cc/output/gl_renderer.h175
-rw-r--r--chromium/cc/output/gl_renderer_unittest.cc1341
-rw-r--r--chromium/cc/output/managed_memory_policy.cc42
-rw-r--r--chromium/cc/output/managed_memory_policy.h27
-rw-r--r--chromium/cc/output/output_surface.cc279
-rw-r--r--chromium/cc/output/output_surface.h67
-rw-r--r--chromium/cc/output/output_surface_client.h4
-rw-r--r--chromium/cc/output/output_surface_unittest.cc237
-rw-r--r--chromium/cc/output/program_binding.cc109
-rw-r--r--chromium/cc/output/program_binding.h61
-rw-r--r--chromium/cc/output/render_surface_filters.cc386
-rw-r--r--chromium/cc/output/render_surface_filters.h6
-rw-r--r--chromium/cc/output/render_surface_filters_unittest.cc140
-rw-r--r--chromium/cc/output/renderer.cc2
-rw-r--r--chromium/cc/output/renderer.h24
-rw-r--r--chromium/cc/output/renderer_pixeltest.cc475
-rw-r--r--chromium/cc/output/shader.cc388
-rw-r--r--chromium/cc/output/shader.h198
-rw-r--r--chromium/cc/output/shader_unittest.cc27
-rw-r--r--chromium/cc/output/software_output_device.cc5
-rw-r--r--chromium/cc/output/software_output_device.h10
-rw-r--r--chromium/cc/output/software_renderer.cc103
-rw-r--r--chromium/cc/output/software_renderer.h3
-rw-r--r--chromium/cc/output/software_renderer_unittest.cc116
-rw-r--r--chromium/cc/quads/draw_quad.cc7
-rw-r--r--chromium/cc/quads/draw_quad_unittest.cc169
-rw-r--r--chromium/cc/quads/picture_draw_quad.cc6
-rw-r--r--chromium/cc/quads/picture_draw_quad.h3
-rw-r--r--chromium/cc/quads/render_pass.cc86
-rw-r--r--chromium/cc/quads/render_pass.h16
-rw-r--r--chromium/cc/quads/render_pass_draw_quad.cc8
-rw-r--r--chromium/cc/quads/render_pass_draw_quad.h7
-rw-r--r--chromium/cc/quads/render_pass_unittest.cc245
-rw-r--r--chromium/cc/quads/shared_quad_state.cc19
-rw-r--r--chromium/cc/quads/shared_quad_state.h5
-rw-r--r--chromium/cc/quads/texture_draw_quad.cc74
-rw-r--r--chromium/cc/quads/texture_draw_quad.h2
-rw-r--r--chromium/cc/resources/bitmap_content_layer_updater.cc10
-rw-r--r--chromium/cc/resources/bitmap_content_layer_updater.h2
-rw-r--r--chromium/cc/resources/bitmap_skpicture_content_layer_updater.cc8
-rw-r--r--chromium/cc/resources/content_layer_updater.cc10
-rw-r--r--chromium/cc/resources/etc1_pixel_ref.cc38
-rw-r--r--chromium/cc/resources/etc1_pixel_ref.h44
-rw-r--r--chromium/cc/resources/image_raster_worker_pool.cc16
-rw-r--r--chromium/cc/resources/image_raster_worker_pool.h14
-rw-r--r--chromium/cc/resources/managed_tile_state.cc21
-rw-r--r--chromium/cc/resources/managed_tile_state.h4
-rw-r--r--chromium/cc/resources/picture.cc79
-rw-r--r--chromium/cc/resources/picture.h27
-rw-r--r--chromium/cc/resources/picture_layer_tiling.cc112
-rw-r--r--chromium/cc/resources/picture_layer_tiling.h32
-rw-r--r--chromium/cc/resources/picture_layer_tiling_perftest.cc5
-rw-r--r--chromium/cc/resources/picture_layer_tiling_set.cc5
-rw-r--r--chromium/cc/resources/picture_layer_tiling_set.h1
-rw-r--r--chromium/cc/resources/picture_layer_tiling_set_unittest.cc4
-rw-r--r--chromium/cc/resources/picture_layer_tiling_unittest.cc38
-rw-r--r--chromium/cc/resources/picture_pile.cc298
-rw-r--r--chromium/cc/resources/picture_pile.h7
-rw-r--r--chromium/cc/resources/picture_pile_base.cc189
-rw-r--r--chromium/cc/resources/picture_pile_base.h53
-rw-r--r--chromium/cc/resources/picture_pile_impl.cc320
-rw-r--r--chromium/cc/resources/picture_pile_impl.h41
-rw-r--r--chromium/cc/resources/picture_pile_impl_unittest.cc162
-rw-r--r--chromium/cc/resources/picture_pile_unittest.cc200
-rw-r--r--chromium/cc/resources/picture_unittest.cc39
-rw-r--r--chromium/cc/resources/pixel_buffer_raster_worker_pool.cc8
-rw-r--r--chromium/cc/resources/pixel_buffer_raster_worker_pool.h1
-rw-r--r--chromium/cc/resources/prioritized_resource.cc7
-rw-r--r--chromium/cc/resources/prioritized_resource.h7
-rw-r--r--chromium/cc/resources/prioritized_resource_manager.cc42
-rw-r--r--chromium/cc/resources/prioritized_resource_manager.h25
-rw-r--r--chromium/cc/resources/prioritized_resource_unittest.cc412
-rw-r--r--chromium/cc/resources/prioritized_tile_set_unittest.cc27
-rw-r--r--chromium/cc/resources/priority_calculator.cc11
-rw-r--r--chromium/cc/resources/raster_worker_pool.cc55
-rw-r--r--chromium/cc/resources/raster_worker_pool.h10
-rw-r--r--chromium/cc/resources/raster_worker_pool_perftest.cc5
-rw-r--r--chromium/cc/resources/raster_worker_pool_unittest.cc10
-rw-r--r--chromium/cc/resources/resource.cc3
-rw-r--r--chromium/cc/resources/resource.h5
-rw-r--r--chromium/cc/resources/resource_format.cc3
-rw-r--r--chromium/cc/resources/resource_format.h6
-rw-r--r--chromium/cc/resources/resource_pool.cc86
-rw-r--r--chromium/cc/resources/resource_pool.h39
-rw-r--r--chromium/cc/resources/resource_provider.cc976
-rw-r--r--chromium/cc/resources/resource_provider.h101
-rw-r--r--chromium/cc/resources/resource_provider_unittest.cc1735
-rw-r--r--chromium/cc/resources/resource_update_controller.cc35
-rw-r--r--chromium/cc/resources/resource_update_controller.h6
-rw-r--r--chromium/cc/resources/resource_update_controller_unittest.cc106
-rw-r--r--chromium/cc/resources/scoped_resource.cc21
-rw-r--r--chromium/cc/resources/scoped_resource.h7
-rw-r--r--chromium/cc/resources/scoped_resource_unittest.cc18
-rw-r--r--chromium/cc/resources/shared_bitmap.cc17
-rw-r--r--chromium/cc/resources/shared_bitmap.h51
-rw-r--r--chromium/cc/resources/shared_bitmap_manager.h32
-rw-r--r--chromium/cc/resources/sync_point_helper.cc48
-rw-r--r--chromium/cc/resources/sync_point_helper.h44
-rw-r--r--chromium/cc/resources/texture_mailbox_deleter.cc6
-rw-r--r--chromium/cc/resources/texture_mailbox_deleter.h2
-rw-r--r--chromium/cc/resources/texture_mailbox_deleter_unittest.cc4
-rw-r--r--chromium/cc/resources/tile.cc17
-rw-r--r--chromium/cc/resources/tile.h57
-rw-r--r--chromium/cc/resources/tile_manager.cc360
-rw-r--r--chromium/cc/resources/tile_manager.h66
-rw-r--r--chromium/cc/resources/tile_manager_perftest.cc33
-rw-r--r--chromium/cc/resources/tile_manager_unittest.cc80
-rw-r--r--chromium/cc/resources/tile_priority.cc8
-rw-r--r--chromium/cc/resources/tile_priority.h33
-rw-r--r--chromium/cc/resources/tile_priority_unittest.cc14
-rw-r--r--chromium/cc/resources/transferable_resource.cc5
-rw-r--r--chromium/cc/resources/transferable_resource.h2
-rw-r--r--chromium/cc/resources/ui_resource_bitmap.cc20
-rw-r--r--chromium/cc/resources/ui_resource_bitmap.h23
-rw-r--r--chromium/cc/resources/ui_resource_request.cc37
-rw-r--r--chromium/cc/resources/ui_resource_request.h49
-rw-r--r--chromium/cc/resources/video_resource_updater.cc85
-rw-r--r--chromium/cc/resources/video_resource_updater.h4
-rw-r--r--chromium/cc/resources/video_resource_updater_unittest.cc4
-rw-r--r--chromium/cc/scheduler/delay_based_time_source.cc21
-rw-r--r--chromium/cc/scheduler/delay_based_time_source.h19
-rw-r--r--chromium/cc/scheduler/frame_rate_controller.cc23
-rw-r--r--chromium/cc/scheduler/frame_rate_controller.h3
-rw-r--r--chromium/cc/scheduler/frame_rate_controller_unittest.cc35
-rw-r--r--chromium/cc/scheduler/rate_limiter.cc61
-rw-r--r--chromium/cc/scheduler/rate_limiter.h61
-rw-r--r--chromium/cc/scheduler/scheduler.cc220
-rw-r--r--chromium/cc/scheduler/scheduler.h51
-rw-r--r--chromium/cc/scheduler/scheduler_settings.cc5
-rw-r--r--chromium/cc/scheduler/scheduler_settings.h1
-rw-r--r--chromium/cc/scheduler/scheduler_state_machine.cc329
-rw-r--r--chromium/cc/scheduler/scheduler_state_machine.h102
-rw-r--r--chromium/cc/scheduler/scheduler_state_machine_unittest.cc587
-rw-r--r--chromium/cc/scheduler/scheduler_unittest.cc680
-rw-r--r--chromium/cc/scheduler/texture_uploader.cc109
-rw-r--r--chromium/cc/scheduler/texture_uploader.h33
-rw-r--r--chromium/cc/scheduler/texture_uploader_unittest.cc68
-rw-r--r--chromium/cc/trees/damage_tracker.cc137
-rw-r--r--chromium/cc/trees/damage_tracker.h36
-rw-r--r--chromium/cc/trees/damage_tracker_unittest.cc10
-rw-r--r--chromium/cc/trees/layer_sorter_unittest.cc4
-rw-r--r--chromium/cc/trees/layer_tree_host.cc291
-rw-r--r--chromium/cc/trees/layer_tree_host.h155
-rw-r--r--chromium/cc/trees/layer_tree_host_client.h21
-rw-r--r--chromium/cc/trees/layer_tree_host_common.cc542
-rw-r--r--chromium/cc/trees/layer_tree_host_common.h9
-rw-r--r--chromium/cc/trees/layer_tree_host_common_perftest.cc198
-rw-r--r--chromium/cc/trees/layer_tree_host_common_unittest.cc1013
-rw-r--r--chromium/cc/trees/layer_tree_host_impl.cc728
-rw-r--r--chromium/cc/trees/layer_tree_host_impl.h119
-rw-r--r--chromium/cc/trees/layer_tree_host_impl_unittest.cc2747
-rw-r--r--chromium/cc/trees/layer_tree_host_perftest.cc131
-rw-r--r--chromium/cc/trees/layer_tree_host_pixeltest_blending.cc120
-rw-r--r--chromium/cc/trees/layer_tree_host_pixeltest_filters.cc97
-rw-r--r--chromium/cc/trees/layer_tree_host_pixeltest_masks.cc7
-rw-r--r--chromium/cc/trees/layer_tree_host_pixeltest_on_demand_raster.cc4
-rw-r--r--chromium/cc/trees/layer_tree_host_pixeltest_readback.cc48
-rw-r--r--chromium/cc/trees/layer_tree_host_single_thread_client.h33
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest.cc1581
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest_animation.cc137
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest_context.cc922
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc908
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest_damage.cc134
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest_delegated.cc901
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest_occlusion.cc146
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest_scroll.cc24
-rw-r--r--chromium/cc/trees/layer_tree_impl.cc134
-rw-r--r--chromium/cc/trees/layer_tree_impl.h33
-rw-r--r--chromium/cc/trees/layer_tree_settings.cc18
-rw-r--r--chromium/cc/trees/layer_tree_settings.h9
-rw-r--r--chromium/cc/trees/occlusion_tracker.cc146
-rw-r--r--chromium/cc/trees/occlusion_tracker.h26
-rw-r--r--chromium/cc/trees/occlusion_tracker_unittest.cc1529
-rw-r--r--chromium/cc/trees/proxy.h1
-rw-r--r--chromium/cc/trees/quad_culler.cc16
-rw-r--r--chromium/cc/trees/quad_culler_unittest.cc517
-rw-r--r--chromium/cc/trees/single_thread_proxy.cc133
-rw-r--r--chromium/cc/trees/single_thread_proxy.h28
-rw-r--r--chromium/cc/trees/thread_proxy.cc386
-rw-r--r--chromium/cc/trees/thread_proxy.h76
-rw-r--r--chromium/cc/trees/tree_synchronizer_unittest.cc21
375 files changed, 25850 insertions, 18857 deletions
diff --git a/chromium/cc/DEPS b/chromium/cc/DEPS
index 91ebb2067c9..2ae5c7bdef5 100644
--- a/chromium/cc/DEPS
+++ b/chromium/cc/DEPS
@@ -1,5 +1,10 @@
include_rules = [
"+gpu/GLES2",
+ "+gpu/command_buffer/client/context_support.h",
+ "+gpu/command_buffer/client/gles2_interface.h",
+ "+gpu/command_buffer/client/gles2_interface_stub.h", # for tests
+ "+gpu/command_buffer/common/gpu_memory_allocation.h",
+ "+gpu/command_buffer/common/capabilities.h",
"+gpu/command_buffer/common/mailbox.h",
"+media",
"+skia/ext",
diff --git a/chromium/cc/PRESUBMIT.py b/chromium/cc/PRESUBMIT.py
index 9e84e3f6609..5b8100b8266 100644
--- a/chromium/cc/PRESUBMIT.py
+++ b/chromium/cc/PRESUBMIT.py
@@ -12,7 +12,6 @@ import re
import string
CC_SOURCE_FILES=(r'^cc/.*\.(cc|h)$',)
-CC_PERF_TEST =(r'^.*_perftest.*\.(cc|h)$',)
def CheckChangeLintsClean(input_api, output_api):
input_api.cpplint._cpplint_state.ResetErrorCounts() # reset global state
@@ -103,35 +102,6 @@ def CheckStdAbs(input_api, output_api,
items=missing_std_prefix_files))
return result
-def CheckSpamLogging(input_api,
- output_api,
- white_list=CC_SOURCE_FILES,
- black_list=None):
- black_list = tuple(black_list or input_api.DEFAULT_BLACK_LIST)
- source_file_filter = lambda x: input_api.FilterSourceFile(x,
- white_list,
- black_list)
-
- log_info = []
- printf = []
-
- for f in input_api.AffectedSourceFiles(source_file_filter):
- contents = input_api.ReadFile(f, 'rb')
- if re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", contents):
- log_info.append(f.LocalPath())
- if re.search(r"\bf?printf\(", contents):
- printf.append(f.LocalPath())
-
- if log_info:
- return [output_api.PresubmitError(
- 'These files spam the console log with LOG(INFO):',
- items=log_info)]
- if printf:
- return [output_api.PresubmitError(
- 'These files spam the console log with printf/fprintf:',
- items=printf)]
- return []
-
def CheckPassByValue(input_api,
output_api,
white_list=CC_SOURCE_FILES,
@@ -182,18 +152,89 @@ def CheckTodos(input_api, output_api):
items=errors)]
return []
+def FindUnquotedQuote(contents, pos):
+ match = re.search(r"(?<!\\)(?P<quote>\")", contents[pos:])
+ return -1 if not match else match.start("quote") + pos
+
+def FindNamespaceInBlock(pos, namespace, contents, whitelist=[]):
+ open_brace = -1
+ close_brace = -1
+ quote = -1
+ name = -1
+ brace_count = 1
+ quote_count = 0
+ while pos < len(contents) and brace_count > 0:
+ if open_brace < pos: open_brace = contents.find("{", pos)
+ if close_brace < pos: close_brace = contents.find("}", pos)
+ if quote < pos: quote = FindUnquotedQuote(contents, pos)
+ if name < pos: name = contents.find(("%s::" % namespace), pos)
+
+ if name < 0:
+ return False # The namespace is not used at all.
+ if open_brace < 0:
+ open_brace = len(contents)
+ if close_brace < 0:
+ close_brace = len(contents)
+ if quote < 0:
+ quote = len(contents)
+
+ next = min(open_brace, min(close_brace, min(quote, name)))
+
+ if next == open_brace:
+ brace_count += 1
+ elif next == close_brace:
+ brace_count -= 1
+ elif next == quote:
+ quote_count = 0 if quote_count else 1
+ elif next == name and not quote_count:
+ in_whitelist = False
+ for w in whitelist:
+ if re.match(w, contents[next:]):
+ in_whitelist = True
+ break
+ if not in_whitelist:
+ return True
+ pos = next + 1
+ return False
+
+# Checks for the use of cc:: within the cc namespace, which is usually
+# redundant.
+def CheckNamespace(input_api, output_api):
+ errors = []
+
+ source_file_filter = lambda x: x
+ for f in input_api.AffectedSourceFiles(source_file_filter):
+ contents = input_api.ReadFile(f, 'rb')
+ match = re.search(r'namespace\s*cc\s*{', contents)
+ if match:
+ whitelist = [
+ r"cc::remove_if\b",
+ ]
+ if FindNamespaceInBlock(match.end(), 'cc', contents, whitelist=whitelist):
+ errors.append(f.LocalPath())
+
+ if errors:
+ return [output_api.PresubmitError(
+ 'Do not use cc:: inside of the cc namespace.',
+ items=errors)]
+ return []
+
def CheckChangeOnUpload(input_api, output_api):
results = []
results += CheckAsserts(input_api, output_api)
results += CheckStdAbs(input_api, output_api)
- results += CheckSpamLogging(input_api, output_api, black_list=CC_PERF_TEST)
results += CheckPassByValue(input_api, output_api)
results += CheckChangeLintsClean(input_api, output_api)
results += CheckTodos(input_api, output_api)
+ results += CheckNamespace(input_api, output_api)
return results
def GetPreferredTrySlaves(project, change):
return [
'linux_layout_rel',
- ]
+ 'win_gpu',
+ 'linux_gpu',
+ 'mac_gpu',
+ 'mac_gpu_retina',
+ ]
diff --git a/chromium/cc/animation/animation.cc b/chromium/cc/animation/animation.cc
index b509cfd994f..f21a1d48486 100644
--- a/chromium/cc/animation/animation.cc
+++ b/chromium/cc/animation/animation.cc
@@ -14,9 +14,7 @@ namespace {
// This should match the RunState enum.
static const char* const s_runStateNames[] = {
- "WaitingForNextTick",
"WaitingForTargetAvailability",
- "WaitingForStartTime",
"WaitingForDeletion",
"Starting",
"Running",
@@ -32,7 +30,10 @@ COMPILE_ASSERT(static_cast<int>(cc::Animation::RunStateEnumSize) ==
// This should match the TargetProperty enum.
static const char* const s_targetPropertyNames[] = {
"Transform",
- "Opacity"
+ "Opacity",
+ "Filter",
+ "BackgroundColor",
+ "ScrollOffset"
};
COMPILE_ASSERT(static_cast<int>(cc::Animation::TargetPropertyEnumSize) ==
@@ -91,9 +92,7 @@ void Animation::SetRunState(RunState run_state, double monotonic_time) {
group_,
is_controlling_instance_ ? "(impl)" : "");
- bool is_waiting_to_start = run_state_ == WaitingForNextTick ||
- run_state_ == WaitingForTargetAvailability ||
- run_state_ == WaitingForStartTime ||
+ bool is_waiting_to_start = run_state_ == WaitingForTargetAvailability ||
run_state_ == Starting;
if (is_waiting_to_start && run_state == Running) {
@@ -153,7 +152,8 @@ bool Animation::IsFinishedAt(double monotonic_time) const {
iterations_ >= 0 &&
iterations_ * curve_->Duration() <= (monotonic_time -
start_time() -
- total_paused_time_);
+ total_paused_time_ +
+ time_offset_);
}
double Animation::TrimTimeToCurrentIteration(double monotonic_time) const {
@@ -210,12 +210,11 @@ double Animation::TrimTimeToCurrentIteration(double monotonic_time) const {
return trimmed;
}
-scoped_ptr<Animation> Animation::Clone(InstanceType instance_type) const {
- return CloneAndInitialize(instance_type, run_state_, start_time_);
+scoped_ptr<Animation> Animation::Clone() const {
+ return CloneAndInitialize(run_state_, start_time_);
}
-scoped_ptr<Animation> Animation::CloneAndInitialize(InstanceType instance_type,
- RunState initial_run_state,
+scoped_ptr<Animation> Animation::CloneAndInitialize(RunState initial_run_state,
double start_time) const {
scoped_ptr<Animation> to_return(
new Animation(curve_->Clone(), id_, group_, target_property_));
@@ -226,7 +225,8 @@ scoped_ptr<Animation> Animation::CloneAndInitialize(InstanceType instance_type,
to_return->total_paused_time_ = total_paused_time_;
to_return->time_offset_ = time_offset_;
to_return->alternates_direction_ = alternates_direction_;
- to_return->is_controlling_instance_ = instance_type == ControllingInstance;
+ DCHECK(!to_return->is_controlling_instance_);
+ to_return->is_controlling_instance_ = true;
return to_return.Pass();
}
diff --git a/chromium/cc/animation/animation.h b/chromium/cc/animation/animation.h
index 990b9ef82cb..c7d53c2745e 100644
--- a/chromium/cc/animation/animation.h
+++ b/chromium/cc/animation/animation.h
@@ -13,26 +13,21 @@ namespace cc {
class AnimationCurve;
-// An Animation, contains all the state required to play an AnimationCurve.
+// An Animation contains all the state required to play an AnimationCurve.
// Specifically, the affected property, the run state (paused, finished, etc.),
// loop count, last pause time, and the total time spent paused.
class CC_EXPORT Animation {
public:
- // Animations begin in one of the 'waiting' states. Animations waiting for the
- // next tick will start the next time the controller animates. Animations
- // waiting for target availibility will run as soon as their target property
+ // Animations begin in the 'WaitingForTargetAvailability' state. An Animation
+ // waiting for target availibility will run as soon as its target property
// is free (and all the animations animating with it are also able to run).
- // Animations waiting for their start time to come have be scheduled to run at
- // a particular point in time. When this time arrives, the controller will
- // move the animations into the Starting state, and then into the Running
- // state. Running animations may toggle between Running and Paused, and may be
- // stopped by moving into either the Aborted or Finished states. A Finished
- // animation was allowed to run to completion, but an Aborted animation was
- // not.
+ // When this time arrives, the controller will move the animation into the
+ // Starting state, and then into the Running state. Running animations may
+ // toggle between Running and Paused, and may be stopped by moving into either
+ // the Aborted or Finished states. A Finished animation was allowed to run to
+ // completion, but an Aborted animation was not.
enum RunState {
- WaitingForNextTick = 0,
- WaitingForTargetAvailability,
- WaitingForStartTime,
+ WaitingForTargetAvailability = 0,
WaitingForDeletion,
Starting,
Running,
@@ -46,6 +41,9 @@ class CC_EXPORT Animation {
enum TargetProperty {
Transform = 0,
Opacity,
+ Filter,
+ BackgroundColor,
+ ScrollOffset,
// This sentinel must be last.
TargetPropertyEnumSize
};
@@ -120,14 +118,8 @@ class CC_EXPORT Animation {
// of iterations, returns the relative time in the current iteration.
double TrimTimeToCurrentIteration(double monotonic_time) const;
- enum InstanceType {
- ControllingInstance = 0,
- NonControllingInstance
- };
-
- scoped_ptr<Animation> Clone(InstanceType instance_type) const;
- scoped_ptr<Animation> CloneAndInitialize(InstanceType instance_type,
- RunState initial_run_state,
+ scoped_ptr<Animation> Clone() const;
+ scoped_ptr<Animation> CloneAndInitialize(RunState initial_run_state,
double start_time) const;
bool is_controlling_instance() const { return is_controlling_instance_; }
diff --git a/chromium/cc/animation/animation_curve.cc b/chromium/cc/animation/animation_curve.cc
index cf04da7f396..3acff5d1f62 100644
--- a/chromium/cc/animation/animation_curve.cc
+++ b/chromium/cc/animation/animation_curve.cc
@@ -5,9 +5,17 @@
#include "cc/animation/animation_curve.h"
#include "base/logging.h"
+#include "cc/animation/scroll_offset_animation_curve.h"
namespace cc {
+const ColorAnimationCurve* AnimationCurve::ToColorAnimationCurve() const {
+ DCHECK(Type() == AnimationCurve::Color);
+ return static_cast<const ColorAnimationCurve*>(this);
+}
+
+AnimationCurve::CurveType ColorAnimationCurve::Type() const { return Color; }
+
const FloatAnimationCurve* AnimationCurve::ToFloatAnimationCurve() const {
DCHECK(Type() == AnimationCurve::Float);
return static_cast<const FloatAnimationCurve*>(this);
@@ -36,4 +44,15 @@ AnimationCurve::CurveType FilterAnimationCurve::Type() const {
return Filter;
}
+const ScrollOffsetAnimationCurve* AnimationCurve::ToScrollOffsetAnimationCurve()
+ const {
+ DCHECK(Type() == AnimationCurve::ScrollOffset);
+ return static_cast<const ScrollOffsetAnimationCurve*>(this);
+}
+
+ScrollOffsetAnimationCurve* AnimationCurve::ToScrollOffsetAnimationCurve() {
+ DCHECK(Type() == AnimationCurve::ScrollOffset);
+ return static_cast<ScrollOffsetAnimationCurve*>(this);
+}
+
} // namespace cc
diff --git a/chromium/cc/animation/animation_curve.h b/chromium/cc/animation/animation_curve.h
index f4cdb10560c..9bcccba1294 100644
--- a/chromium/cc/animation/animation_curve.h
+++ b/chromium/cc/animation/animation_curve.h
@@ -16,15 +16,17 @@ class BoxF;
namespace cc {
+class ColorAnimationCurve;
class FilterAnimationCurve;
class FloatAnimationCurve;
+class ScrollOffsetAnimationCurve;
class TransformAnimationCurve;
class TransformOperations;
// An animation curve is a function that returns a value given a time.
class CC_EXPORT AnimationCurve {
public:
- enum CurveType { Float, Transform, Filter };
+ enum CurveType { Color, Float, Transform, Filter, ScrollOffset };
virtual ~AnimationCurve() {}
@@ -32,9 +34,23 @@ class CC_EXPORT AnimationCurve {
virtual CurveType Type() const = 0;
virtual scoped_ptr<AnimationCurve> Clone() const = 0;
+ const ColorAnimationCurve* ToColorAnimationCurve() const;
const FloatAnimationCurve* ToFloatAnimationCurve() const;
const TransformAnimationCurve* ToTransformAnimationCurve() const;
const FilterAnimationCurve* ToFilterAnimationCurve() const;
+ const ScrollOffsetAnimationCurve* ToScrollOffsetAnimationCurve() const;
+
+ ScrollOffsetAnimationCurve* ToScrollOffsetAnimationCurve();
+};
+
+class CC_EXPORT ColorAnimationCurve : public AnimationCurve {
+ public:
+ virtual ~ColorAnimationCurve() {}
+
+ virtual SkColor GetValue(double t) const = 0;
+
+ // Partial Animation implementation.
+ virtual CurveType Type() const OVERRIDE;
};
class CC_EXPORT FloatAnimationCurve : public AnimationCurve {
diff --git a/chromium/cc/animation/animation_delegate.h b/chromium/cc/animation/animation_delegate.h
index c9367b8546a..f1176a36a46 100644
--- a/chromium/cc/animation/animation_delegate.h
+++ b/chromium/cc/animation/animation_delegate.h
@@ -5,12 +5,23 @@
#ifndef CC_ANIMATION_ANIMATION_DELEGATE_H_
#define CC_ANIMATION_ANIMATION_DELEGATE_H_
+#include "base/time/time.h"
+#include "cc/animation/animation.h"
+
namespace cc {
class AnimationDelegate {
public:
- virtual void NotifyAnimationStarted(double time) = 0;
- virtual void NotifyAnimationFinished(double time) = 0;
+ // TODO(ajuma): Remove wall_clock_time once the legacy implementation of
+ // CSS animations and transitions in Blink is removed.
+ virtual void NotifyAnimationStarted(
+ double wall_clock_time,
+ base::TimeTicks monotonic_time,
+ Animation::TargetProperty target_property) = 0;
+ virtual void NotifyAnimationFinished(
+ double wall_clock_time,
+ base::TimeTicks monotonic_time,
+ Animation::TargetProperty target_property) = 0;
protected:
virtual ~AnimationDelegate() {}
diff --git a/chromium/cc/animation/animation_events.h b/chromium/cc/animation/animation_events.h
index 1fd742c9a8b..e0cf73645c9 100644
--- a/chromium/cc/animation/animation_events.h
+++ b/chromium/cc/animation/animation_events.h
@@ -9,12 +9,13 @@
#include "cc/animation/animation.h"
#include "cc/base/cc_export.h"
+#include "cc/output/filter_operations.h"
#include "ui/gfx/transform.h"
namespace cc {
struct CC_EXPORT AnimationEvent {
- enum Type { Started, Finished, PropertyUpdate };
+ enum Type { Started, Finished, Aborted, PropertyUpdate };
AnimationEvent(Type type,
int layer_id,
@@ -30,6 +31,7 @@ struct CC_EXPORT AnimationEvent {
bool is_impl_only;
float opacity;
gfx::Transform transform;
+ FilterOperations filters;
};
typedef std::vector<AnimationEvent> AnimationEventsVector;
diff --git a/chromium/cc/animation/animation_unittest.cc b/chromium/cc/animation/animation_unittest.cc
index 23d41697679..8223cee5855 100644
--- a/chromium/cc/animation/animation_unittest.cc
+++ b/chromium/cc/animation/animation_unittest.cc
@@ -78,6 +78,16 @@ TEST(AnimationTest, TrimTimeTimeOffset) {
EXPECT_EQ(1, anim->TrimTimeToCurrentIteration(1.0));
}
+TEST(AnimationTest, TrimTimeNegativeTimeOffset) {
+ scoped_ptr<Animation> anim(CreateAnimation(1));
+ anim->set_time_offset(-4);
+
+ EXPECT_EQ(0, anim->TrimTimeToCurrentIteration(0.0));
+ EXPECT_EQ(0, anim->TrimTimeToCurrentIteration(4.0));
+ EXPECT_EQ(0.5, anim->TrimTimeToCurrentIteration(4.5));
+ EXPECT_EQ(1, anim->TrimTimeToCurrentIteration(5.0));
+}
+
TEST(AnimationTest, TrimTimePauseResume) {
scoped_ptr<Animation> anim(CreateAnimation(1));
anim->SetRunState(Animation::Running, 0.0);
@@ -171,18 +181,39 @@ TEST(AnimationTest, IsFinishedAtInfiniteIterations) {
EXPECT_FALSE(anim->IsFinishedAt(1.5));
}
+TEST(AnimationTest, IsFinishedNegativeTimeOffset) {
+ scoped_ptr<Animation> anim(CreateAnimation(1));
+ anim->set_time_offset(-0.5);
+ anim->SetRunState(Animation::Running, 0.0);
+
+ EXPECT_FALSE(anim->IsFinishedAt(-1.0));
+ EXPECT_FALSE(anim->IsFinishedAt(0.0));
+ EXPECT_FALSE(anim->IsFinishedAt(0.5));
+ EXPECT_FALSE(anim->IsFinishedAt(1.0));
+ EXPECT_TRUE(anim->IsFinishedAt(1.5));
+ EXPECT_TRUE(anim->IsFinishedAt(2.0));
+ EXPECT_TRUE(anim->IsFinishedAt(2.5));
+}
+
+TEST(AnimationTest, IsFinishedPositiveTimeOffset) {
+ scoped_ptr<Animation> anim(CreateAnimation(1));
+ anim->set_time_offset(0.5);
+ anim->SetRunState(Animation::Running, 0.0);
+
+ EXPECT_FALSE(anim->IsFinishedAt(-1.0));
+ EXPECT_FALSE(anim->IsFinishedAt(0.0));
+ EXPECT_TRUE(anim->IsFinishedAt(0.5));
+ EXPECT_TRUE(anim->IsFinishedAt(1.0));
+}
+
TEST(AnimationTest, IsFinishedAtNotRunning) {
scoped_ptr<Animation> anim(CreateAnimation(0));
anim->SetRunState(Animation::Running, 0.0);
EXPECT_TRUE(anim->IsFinishedAt(0.0));
anim->SetRunState(Animation::Paused, 0.0);
EXPECT_FALSE(anim->IsFinishedAt(0.0));
- anim->SetRunState(Animation::WaitingForNextTick, 0.0);
- EXPECT_FALSE(anim->IsFinishedAt(0.0));
anim->SetRunState(Animation::WaitingForTargetAvailability, 0.0);
EXPECT_FALSE(anim->IsFinishedAt(0.0));
- anim->SetRunState(Animation::WaitingForStartTime, 0.0);
- EXPECT_FALSE(anim->IsFinishedAt(0.0));
anim->SetRunState(Animation::Finished, 0.0);
EXPECT_TRUE(anim->IsFinishedAt(0.0));
anim->SetRunState(Animation::Aborted, 0.0);
@@ -195,12 +226,8 @@ TEST(AnimationTest, IsFinished) {
EXPECT_FALSE(anim->is_finished());
anim->SetRunState(Animation::Paused, 0.0);
EXPECT_FALSE(anim->is_finished());
- anim->SetRunState(Animation::WaitingForNextTick, 0.0);
- EXPECT_FALSE(anim->is_finished());
anim->SetRunState(Animation::WaitingForTargetAvailability, 0.0);
EXPECT_FALSE(anim->is_finished());
- anim->SetRunState(Animation::WaitingForStartTime, 0.0);
- EXPECT_FALSE(anim->is_finished());
anim->SetRunState(Animation::Finished, 0.0);
EXPECT_TRUE(anim->is_finished());
anim->SetRunState(Animation::Aborted, 0.0);
@@ -213,12 +240,8 @@ TEST(AnimationTest, IsFinishedNeedsSynchronizedStartTime) {
EXPECT_FALSE(anim->is_finished());
anim->SetRunState(Animation::Paused, 2.0);
EXPECT_FALSE(anim->is_finished());
- anim->SetRunState(Animation::WaitingForNextTick, 2.0);
- EXPECT_FALSE(anim->is_finished());
anim->SetRunState(Animation::WaitingForTargetAvailability, 2.0);
EXPECT_FALSE(anim->is_finished());
- anim->SetRunState(Animation::WaitingForStartTime, 2.0);
- EXPECT_FALSE(anim->is_finished());
anim->SetRunState(Animation::Finished, 0.0);
EXPECT_TRUE(anim->is_finished());
anim->SetRunState(Animation::Aborted, 0.0);
diff --git a/chromium/cc/animation/keyframed_animation_curve.cc b/chromium/cc/animation/keyframed_animation_curve.cc
index 14dfd9c8446..d855decbaf9 100644
--- a/chromium/cc/animation/keyframed_animation_curve.cc
+++ b/chromium/cc/animation/keyframed_animation_curve.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "cc/animation/keyframed_animation_curve.h"
+#include "ui/gfx/animation/tween.h"
#include "ui/gfx/box_f.h"
namespace cc {
@@ -26,6 +27,17 @@ void InsertKeyframe(scoped_ptr<Keyframe> keyframe,
keyframes.push_back(keyframe.Pass());
}
+template <class Keyframes>
+float GetProgress(double t, size_t i, const Keyframes& keyframes) {
+ float progress =
+ static_cast<float>((t - keyframes[i]->Time()) /
+ (keyframes[i + 1]->Time() - keyframes[i]->Time()));
+
+ if (keyframes[i]->timing_function())
+ progress = keyframes[i]->timing_function()->GetValue(progress);
+ return progress;
+}
+
scoped_ptr<TimingFunction> CloneTimingFunction(
const TimingFunction* timing_function) {
DCHECK(timing_function);
@@ -46,6 +58,31 @@ double Keyframe::Time() const {
return time_;
}
+scoped_ptr<ColorKeyframe> ColorKeyframe::Create(
+ double time,
+ SkColor value,
+ scoped_ptr<TimingFunction> timing_function) {
+ return make_scoped_ptr(
+ new ColorKeyframe(time, value, timing_function.Pass()));
+}
+
+ColorKeyframe::ColorKeyframe(double time,
+ SkColor value,
+ scoped_ptr<TimingFunction> timing_function)
+ : Keyframe(time, timing_function.Pass()),
+ value_(value) {}
+
+ColorKeyframe::~ColorKeyframe() {}
+
+SkColor ColorKeyframe::Value() const { return value_; }
+
+scoped_ptr<ColorKeyframe> ColorKeyframe::Clone() const {
+ scoped_ptr<TimingFunction> func;
+ if (timing_function())
+ func = CloneTimingFunction(timing_function());
+ return ColorKeyframe::Create(Time(), Value(), func.Pass());
+}
+
scoped_ptr<FloatKeyframe> FloatKeyframe::Create(
double time,
float value,
@@ -127,6 +164,53 @@ scoped_ptr<FilterKeyframe> FilterKeyframe::Clone() const {
return FilterKeyframe::Create(Time(), Value(), func.Pass());
}
+scoped_ptr<KeyframedColorAnimationCurve> KeyframedColorAnimationCurve::
+ Create() {
+ return make_scoped_ptr(new KeyframedColorAnimationCurve);
+}
+
+KeyframedColorAnimationCurve::KeyframedColorAnimationCurve() {}
+
+KeyframedColorAnimationCurve::~KeyframedColorAnimationCurve() {}
+
+void KeyframedColorAnimationCurve::AddKeyframe(
+ scoped_ptr<ColorKeyframe> keyframe) {
+ InsertKeyframe(keyframe.Pass(), keyframes_);
+}
+
+double KeyframedColorAnimationCurve::Duration() const {
+ return keyframes_.back()->Time() - keyframes_.front()->Time();
+}
+
+scoped_ptr<AnimationCurve> KeyframedColorAnimationCurve::Clone() const {
+ scoped_ptr<KeyframedColorAnimationCurve> to_return(
+ KeyframedColorAnimationCurve::Create());
+ for (size_t i = 0; i < keyframes_.size(); ++i)
+ to_return->AddKeyframe(keyframes_[i]->Clone());
+ return to_return.PassAs<AnimationCurve>();
+}
+
+SkColor KeyframedColorAnimationCurve::GetValue(double t) const {
+ if (t <= keyframes_.front()->Time())
+ return keyframes_.front()->Value();
+
+ if (t >= keyframes_.back()->Time())
+ return keyframes_.back()->Value();
+
+ size_t i = 0;
+ for (; i < keyframes_.size() - 1; ++i) {
+ if (t < keyframes_[i + 1]->Time())
+ break;
+ }
+
+ float progress = GetProgress(t, i, keyframes_);
+
+ return gfx::Tween::ColorValueBetween(
+ progress, keyframes_[i]->Value(), keyframes_[i + 1]->Value());
+}
+
+// KeyframedFloatAnimationCurve
+
scoped_ptr<KeyframedFloatAnimationCurve> KeyframedFloatAnimationCurve::
Create() {
return make_scoped_ptr(new KeyframedFloatAnimationCurve);
@@ -166,12 +250,7 @@ float KeyframedFloatAnimationCurve::GetValue(double t) const {
break;
}
- float progress =
- static_cast<float>((t - keyframes_[i]->Time()) /
- (keyframes_[i+1]->Time() - keyframes_[i]->Time()));
-
- if (keyframes_[i]->timing_function())
- progress = keyframes_[i]->timing_function()->GetValue(progress);
+ float progress = GetProgress(t, i, keyframes_);
return keyframes_[i]->Value() +
(keyframes_[i+1]->Value() - keyframes_[i]->Value()) * progress;
diff --git a/chromium/cc/animation/keyframed_animation_curve.h b/chromium/cc/animation/keyframed_animation_curve.h
index 5892dc70e58..4b5ac3bf307 100644
--- a/chromium/cc/animation/keyframed_animation_curve.h
+++ b/chromium/cc/animation/keyframed_animation_curve.h
@@ -31,6 +31,26 @@ class CC_EXPORT Keyframe {
DISALLOW_COPY_AND_ASSIGN(Keyframe);
};
+class CC_EXPORT ColorKeyframe : public Keyframe {
+ public:
+ static scoped_ptr<ColorKeyframe> Create(
+ double time,
+ SkColor value,
+ scoped_ptr<TimingFunction> timing_function);
+ virtual ~ColorKeyframe();
+
+ SkColor Value() const;
+
+ scoped_ptr<ColorKeyframe> Clone() const;
+
+ private:
+ ColorKeyframe(double time,
+ SkColor value,
+ scoped_ptr<TimingFunction> timing_function);
+
+ SkColor value_;
+};
+
class CC_EXPORT FloatKeyframe : public Keyframe {
public:
static scoped_ptr<FloatKeyframe> Create(
@@ -93,6 +113,32 @@ class CC_EXPORT FilterKeyframe : public Keyframe {
FilterOperations value_;
};
+class CC_EXPORT KeyframedColorAnimationCurve : public ColorAnimationCurve {
+ public:
+ // It is required that the keyframes be sorted by time.
+ static scoped_ptr<KeyframedColorAnimationCurve> Create();
+
+ virtual ~KeyframedColorAnimationCurve();
+
+ void AddKeyframe(scoped_ptr<ColorKeyframe> keyframe);
+
+ // AnimationCurve implementation
+ virtual double Duration() const OVERRIDE;
+ virtual scoped_ptr<AnimationCurve> Clone() const OVERRIDE;
+
+ // BackgrounColorAnimationCurve implementation
+ virtual SkColor GetValue(double t) const OVERRIDE;
+
+ private:
+ KeyframedColorAnimationCurve();
+
+ // Always sorted in order of increasing time. No two keyframes have the
+ // same time.
+ ScopedPtrVector<ColorKeyframe> keyframes_;
+
+ DISALLOW_COPY_AND_ASSIGN(KeyframedColorAnimationCurve);
+};
+
class CC_EXPORT KeyframedFloatAnimationCurve : public FloatAnimationCurve {
public:
// It is required that the keyframes be sorted by time.
diff --git a/chromium/cc/animation/keyframed_animation_curve_unittest.cc b/chromium/cc/animation/keyframed_animation_curve_unittest.cc
index 48f511c0317..63e98668021 100644
--- a/chromium/cc/animation/keyframed_animation_curve_unittest.cc
+++ b/chromium/cc/animation/keyframed_animation_curve_unittest.cc
@@ -7,13 +7,15 @@
#include "cc/animation/transform_operations.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/animation/tween.h"
#include "ui/gfx/box_f.h"
+#include "ui/gfx/test/color_util.h"
namespace cc {
namespace {
-void ExpectTranslateX(double translate_x, const gfx::Transform& transform) {
- EXPECT_FLOAT_EQ(translate_x, transform.matrix().getDouble(0, 3));
+void ExpectTranslateX(SkMScalar translate_x, const gfx::Transform& transform) {
+ EXPECT_FLOAT_EQ(translate_x, transform.matrix().get(0, 3));
}
void ExpectBrightness(double brightness, const FilterOperations& filter) {
@@ -22,6 +24,98 @@ void ExpectBrightness(double brightness, const FilterOperations& filter) {
EXPECT_FLOAT_EQ(brightness, filter.at(0).amount());
}
+// Tests that a color animation with one keyframe works as expected.
+TEST(KeyframedAnimationCurveTest, OneColorKeyFrame) {
+ SkColor color = SkColorSetARGB(255, 255, 255, 255);
+ scoped_ptr<KeyframedColorAnimationCurve> curve(
+ KeyframedColorAnimationCurve::Create());
+ curve->AddKeyframe(
+ ColorKeyframe::Create(0.0, color, scoped_ptr<TimingFunction>()));
+
+ EXPECT_SKCOLOR_EQ(color, curve->GetValue(-1.f));
+ EXPECT_SKCOLOR_EQ(color, curve->GetValue(0.f));
+ EXPECT_SKCOLOR_EQ(color, curve->GetValue(0.5f));
+ EXPECT_SKCOLOR_EQ(color, curve->GetValue(1.f));
+ EXPECT_SKCOLOR_EQ(color, curve->GetValue(2.f));
+}
+
+// Tests that a color animation with two keyframes works as expected.
+TEST(KeyframedAnimationCurveTest, TwoColorKeyFrame) {
+ SkColor color_a = SkColorSetARGB(255, 255, 0, 0);
+ SkColor color_b = SkColorSetARGB(255, 0, 255, 0);
+ SkColor color_midpoint = gfx::Tween::ColorValueBetween(0.5, color_a, color_b);
+ scoped_ptr<KeyframedColorAnimationCurve> curve(
+ KeyframedColorAnimationCurve::Create());
+ curve->AddKeyframe(
+ ColorKeyframe::Create(0.0, color_a, scoped_ptr<TimingFunction>()));
+ curve->AddKeyframe(
+ ColorKeyframe::Create(1.0, color_b, scoped_ptr<TimingFunction>()));
+
+ EXPECT_SKCOLOR_EQ(color_a, curve->GetValue(-1.f));
+ EXPECT_SKCOLOR_EQ(color_a, curve->GetValue(0.f));
+ EXPECT_SKCOLOR_EQ(color_midpoint, curve->GetValue(0.5f));
+ EXPECT_SKCOLOR_EQ(color_b, curve->GetValue(1.f));
+ EXPECT_SKCOLOR_EQ(color_b, curve->GetValue(2.f));
+}
+
+// Tests that a color animation with three keyframes works as expected.
+TEST(KeyframedAnimationCurveTest, ThreeColorKeyFrame) {
+ SkColor color_a = SkColorSetARGB(255, 255, 0, 0);
+ SkColor color_b = SkColorSetARGB(255, 0, 255, 0);
+ SkColor color_c = SkColorSetARGB(255, 0, 0, 255);
+ SkColor color_midpoint1 =
+ gfx::Tween::ColorValueBetween(0.5, color_a, color_b);
+ SkColor color_midpoint2 =
+ gfx::Tween::ColorValueBetween(0.5, color_b, color_c);
+ scoped_ptr<KeyframedColorAnimationCurve> curve(
+ KeyframedColorAnimationCurve::Create());
+ curve->AddKeyframe(
+ ColorKeyframe::Create(0.0, color_a, scoped_ptr<TimingFunction>()));
+ curve->AddKeyframe(
+ ColorKeyframe::Create(1.0, color_b, scoped_ptr<TimingFunction>()));
+ curve->AddKeyframe(
+ ColorKeyframe::Create(2.0, color_c, scoped_ptr<TimingFunction>()));
+
+ EXPECT_SKCOLOR_EQ(color_a, curve->GetValue(-1.f));
+ EXPECT_SKCOLOR_EQ(color_a, curve->GetValue(0.f));
+ EXPECT_SKCOLOR_EQ(color_midpoint1, curve->GetValue(0.5f));
+ EXPECT_SKCOLOR_EQ(color_b, curve->GetValue(1.f));
+ EXPECT_SKCOLOR_EQ(color_midpoint2, curve->GetValue(1.5f));
+ EXPECT_SKCOLOR_EQ(color_c, curve->GetValue(2.f));
+ EXPECT_SKCOLOR_EQ(color_c, curve->GetValue(3.f));
+}
+
+// Tests that a colro animation with multiple keys at a given time works sanely.
+TEST(KeyframedAnimationCurveTest, RepeatedColorKeyFrame) {
+ SkColor color_a = SkColorSetARGB(255, 64, 0, 0);
+ SkColor color_b = SkColorSetARGB(255, 192, 0, 0);
+
+ scoped_ptr<KeyframedColorAnimationCurve> curve(
+ KeyframedColorAnimationCurve::Create());
+ curve->AddKeyframe(
+ ColorKeyframe::Create(0.0, color_a, scoped_ptr<TimingFunction>()));
+ curve->AddKeyframe(
+ ColorKeyframe::Create(1.0, color_a, scoped_ptr<TimingFunction>()));
+ curve->AddKeyframe(
+ ColorKeyframe::Create(1.0, color_b, scoped_ptr<TimingFunction>()));
+ curve->AddKeyframe(
+ ColorKeyframe::Create(2.0, color_b, scoped_ptr<TimingFunction>()));
+
+ EXPECT_SKCOLOR_EQ(color_a, curve->GetValue(-1.f));
+ EXPECT_SKCOLOR_EQ(color_a, curve->GetValue(0.f));
+ EXPECT_SKCOLOR_EQ(color_a, curve->GetValue(0.5f));
+
+ SkColor value = curve->GetValue(1.0f);
+ EXPECT_EQ(255u, SkColorGetA(value));
+ int red_value = SkColorGetR(value);
+ EXPECT_LE(64, red_value);
+ EXPECT_GE(192, red_value);
+
+ EXPECT_SKCOLOR_EQ(color_b, curve->GetValue(1.5f));
+ EXPECT_SKCOLOR_EQ(color_b, curve->GetValue(2.f));
+ EXPECT_SKCOLOR_EQ(color_b, curve->GetValue(3.f));
+}
+
// Tests that a float animation with one keyframe works as expected.
TEST(KeyframedAnimationCurveTest, OneFloatKeyframe) {
scoped_ptr<KeyframedFloatAnimationCurve> curve(
@@ -185,8 +279,8 @@ TEST(KeyframedAnimationCurveTest, RepeatedTransformKeyTimes) {
// There is a discontinuity at 1. Any value between 4 and 6 is valid.
gfx::Transform value = curve->GetValue(1.f);
- EXPECT_GE(value.matrix().getDouble(0.f, 3.f), 4);
- EXPECT_LE(value.matrix().getDouble(0.f, 3.f), 6);
+ EXPECT_GE(value.matrix().get(0, 3), 4.f);
+ EXPECT_LE(value.matrix().get(0, 3), 6.f);
ExpectTranslateX(6.f, curve->GetValue(1.5f));
ExpectTranslateX(6.f, curve->GetValue(2.f));
diff --git a/chromium/cc/animation/layer_animation_controller.cc b/chromium/cc/animation/layer_animation_controller.cc
index 04920acc6ef..e1ab6464a1f 100644
--- a/chromium/cc/animation/layer_animation_controller.cc
+++ b/chromium/cc/animation/layer_animation_controller.cc
@@ -11,18 +11,21 @@
#include "cc/animation/animation_registrar.h"
#include "cc/animation/keyframed_animation_curve.h"
#include "cc/animation/layer_animation_value_observer.h"
+#include "cc/animation/layer_animation_value_provider.h"
+#include "cc/animation/scroll_offset_animation_curve.h"
#include "cc/base/scoped_ptr_algorithm.h"
+#include "cc/output/filter_operations.h"
#include "ui/gfx/box_f.h"
#include "ui/gfx/transform.h"
namespace cc {
LayerAnimationController::LayerAnimationController(int id)
- : force_sync_(false),
- registrar_(0),
+ : registrar_(0),
id_(id),
is_active_(false),
last_tick_time_(0),
+ value_provider_(NULL),
layer_animation_delegate_(NULL) {}
LayerAnimationController::~LayerAnimationController() {
@@ -82,29 +85,21 @@ void LayerAnimationController::RemoveAnimation(
int animation_id,
Animation::TargetProperty target_property) {
ScopedPtrVector<Animation>& animations = active_animations_;
- animations.erase(cc::remove_if(&animations,
- animations.begin(),
- animations.end(),
- HasAnimationIdAndProperty(animation_id,
- target_property)),
- animations.end());
+ animations.erase(
+ cc::remove_if(&animations,
+ animations.begin(),
+ animations.end(),
+ HasAnimationIdAndProperty(animation_id, target_property)),
+ animations.end());
UpdateActivation(NormalActivation);
}
-// According to render layer backing, these are for testing only.
-void LayerAnimationController::SuspendAnimations(double monotonic_time) {
- for (size_t i = 0; i < active_animations_.size(); ++i) {
- if (!active_animations_[i]->is_finished())
- active_animations_[i]->SetRunState(Animation::Paused, monotonic_time);
- }
-}
-
-// Looking at GraphicsLayerCA, this appears to be the analog to
-// SuspendAnimations, which is for testing.
-void LayerAnimationController::ResumeAnimations(double monotonic_time) {
+void LayerAnimationController::AbortAnimations(
+ Animation::TargetProperty target_property) {
for (size_t i = 0; i < active_animations_.size(); ++i) {
- if (active_animations_[i]->run_state() == Animation::Paused)
- active_animations_[i]->SetRunState(Animation::Running, monotonic_time);
+ if (active_animations_[i]->target_property() == target_property &&
+ !active_animations_[i]->is_finished())
+ active_animations_[i]->SetRunState(Animation::Aborted, last_tick_time_);
}
}
@@ -113,32 +108,27 @@ void LayerAnimationController::ResumeAnimations(double monotonic_time) {
void LayerAnimationController::PushAnimationUpdatesTo(
LayerAnimationController* controller_impl) {
DCHECK(this != controller_impl);
- if (force_sync_) {
- ReplaceImplThreadAnimations(controller_impl);
- force_sync_ = false;
- } else {
- PurgeAnimationsMarkedForDeletion();
- PushNewAnimationsToImplThread(controller_impl);
-
- // Remove finished impl side animations only after pushing,
- // and only after the animations are deleted on the main thread
- // this insures we will never push an animation twice.
- RemoveAnimationsCompletedOnMainThread(controller_impl);
-
- PushPropertiesToImplThread(controller_impl);
- }
+ if (!has_any_animation() && !controller_impl->has_any_animation())
+ return;
+ PurgeAnimationsMarkedForDeletion();
+ PushNewAnimationsToImplThread(controller_impl);
+
+ // Remove finished impl side animations only after pushing,
+ // and only after the animations are deleted on the main thread
+ // this insures we will never push an animation twice.
+ RemoveAnimationsCompletedOnMainThread(controller_impl);
+
+ PushPropertiesToImplThread(controller_impl);
controller_impl->UpdateActivation(NormalActivation);
UpdateActivation(NormalActivation);
}
void LayerAnimationController::Animate(double monotonic_time) {
+ DCHECK(monotonic_time);
if (!HasValueObserver())
return;
- StartAnimationsWaitingForNextTick(monotonic_time);
- StartAnimationsWaitingForStartTime(monotonic_time);
- StartAnimationsWaitingForTargetAvailability(monotonic_time);
- ResolveConflicts(monotonic_time);
+ StartAnimations(monotonic_time);
TickAnimations(monotonic_time);
last_tick_time_ = monotonic_time;
}
@@ -154,27 +144,58 @@ void LayerAnimationController::AccumulatePropertyUpdates(
if (!animation->is_impl_only())
continue;
- if (animation->target_property() == Animation::Opacity) {
- AnimationEvent event(AnimationEvent::PropertyUpdate,
- id_,
- animation->group(),
- Animation::Opacity,
- monotonic_time);
- event.opacity = animation->curve()->ToFloatAnimationCurve()->GetValue(
- monotonic_time);
- event.is_impl_only = true;
- events->push_back(event);
- } else if (animation->target_property() == Animation::Transform) {
- AnimationEvent event(AnimationEvent::PropertyUpdate,
- id_,
- animation->group(),
- Animation::Transform,
- monotonic_time);
- event.transform =
- animation->curve()->ToTransformAnimationCurve()->GetValue(
- monotonic_time);
- event.is_impl_only = true;
- events->push_back(event);
+ double trimmed = animation->TrimTimeToCurrentIteration(monotonic_time);
+ switch (animation->target_property()) {
+ case Animation::Opacity: {
+ AnimationEvent event(AnimationEvent::PropertyUpdate,
+ id_,
+ animation->group(),
+ Animation::Opacity,
+ monotonic_time);
+ event.opacity = animation->curve()->ToFloatAnimationCurve()->GetValue(
+ trimmed);
+ event.is_impl_only = true;
+ events->push_back(event);
+ break;
+ }
+
+ case Animation::Transform: {
+ AnimationEvent event(AnimationEvent::PropertyUpdate,
+ id_,
+ animation->group(),
+ Animation::Transform,
+ monotonic_time);
+ event.transform =
+ animation->curve()->ToTransformAnimationCurve()->GetValue(trimmed);
+ event.is_impl_only = true;
+ events->push_back(event);
+ break;
+ }
+
+ case Animation::Filter: {
+ AnimationEvent event(AnimationEvent::PropertyUpdate,
+ id_,
+ animation->group(),
+ Animation::Filter,
+ monotonic_time);
+ event.filters = animation->curve()->ToFilterAnimationCurve()->GetValue(
+ trimmed);
+ event.is_impl_only = true;
+ events->push_back(event);
+ break;
+ }
+
+ case Animation::BackgroundColor: { break; }
+
+ case Animation::ScrollOffset: {
+ // Impl-side changes to scroll offset are already sent back to the
+ // main thread (e.g. for user-driven scrolling), so a PropertyUpdate
+ // isn't needed.
+ break;
+ }
+
+ case Animation::TargetPropertyEnumSize:
+ NOTREACHED();
}
}
}
@@ -191,7 +212,7 @@ void LayerAnimationController::UpdateState(bool start_ready_animations,
MarkAnimationsForDeletion(last_tick_time_, events);
if (start_ready_animations) {
- StartAnimationsWaitingForTargetAvailability(last_tick_time_);
+ StartAnimations(last_tick_time_);
PromoteStartedAnimations(last_tick_time_, events);
}
@@ -261,11 +282,14 @@ void LayerAnimationController::SetAnimationRegistrar(
void LayerAnimationController::NotifyAnimationStarted(
const AnimationEvent& event,
double wall_clock_time) {
+ base::TimeTicks monotonic_time = base::TimeTicks::FromInternalValue(
+ event.monotonic_time * base::Time::kMicrosecondsPerSecond);
if (event.is_impl_only) {
FOR_EACH_OBSERVER(LayerAnimationEventObserver, event_observers_,
OnAnimationStarted(event));
if (layer_animation_delegate_)
- layer_animation_delegate_->NotifyAnimationStarted(wall_clock_time);
+ layer_animation_delegate_->NotifyAnimationStarted(
+ wall_clock_time, monotonic_time, event.target_property);
return;
}
@@ -280,7 +304,8 @@ void LayerAnimationController::NotifyAnimationStarted(
FOR_EACH_OBSERVER(LayerAnimationEventObserver, event_observers_,
OnAnimationStarted(event));
if (layer_animation_delegate_)
- layer_animation_delegate_->NotifyAnimationStarted(wall_clock_time);
+ layer_animation_delegate_->NotifyAnimationStarted(
+ wall_clock_time, monotonic_time, event.target_property);
return;
}
@@ -290,9 +315,12 @@ void LayerAnimationController::NotifyAnimationStarted(
void LayerAnimationController::NotifyAnimationFinished(
const AnimationEvent& event,
double wall_clock_time) {
+ base::TimeTicks monotonic_time = base::TimeTicks::FromInternalValue(
+ event.monotonic_time * base::Time::kMicrosecondsPerSecond);
if (event.is_impl_only) {
if (layer_animation_delegate_)
- layer_animation_delegate_->NotifyAnimationFinished(wall_clock_time);
+ layer_animation_delegate_->NotifyAnimationFinished(
+ wall_clock_time, monotonic_time, event.target_property);
return;
}
@@ -301,13 +329,25 @@ void LayerAnimationController::NotifyAnimationFinished(
active_animations_[i]->target_property() == event.target_property) {
active_animations_[i]->set_received_finished_event(true);
if (layer_animation_delegate_)
- layer_animation_delegate_->NotifyAnimationFinished(wall_clock_time);
+ layer_animation_delegate_->NotifyAnimationFinished(
+ wall_clock_time, monotonic_time, event.target_property);
return;
}
}
}
+void LayerAnimationController::NotifyAnimationAborted(
+ const AnimationEvent& event) {
+ for (size_t i = 0; i < active_animations_.size(); ++i) {
+ if (active_animations_[i]->group() == event.group_id &&
+ active_animations_[i]->target_property() == event.target_property) {
+ active_animations_[i]->SetRunState(Animation::Aborted,
+ event.monotonic_time);
+ }
+ }
+}
+
void LayerAnimationController::NotifyAnimationPropertyUpdate(
const AnimationEvent& event) {
switch (event.target_property) {
@@ -389,12 +429,27 @@ void LayerAnimationController::PushNewAnimationsToImplThread(
if (!active_animations_[i]->needs_synchronized_start_time())
continue;
+ // Scroll animations always start at the current scroll offset.
+ if (active_animations_[i]->target_property() == Animation::ScrollOffset) {
+ gfx::Vector2dF current_scroll_offset;
+ if (controller_impl->value_provider_) {
+ current_scroll_offset =
+ controller_impl->value_provider_->ScrollOffsetForAnimation();
+ } else {
+ // The owning layer isn't yet in the active tree, so the main thread
+ // scroll offset will be up-to-date.
+ current_scroll_offset = value_provider_->ScrollOffsetForAnimation();
+ }
+ active_animations_[i]->curve()->ToScrollOffsetAnimationCurve()
+ ->SetInitialValue(current_scroll_offset);
+ }
+
// The new animation should be set to run as soon as possible.
Animation::RunState initial_run_state =
Animation::WaitingForTargetAvailability;
double start_time = 0;
scoped_ptr<Animation> to_add(active_animations_[i]->CloneAndInitialize(
- Animation::ControllingInstance, initial_run_state, start_time));
+ initial_run_state, start_time));
DCHECK(!to_add->needs_synchronized_start_time());
controller_impl->AddAnimation(to_add.Pass());
}
@@ -444,25 +499,7 @@ void LayerAnimationController::PushPropertiesToImplThread(
}
}
-void LayerAnimationController::StartAnimationsWaitingForNextTick(
- double monotonic_time) {
- for (size_t i = 0; i < active_animations_.size(); ++i) {
- if (active_animations_[i]->run_state() == Animation::WaitingForNextTick)
- active_animations_[i]->SetRunState(Animation::Starting, monotonic_time);
- }
-}
-
-void LayerAnimationController::StartAnimationsWaitingForStartTime(
- double monotonic_time) {
- for (size_t i = 0; i < active_animations_.size(); ++i) {
- if (active_animations_[i]->run_state() == Animation::WaitingForStartTime &&
- active_animations_[i]->start_time() <= monotonic_time)
- active_animations_[i]->SetRunState(Animation::Starting, monotonic_time);
- }
-}
-
-void LayerAnimationController::StartAnimationsWaitingForTargetAvailability(
- double monotonic_time) {
+void LayerAnimationController::StartAnimations(double monotonic_time) {
// First collect running properties.
TargetProperties blocked_properties;
for (size_t i = 0; i < active_animations_.size(); ++i) {
@@ -537,47 +574,38 @@ void LayerAnimationController::PromoteStartedAnimations(
void LayerAnimationController::MarkFinishedAnimations(double monotonic_time) {
for (size_t i = 0; i < active_animations_.size(); ++i) {
if (active_animations_[i]->IsFinishedAt(monotonic_time) &&
+ active_animations_[i]->run_state() != Animation::Aborted &&
active_animations_[i]->run_state() != Animation::WaitingForDeletion)
active_animations_[i]->SetRunState(Animation::Finished, monotonic_time);
}
}
-void LayerAnimationController::ResolveConflicts(double monotonic_time) {
- // Find any animations that are animating the same property and resolve the
- // confict. We could eventually blend, but for now we'll just abort the
- // previous animation (where 'previous' means: (1) has a prior start time or
- // (2) has an equal start time, but was added to the queue earlier, i.e.,
- // has a lower index in active_animations_).
- for (size_t i = 0; i < active_animations_.size(); ++i) {
- if (active_animations_[i]->run_state() == Animation::Starting ||
- active_animations_[i]->run_state() == Animation::Running) {
- for (size_t j = i + 1; j < active_animations_.size(); ++j) {
- if ((active_animations_[j]->run_state() == Animation::Starting ||
- active_animations_[j]->run_state() == Animation::Running) &&
- active_animations_[i]->target_property() ==
- active_animations_[j]->target_property()) {
- if (active_animations_[i]->start_time() >
- active_animations_[j]->start_time()) {
- active_animations_[j]->SetRunState(Animation::Aborted,
- monotonic_time);
- } else {
- active_animations_[i]->SetRunState(Animation::Aborted,
- monotonic_time);
- }
- }
- }
- }
- }
-}
-
void LayerAnimationController::MarkAnimationsForDeletion(
double monotonic_time, AnimationEventsVector* events) {
+ bool marked_animations_for_deletions = false;
+
// Non-aborted animations are marked for deletion after a corresponding
// AnimationEvent::Finished event is sent or received. This means that if
// we don't have an events vector, we must ensure that non-aborted animations
// have received a finished event before marking them for deletion.
for (size_t i = 0; i < active_animations_.size(); i++) {
int group_id = active_animations_[i]->group();
+ if (active_animations_[i]->run_state() == Animation::Aborted) {
+ if (events && !active_animations_[i]->is_impl_only()) {
+ AnimationEvent aborted_event(
+ AnimationEvent::Aborted,
+ id_,
+ group_id,
+ active_animations_[i]->target_property(),
+ monotonic_time);
+ events->push_back(aborted_event);
+ }
+ active_animations_[i]->SetRunState(Animation::WaitingForDeletion,
+ monotonic_time);
+ marked_animations_for_deletions = true;
+ continue;
+ }
+
bool all_anims_with_same_id_are_finished = false;
// Since deleting an animation on the main thread leads to its deletion
@@ -587,9 +615,8 @@ void LayerAnimationController::MarkAnimationsForDeletion(
events || active_animations_[i]->received_finished_event();
// If an animation is finished, and not already marked for deletion,
// find out if all other animations in the same group are also finished.
- if (active_animations_[i]->run_state() == Animation::Aborted ||
- (active_animations_[i]->run_state() == Animation::Finished &&
- animation_i_will_send_or_has_received_finish_event)) {
+ if (active_animations_[i]->run_state() == Animation::Finished &&
+ animation_i_will_send_or_has_received_finish_event) {
all_anims_with_same_id_are_finished = true;
for (size_t j = 0; j < active_animations_.size(); ++j) {
bool animation_j_will_send_or_has_received_finish_event =
@@ -608,7 +635,8 @@ void LayerAnimationController::MarkAnimationsForDeletion(
// group_id (and send along animation finished notifications, if
// necessary).
for (size_t j = i; j < active_animations_.size(); j++) {
- if (group_id == active_animations_[j]->group()) {
+ if (active_animations_[j]->group() == group_id &&
+ active_animations_[j]->run_state() != Animation::Aborted) {
if (events) {
AnimationEvent finished_event(
AnimationEvent::Finished,
@@ -623,8 +651,11 @@ void LayerAnimationController::MarkAnimationsForDeletion(
monotonic_time);
}
}
+ marked_animations_for_deletions = true;
}
}
+ if (marked_animations_for_deletions)
+ NotifyObserversAnimationWaitingForDeletion();
}
static bool IsWaitingForDeletion(Animation* animation) {
@@ -640,29 +671,6 @@ void LayerAnimationController::PurgeAnimationsMarkedForDeletion() {
animations.end());
}
-void LayerAnimationController::ReplaceImplThreadAnimations(
- LayerAnimationController* controller_impl) const {
- controller_impl->active_animations_.clear();
- for (size_t i = 0; i < active_animations_.size(); ++i) {
- scoped_ptr<Animation> to_add;
- if (active_animations_[i]->needs_synchronized_start_time()) {
- // We haven't received an animation started notification yet, so it
- // is important that we add it in a 'waiting' and not 'running' state.
- Animation::RunState initial_run_state =
- Animation::WaitingForTargetAvailability;
- double start_time = 0;
- to_add = active_animations_[i]->CloneAndInitialize(
- Animation::ControllingInstance,
- initial_run_state, start_time).Pass();
- } else {
- to_add = active_animations_[i]->Clone(
- Animation::ControllingInstance).Pass();
- }
-
- controller_impl->AddAnimation(to_add.Pass());
- }
-}
-
void LayerAnimationController::TickAnimations(double monotonic_time) {
for (size_t i = 0; i < active_animations_.size(); ++i) {
if (active_animations_[i]->run_state() == Animation::Starting ||
@@ -689,7 +697,30 @@ void LayerAnimationController::TickAnimations(double monotonic_time) {
break;
}
- // Do nothing for sentinel value.
+ case Animation::Filter: {
+ const FilterAnimationCurve* filter_animation_curve =
+ active_animations_[i]->curve()->ToFilterAnimationCurve();
+ const FilterOperations filter =
+ filter_animation_curve->GetValue(trimmed);
+ NotifyObserversFilterAnimated(filter);
+ break;
+ }
+
+ case Animation::BackgroundColor: {
+ // Not yet implemented.
+ break;
+ }
+
+ case Animation::ScrollOffset: {
+ const ScrollOffsetAnimationCurve* scroll_offset_animation_curve =
+ active_animations_[i]->curve()->ToScrollOffsetAnimationCurve();
+ const gfx::Vector2dF scroll_offset =
+ scroll_offset_animation_curve->GetValue(trimmed);
+ NotifyObserversScrollOffsetAnimated(scroll_offset);
+ break;
+ }
+
+ // Do nothing for sentinel value.
case Animation::TargetPropertyEnumSize:
NOTREACHED();
}
@@ -700,11 +731,19 @@ void LayerAnimationController::TickAnimations(double monotonic_time) {
void LayerAnimationController::UpdateActivation(UpdateActivationType type) {
bool force = type == ForceActivation;
if (registrar_) {
- if (!active_animations_.empty() && (!is_active_ || force))
+ bool was_active = is_active_;
+ is_active_ = false;
+ for (size_t i = 0; i < active_animations_.size(); ++i) {
+ if (active_animations_[i]->run_state() != Animation::WaitingForDeletion) {
+ is_active_ = true;
+ break;
+ }
+ }
+
+ if (is_active_ && (!was_active || force))
registrar_->DidActivateAnimationController(this);
- else if (active_animations_.empty() && (is_active_ || force))
+ else if (!is_active_ && (was_active || force))
registrar_->DidDeactivateAnimationController(this);
- is_active_ = !active_animations_.empty();
}
}
@@ -721,6 +760,26 @@ void LayerAnimationController::NotifyObserversTransformAnimated(
OnTransformAnimated(transform));
}
+void LayerAnimationController::NotifyObserversFilterAnimated(
+ const FilterOperations& filters) {
+ FOR_EACH_OBSERVER(LayerAnimationValueObserver,
+ value_observers_,
+ OnFilterAnimated(filters));
+}
+
+void LayerAnimationController::NotifyObserversScrollOffsetAnimated(
+ gfx::Vector2dF scroll_offset) {
+ FOR_EACH_OBSERVER(LayerAnimationValueObserver,
+ value_observers_,
+ OnScrollOffsetAnimated(scroll_offset));
+}
+
+void LayerAnimationController::NotifyObserversAnimationWaitingForDeletion() {
+ FOR_EACH_OBSERVER(LayerAnimationValueObserver,
+ value_observers_,
+ OnAnimationWaitingForDeletion());
+}
+
bool LayerAnimationController::HasValueObserver() {
if (value_observers_.might_have_observers()) {
ObserverListBase<LayerAnimationValueObserver>::Iterator it(
diff --git a/chromium/cc/animation/layer_animation_controller.h b/chromium/cc/animation/layer_animation_controller.h
index 4138704af66..564a5933e7f 100644
--- a/chromium/cc/animation/layer_animation_controller.h
+++ b/chromium/cc/animation/layer_animation_controller.h
@@ -27,8 +27,10 @@ namespace cc {
class Animation;
class AnimationDelegate;
class AnimationRegistrar;
+class FilterOperations;
class KeyframeValueList;
class LayerAnimationValueObserver;
+class LayerAnimationValueProvider;
class CC_EXPORT LayerAnimationController
: public base::RefCounted<LayerAnimationController> {
@@ -37,18 +39,16 @@ class CC_EXPORT LayerAnimationController
int id() const { return id_; }
- // These methods are virtual for testing.
- virtual void AddAnimation(scoped_ptr<Animation> animation);
- virtual void PauseAnimation(int animation_id, double time_offset);
- virtual void RemoveAnimation(int animation_id);
- virtual void RemoveAnimation(int animation_id,
- Animation::TargetProperty target_property);
- virtual void SuspendAnimations(double monotonic_time);
- virtual void ResumeAnimations(double monotonic_time);
+ void AddAnimation(scoped_ptr<Animation> animation);
+ void PauseAnimation(int animation_id, double time_offset);
+ void RemoveAnimation(int animation_id);
+ void RemoveAnimation(int animation_id,
+ Animation::TargetProperty target_property);
+ void AbortAnimations(Animation::TargetProperty target_property);
// Ensures that the list of active animations on the main thread and the impl
// thread are kept in sync. This function does not take ownership of the impl
- // thread controller.
+ // thread controller. This method is virtual for testing.
virtual void PushAnimationUpdatesTo(
LayerAnimationController* controller_impl);
@@ -80,10 +80,6 @@ class CC_EXPORT LayerAnimationController
// the future.
bool IsAnimatingProperty(Animation::TargetProperty target_property) const;
- // If a sync is forced, then the next time animation updates are pushed to the
- // impl thread, all animations will be transferred.
- void set_force_sync() { force_sync_ = true; }
-
void SetAnimationRegistrar(AnimationRegistrar* registrar);
AnimationRegistrar* animation_registrar() { return registrar_; }
@@ -91,6 +87,7 @@ class CC_EXPORT LayerAnimationController
double wall_clock_time);
void NotifyAnimationFinished(const AnimationEvent& event,
double wall_clock_time);
+ void NotifyAnimationAborted(const AnimationEvent& event);
void NotifyAnimationPropertyUpdate(const AnimationEvent& event);
void AddValueObserver(LayerAnimationValueObserver* observer);
@@ -99,6 +96,15 @@ class CC_EXPORT LayerAnimationController
void AddEventObserver(LayerAnimationEventObserver* observer);
void RemoveEventObserver(LayerAnimationEventObserver* observer);
+ void set_value_provider(LayerAnimationValueProvider* provider) {
+ value_provider_ = provider;
+ }
+
+ void remove_value_provider(LayerAnimationValueProvider* provider) {
+ if (value_provider_ == provider)
+ value_provider_ = NULL;
+ }
+
void set_layer_animation_delegate(AnimationDelegate* delegate) {
layer_animation_delegate_ = delegate;
}
@@ -120,13 +126,8 @@ class CC_EXPORT LayerAnimationController
LayerAnimationController* controller_impl) const;
void PushPropertiesToImplThread(
LayerAnimationController* controller_impl) const;
- void ReplaceImplThreadAnimations(
- LayerAnimationController* controller_impl) const;
- void StartAnimationsWaitingForNextTick(double monotonic_time);
- void StartAnimationsWaitingForStartTime(double monotonic_time);
- void StartAnimationsWaitingForTargetAvailability(double monotonic_time);
- void ResolveConflicts(double monotonic_time);
+ void StartAnimations(double monotonic_time);
void PromoteStartedAnimations(double monotonic_time,
AnimationEventsVector* events);
void MarkFinishedAnimations(double monotonic_time);
@@ -144,13 +145,14 @@ class CC_EXPORT LayerAnimationController
void NotifyObserversOpacityAnimated(float opacity);
void NotifyObserversTransformAnimated(const gfx::Transform& transform);
+ void NotifyObserversFilterAnimated(const FilterOperations& filter);
+ void NotifyObserversScrollOffsetAnimated(gfx::Vector2dF scroll_offset);
+
+ void NotifyObserversAnimationWaitingForDeletion();
bool HasValueObserver();
bool HasActiveValueObserver();
- // If this is true, we force a sync to the impl thread.
- bool force_sync_;
-
AnimationRegistrar* registrar_;
int id_;
ScopedPtrVector<Animation> active_animations_;
@@ -163,6 +165,8 @@ class CC_EXPORT LayerAnimationController
ObserverList<LayerAnimationValueObserver> value_observers_;
ObserverList<LayerAnimationEventObserver> event_observers_;
+ LayerAnimationValueProvider* value_provider_;
+
AnimationDelegate* layer_animation_delegate_;
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 e55c53c07f3..f7918cd2bf3 100644
--- a/chromium/cc/animation/layer_animation_controller_unittest.cc
+++ b/chromium/cc/animation/layer_animation_controller_unittest.cc
@@ -7,7 +7,9 @@
#include "cc/animation/animation.h"
#include "cc/animation/animation_curve.h"
#include "cc/animation/animation_delegate.h"
+#include "cc/animation/animation_registrar.h"
#include "cc/animation/keyframed_animation_curve.h"
+#include "cc/animation/scroll_offset_animation_curve.h"
#include "cc/animation/transform_operations.h"
#include "cc/test/animation_test_common.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -18,6 +20,11 @@
namespace cc {
namespace {
+// A LayerAnimationController cannot be ticked at 0.0, since an animation
+// with start time 0.0 is treated as an animation whose start time has
+// not yet been set.
+const double kInitialTickTime = 1.0;
+
scoped_ptr<Animation> CreateAnimation(scoped_ptr<AnimationCurve> curve,
int id,
Animation::TargetProperty property) {
@@ -72,7 +79,7 @@ TEST(LayerAnimationControllerTest, DoNotClobberStartTimes) {
Animation::Opacity)->run_state());
AnimationEventsVector events;
- controller_impl->Animate(1.0);
+ controller_impl->Animate(kInitialTickTime);
controller_impl->UpdateState(true, &events);
// Synchronize the start times.
@@ -84,7 +91,7 @@ TEST(LayerAnimationControllerTest, DoNotClobberStartTimes) {
Animation::Opacity)->start_time());
// Start the animation on the main thread. Should not affect the start time.
- controller->Animate(1.5);
+ controller->Animate(kInitialTickTime + 0.5);
controller->UpdateState(true, NULL);
EXPECT_EQ(controller->GetAnimation(group_id,
Animation::Opacity)->start_time(),
@@ -92,7 +99,88 @@ TEST(LayerAnimationControllerTest, DoNotClobberStartTimes) {
Animation::Opacity)->start_time());
}
-TEST(LayerAnimationControllerTest, SyncPauseAndResume) {
+// Tests that controllers activate and deactivate as expected.
+TEST(LayerAnimationControllerTest, Activation) {
+ scoped_ptr<AnimationRegistrar> registrar = AnimationRegistrar::Create();
+ scoped_ptr<AnimationRegistrar> registrar_impl = AnimationRegistrar::Create();
+
+ FakeLayerAnimationValueObserver dummy_impl;
+ scoped_refptr<LayerAnimationController> controller_impl(
+ LayerAnimationController::Create(0));
+ controller_impl->AddValueObserver(&dummy_impl);
+ FakeLayerAnimationValueObserver dummy;
+ scoped_refptr<LayerAnimationController> controller(
+ LayerAnimationController::Create(0));
+ controller->AddValueObserver(&dummy);
+ scoped_ptr<AnimationEventsVector> events(
+ make_scoped_ptr(new AnimationEventsVector));
+
+ controller->SetAnimationRegistrar(registrar.get());
+ controller_impl->SetAnimationRegistrar(registrar_impl.get());
+ EXPECT_EQ(1u, registrar->all_animation_controllers().size());
+ EXPECT_EQ(1u, registrar_impl->all_animation_controllers().size());
+
+ // Initially, both controllers should be inactive.
+ EXPECT_EQ(0u, registrar->active_animation_controllers().size());
+ EXPECT_EQ(0u, registrar_impl->active_animation_controllers().size());
+
+ AddOpacityTransitionToController(controller.get(), 1, 0, 1, false);
+ // The main thread controller should now be active.
+ EXPECT_EQ(1u, registrar->active_animation_controllers().size());
+
+ controller->PushAnimationUpdatesTo(controller_impl.get());
+ // Both controllers should now be active.
+ EXPECT_EQ(1u, registrar->active_animation_controllers().size());
+ EXPECT_EQ(1u, registrar_impl->active_animation_controllers().size());
+
+ controller_impl->Animate(kInitialTickTime);
+ controller_impl->UpdateState(true, events.get());
+ EXPECT_EQ(1u, events->size());
+ controller->NotifyAnimationStarted((*events)[0], 0.0);
+
+ EXPECT_EQ(1u, registrar->active_animation_controllers().size());
+ EXPECT_EQ(1u, registrar_impl->active_animation_controllers().size());
+
+ controller->Animate(kInitialTickTime + 0.5);
+ controller->UpdateState(true, NULL);
+ EXPECT_EQ(1u, registrar->active_animation_controllers().size());
+
+ controller->Animate(kInitialTickTime + 1.0);
+ controller->UpdateState(true, NULL);
+ EXPECT_EQ(Animation::Finished,
+ controller->GetAnimation(Animation::Opacity)->run_state());
+ EXPECT_EQ(1u, registrar->active_animation_controllers().size());
+
+ events.reset(new AnimationEventsVector);
+ controller_impl->Animate(kInitialTickTime + 1.5);
+ controller_impl->UpdateState(true, events.get());
+
+ EXPECT_EQ(Animation::WaitingForDeletion,
+ controller_impl->GetAnimation(Animation::Opacity)->run_state());
+ // The impl thread controller should have de-activated.
+ EXPECT_EQ(0u, registrar_impl->active_animation_controllers().size());
+
+ EXPECT_EQ(1u, events->size());
+ controller->NotifyAnimationFinished((*events)[0], 0.0);
+ controller->Animate(kInitialTickTime + 1.5);
+ controller->UpdateState(true, NULL);
+
+ EXPECT_EQ(Animation::WaitingForDeletion,
+ controller->GetAnimation(Animation::Opacity)->run_state());
+ // The main thread controller should have de-activated.
+ EXPECT_EQ(0u, registrar->active_animation_controllers().size());
+
+ controller->PushAnimationUpdatesTo(controller_impl.get());
+ EXPECT_FALSE(controller->has_any_animation());
+ EXPECT_FALSE(controller_impl->has_any_animation());
+ EXPECT_EQ(0u, registrar->active_animation_controllers().size());
+ EXPECT_EQ(0u, registrar_impl->active_animation_controllers().size());
+
+ controller->SetAnimationRegistrar(NULL);
+ controller_impl->SetAnimationRegistrar(NULL);
+}
+
+TEST(LayerAnimationControllerTest, SyncPause) {
FakeLayerAnimationValueObserver dummy_impl;
scoped_refptr<LayerAnimationController> controller_impl(
LayerAnimationController::Create(0));
@@ -106,6 +194,7 @@ TEST(LayerAnimationControllerTest, SyncPauseAndResume) {
AddOpacityTransitionToController(controller.get(), 1, 0, 1, false);
int group_id = controller->GetAnimation(Animation::Opacity)->group();
+ int animation_id = controller->GetAnimation(Animation::Opacity)->id();
controller->PushAnimationUpdatesTo(controller_impl.get());
@@ -116,9 +205,9 @@ TEST(LayerAnimationControllerTest, SyncPauseAndResume) {
// Start the animations on each controller.
AnimationEventsVector events;
- controller_impl->Animate(0.0);
+ controller_impl->Animate(kInitialTickTime);
controller_impl->UpdateState(true, &events);
- controller->Animate(0.0);
+ controller->Animate(kInitialTickTime);
controller->UpdateState(true, NULL);
EXPECT_EQ(Animation::Running,
controller_impl->GetAnimation(group_id,
@@ -128,7 +217,7 @@ TEST(LayerAnimationControllerTest, SyncPauseAndResume) {
Animation::Opacity)->run_state());
// Pause the main-thread animation.
- controller->SuspendAnimations(1.0);
+ controller->PauseAnimation(animation_id, kInitialTickTime + 1.0);
EXPECT_EQ(Animation::Paused,
controller->GetAnimation(group_id,
Animation::Opacity)->run_state());
@@ -138,18 +227,6 @@ TEST(LayerAnimationControllerTest, SyncPauseAndResume) {
EXPECT_EQ(Animation::Paused,
controller_impl->GetAnimation(group_id,
Animation::Opacity)->run_state());
-
- // Resume the main-thread animation.
- controller->ResumeAnimations(2.0);
- EXPECT_EQ(Animation::Running,
- controller->GetAnimation(group_id,
- Animation::Opacity)->run_state());
-
- // The pause run state change should make it to the impl thread controller.
- controller->PushAnimationUpdatesTo(controller_impl.get());
- EXPECT_EQ(Animation::Running,
- controller_impl->GetAnimation(group_id,
- Animation::Opacity)->run_state());
}
TEST(LayerAnimationControllerTest, DoNotSyncFinishedAnimation) {
@@ -176,8 +253,11 @@ TEST(LayerAnimationControllerTest, DoNotSyncFinishedAnimation) {
Animation::Opacity)->run_state());
// Notify main thread controller that the animation has started.
- AnimationEvent animation_started_event(
- AnimationEvent::Started, 0, group_id, Animation::Opacity, 0);
+ AnimationEvent animation_started_event(AnimationEvent::Started,
+ 0,
+ group_id,
+ Animation::Opacity,
+ kInitialTickTime);
controller->NotifyAnimationStarted(animation_started_event, 0.0);
// Force animation to complete on impl thread.
@@ -207,11 +287,11 @@ TEST(LayerAnimationControllerTest, AnimationsAreDeleted) {
controller_impl->AddValueObserver(&dummy_impl);
AddOpacityTransitionToController(controller.get(), 1.0, 0.0f, 1.0f, false);
- controller->Animate(0.0);
+ controller->Animate(kInitialTickTime);
controller->UpdateState(true, NULL);
controller->PushAnimationUpdatesTo(controller_impl.get());
- controller_impl->Animate(0.5);
+ controller_impl->Animate(kInitialTickTime + 0.5);
controller_impl->UpdateState(true, events.get());
// There should be a Started event for the animation.
@@ -219,13 +299,18 @@ TEST(LayerAnimationControllerTest, AnimationsAreDeleted) {
EXPECT_EQ(AnimationEvent::Started, (*events)[0].type);
controller->NotifyAnimationStarted((*events)[0], 0.0);
- controller->Animate(1.0);
+ controller->Animate(kInitialTickTime + 1.0);
controller->UpdateState(true, NULL);
+ EXPECT_FALSE(dummy.animation_waiting_for_deletion());
+ EXPECT_FALSE(dummy_impl.animation_waiting_for_deletion());
+
events.reset(new AnimationEventsVector);
- controller_impl->Animate(2.0);
+ controller_impl->Animate(kInitialTickTime + 2.0);
controller_impl->UpdateState(true, events.get());
+ EXPECT_TRUE(dummy_impl.animation_waiting_for_deletion());
+
// There should be a Finished event for the animation.
EXPECT_EQ(1u, events->size());
EXPECT_EQ(AnimationEvent::Finished, (*events)[0].type);
@@ -236,8 +321,9 @@ TEST(LayerAnimationControllerTest, AnimationsAreDeleted) {
controller->NotifyAnimationFinished((*events)[0], 0.0);
- controller->Animate(3.0);
+ controller->Animate(kInitialTickTime + 3.0);
controller->UpdateState(true, NULL);
+ EXPECT_TRUE(dummy.animation_waiting_for_deletion());
controller->PushAnimationUpdatesTo(controller_impl.get());
@@ -272,14 +358,14 @@ TEST(LayerAnimationControllerTest, TrivialTransition) {
Animation::Opacity));
controller->AddAnimation(to_add.Pass());
- controller->Animate(0.0);
+ controller->Animate(kInitialTickTime);
controller->UpdateState(true, events.get());
EXPECT_TRUE(controller->HasActiveAnimation());
EXPECT_EQ(0.f, dummy.opacity());
// A non-impl-only animation should not generate property updates.
const AnimationEvent* event = GetMostRecentPropertyUpdateEvent(events.get());
EXPECT_FALSE(event);
- controller->Animate(1.0);
+ controller->Animate(kInitialTickTime + 1.0);
controller->UpdateState(true, events.get());
EXPECT_EQ(1.f, dummy.opacity());
EXPECT_FALSE(controller->HasActiveAnimation());
@@ -302,7 +388,7 @@ TEST(LayerAnimationControllerTest, TrivialTransitionOnImpl) {
to_add->set_is_impl_only(true);
controller_impl->AddAnimation(to_add.Pass());
- controller_impl->Animate(0.0);
+ controller_impl->Animate(kInitialTickTime);
controller_impl->UpdateState(true, events.get());
EXPECT_TRUE(controller_impl->HasActiveAnimation());
EXPECT_EQ(0.f, dummy_impl.opacity());
@@ -311,7 +397,7 @@ TEST(LayerAnimationControllerTest, TrivialTransitionOnImpl) {
GetMostRecentPropertyUpdateEvent(events.get());
EXPECT_EQ(0.f, start_opacity_event->opacity);
- controller_impl->Animate(1.0);
+ controller_impl->Animate(kInitialTickTime + 1.0);
controller_impl->UpdateState(true, events.get());
EXPECT_EQ(1.f, dummy_impl.opacity());
EXPECT_FALSE(controller_impl->HasActiveAnimation());
@@ -339,11 +425,11 @@ TEST(LayerAnimationControllerTest, TrivialTransformOnImpl) {
// Create simple Transform animation.
TransformOperations operations;
- curve->AddKeyframe(TransformKeyframe::Create(
- 0, operations, scoped_ptr<cc::TimingFunction>()));
+ curve->AddKeyframe(
+ TransformKeyframe::Create(0, operations, scoped_ptr<TimingFunction>()));
operations.AppendTranslate(delta_x, delta_y, 0);
- curve->AddKeyframe(TransformKeyframe::Create(
- 1, operations, scoped_ptr<cc::TimingFunction>()));
+ curve->AddKeyframe(
+ TransformKeyframe::Create(1, operations, scoped_ptr<TimingFunction>()));
scoped_ptr<Animation> animation(Animation::Create(
curve.PassAs<AnimationCurve>(), 1, 0, Animation::Transform));
@@ -351,7 +437,7 @@ TEST(LayerAnimationControllerTest, TrivialTransformOnImpl) {
controller_impl->AddAnimation(animation.Pass());
// Run animation.
- controller_impl->Animate(0.0);
+ controller_impl->Animate(kInitialTickTime);
controller_impl->UpdateState(true, events.get());
EXPECT_TRUE(controller_impl->HasActiveAnimation());
EXPECT_EQ(gfx::Transform(), dummy_impl.transform());
@@ -365,7 +451,7 @@ TEST(LayerAnimationControllerTest, TrivialTransformOnImpl) {
gfx::Transform expected_transform;
expected_transform.Translate(delta_x, delta_y);
- controller_impl->Animate(1.0);
+ controller_impl->Animate(kInitialTickTime + 1.0);
controller_impl->UpdateState(true, events.get());
EXPECT_EQ(expected_transform, dummy_impl.transform());
EXPECT_FALSE(controller_impl->HasActiveAnimation());
@@ -376,17 +462,321 @@ TEST(LayerAnimationControllerTest, TrivialTransformOnImpl) {
EXPECT_TRUE(end_transform_event->is_impl_only);
}
+TEST(LayerAnimationControllerTest, FilterTransition) {
+ scoped_ptr<AnimationEventsVector> events(
+ make_scoped_ptr(new AnimationEventsVector));
+ FakeLayerAnimationValueObserver dummy;
+ scoped_refptr<LayerAnimationController> controller(
+ LayerAnimationController::Create(0));
+ controller->AddValueObserver(&dummy);
+
+ scoped_ptr<KeyframedFilterAnimationCurve> curve(
+ KeyframedFilterAnimationCurve::Create());
+
+ FilterOperations start_filters;
+ start_filters.Append(FilterOperation::CreateBrightnessFilter(1.f));
+ curve->AddKeyframe(
+ FilterKeyframe::Create(0, start_filters, scoped_ptr<TimingFunction>()));
+ FilterOperations end_filters;
+ end_filters.Append(FilterOperation::CreateBrightnessFilter(2.f));
+ curve->AddKeyframe(
+ FilterKeyframe::Create(1, end_filters, scoped_ptr<TimingFunction>()));
+
+ scoped_ptr<Animation> animation(Animation::Create(
+ curve.PassAs<AnimationCurve>(), 1, 0, Animation::Filter));
+ controller->AddAnimation(animation.Pass());
+
+ controller->Animate(kInitialTickTime);
+ controller->UpdateState(true, events.get());
+ EXPECT_TRUE(controller->HasActiveAnimation());
+ EXPECT_EQ(start_filters, dummy.filters());
+ // A non-impl-only animation should not generate property updates.
+ const AnimationEvent* event = GetMostRecentPropertyUpdateEvent(events.get());
+ EXPECT_FALSE(event);
+
+ controller->Animate(kInitialTickTime + 0.5);
+ controller->UpdateState(true, events.get());
+ EXPECT_EQ(1u, dummy.filters().size());
+ EXPECT_EQ(FilterOperation::CreateBrightnessFilter(1.5f),
+ dummy.filters().at(0));
+ event = GetMostRecentPropertyUpdateEvent(events.get());
+ EXPECT_FALSE(event);
+
+ controller->Animate(kInitialTickTime + 1.0);
+ controller->UpdateState(true, events.get());
+ EXPECT_EQ(end_filters, dummy.filters());
+ EXPECT_FALSE(controller->HasActiveAnimation());
+ event = GetMostRecentPropertyUpdateEvent(events.get());
+ EXPECT_FALSE(event);
+}
+
+TEST(LayerAnimationControllerTest, FilterTransitionOnImplOnly) {
+ scoped_ptr<AnimationEventsVector> events(
+ make_scoped_ptr(new AnimationEventsVector));
+ FakeLayerAnimationValueObserver dummy_impl;
+ scoped_refptr<LayerAnimationController> controller_impl(
+ LayerAnimationController::Create(0));
+ controller_impl->AddValueObserver(&dummy_impl);
+
+ scoped_ptr<KeyframedFilterAnimationCurve> curve(
+ KeyframedFilterAnimationCurve::Create());
+
+ // Create simple Filter animation.
+ FilterOperations start_filters;
+ start_filters.Append(FilterOperation::CreateBrightnessFilter(1.f));
+ curve->AddKeyframe(
+ FilterKeyframe::Create(0, start_filters, scoped_ptr<TimingFunction>()));
+ FilterOperations end_filters;
+ end_filters.Append(FilterOperation::CreateBrightnessFilter(2.f));
+ curve->AddKeyframe(
+ FilterKeyframe::Create(1, end_filters, scoped_ptr<TimingFunction>()));
+
+ scoped_ptr<Animation> animation(Animation::Create(
+ curve.PassAs<AnimationCurve>(), 1, 0, Animation::Filter));
+ animation->set_is_impl_only(true);
+ controller_impl->AddAnimation(animation.Pass());
+
+ // Run animation.
+ controller_impl->Animate(kInitialTickTime);
+ controller_impl->UpdateState(true, events.get());
+ EXPECT_TRUE(controller_impl->HasActiveAnimation());
+ EXPECT_EQ(start_filters, dummy_impl.filters());
+ EXPECT_EQ(2u, events->size());
+ const AnimationEvent* start_filter_event =
+ GetMostRecentPropertyUpdateEvent(events.get());
+ EXPECT_TRUE(start_filter_event);
+ EXPECT_EQ(start_filters, start_filter_event->filters);
+ EXPECT_TRUE(start_filter_event->is_impl_only);
+
+ controller_impl->Animate(kInitialTickTime + 1.0);
+ controller_impl->UpdateState(true, events.get());
+ EXPECT_EQ(end_filters, dummy_impl.filters());
+ EXPECT_FALSE(controller_impl->HasActiveAnimation());
+ EXPECT_EQ(4u, events->size());
+ const AnimationEvent* end_filter_event =
+ GetMostRecentPropertyUpdateEvent(events.get());
+ EXPECT_TRUE(end_filter_event);
+ EXPECT_EQ(end_filters, end_filter_event->filters);
+ EXPECT_TRUE(end_filter_event->is_impl_only);
+}
+
+TEST(LayerAnimationControllerTest, ScrollOffsetTransition) {
+ FakeLayerAnimationValueObserver dummy_impl;
+ FakeLayerAnimationValueProvider dummy_provider_impl;
+ scoped_refptr<LayerAnimationController> controller_impl(
+ LayerAnimationController::Create(0));
+ controller_impl->AddValueObserver(&dummy_impl);
+ controller_impl->set_value_provider(&dummy_provider_impl);
+ scoped_ptr<AnimationEventsVector> events(
+ make_scoped_ptr(new AnimationEventsVector));
+ FakeLayerAnimationValueObserver dummy;
+ FakeLayerAnimationValueProvider dummy_provider;
+ scoped_refptr<LayerAnimationController> controller(
+ LayerAnimationController::Create(0));
+ controller->AddValueObserver(&dummy);
+ controller->set_value_provider(&dummy_provider);
+
+ gfx::Vector2dF initial_value(100.f, 300.f);
+ gfx::Vector2dF target_value(300.f, 200.f);
+ scoped_ptr<ScrollOffsetAnimationCurve> curve(
+ ScrollOffsetAnimationCurve::Create(
+ target_value,
+ EaseInOutTimingFunction::Create().Pass()));
+
+ scoped_ptr<Animation> animation(Animation::Create(
+ curve.PassAs<AnimationCurve>(), 1, 0, Animation::ScrollOffset));
+ animation->set_needs_synchronized_start_time(true);
+ controller->AddAnimation(animation.Pass());
+
+ dummy_provider_impl.set_scroll_offset(initial_value);
+ controller->PushAnimationUpdatesTo(controller_impl.get());
+ EXPECT_TRUE(controller_impl->GetAnimation(Animation::ScrollOffset));
+ double duration = controller_impl->GetAnimation(
+ Animation::ScrollOffset)->curve()->Duration();
+
+ EXPECT_EQ(
+ duration,
+ controller->GetAnimation(Animation::ScrollOffset)->curve()->Duration());
+
+ controller->Animate(kInitialTickTime);
+ controller->UpdateState(true, NULL);
+ EXPECT_TRUE(controller->HasActiveAnimation());
+ EXPECT_EQ(initial_value, dummy.scroll_offset());
+
+ controller_impl->Animate(kInitialTickTime);
+ controller_impl->UpdateState(true, events.get());
+ EXPECT_TRUE(controller_impl->HasActiveAnimation());
+ EXPECT_EQ(initial_value, dummy_impl.scroll_offset());
+ // Scroll offset animations should not generate property updates.
+ const AnimationEvent* event = GetMostRecentPropertyUpdateEvent(events.get());
+ EXPECT_FALSE(event);
+
+ controller->NotifyAnimationStarted((*events)[0], 0.0);
+ controller->Animate(kInitialTickTime + duration/2.0);
+ controller->UpdateState(true, NULL);
+ EXPECT_TRUE(controller->HasActiveAnimation());
+ EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(200.f, 250.f), dummy.scroll_offset());
+
+ controller_impl->Animate(kInitialTickTime + duration/2.0);
+ controller_impl->UpdateState(true, events.get());
+ EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(200.f, 250.f),
+ dummy_impl.scroll_offset());
+ event = GetMostRecentPropertyUpdateEvent(events.get());
+ EXPECT_FALSE(event);
+
+ controller_impl->Animate(kInitialTickTime + duration);
+ controller_impl->UpdateState(true, events.get());
+ EXPECT_VECTOR2DF_EQ(target_value, dummy_impl.scroll_offset());
+ EXPECT_FALSE(controller_impl->HasActiveAnimation());
+ event = GetMostRecentPropertyUpdateEvent(events.get());
+ EXPECT_FALSE(event);
+
+ controller->Animate(kInitialTickTime + duration);
+ controller->UpdateState(true, NULL);
+ EXPECT_VECTOR2DF_EQ(target_value, dummy.scroll_offset());
+ EXPECT_FALSE(controller->HasActiveAnimation());
+}
+
+// Ensure that when the impl controller doesn't have a value provider,
+// the main-thread controller's value provider is used to obtain the intial
+// scroll offset.
+TEST(LayerAnimationControllerTest, ScrollOffsetTransitionNoImplProvider) {
+ FakeLayerAnimationValueObserver dummy_impl;
+ scoped_refptr<LayerAnimationController> controller_impl(
+ LayerAnimationController::Create(0));
+ controller_impl->AddValueObserver(&dummy_impl);
+ scoped_ptr<AnimationEventsVector> events(
+ make_scoped_ptr(new AnimationEventsVector));
+ FakeLayerAnimationValueObserver dummy;
+ FakeLayerAnimationValueProvider dummy_provider;
+ scoped_refptr<LayerAnimationController> controller(
+ LayerAnimationController::Create(0));
+ controller->AddValueObserver(&dummy);
+ controller->set_value_provider(&dummy_provider);
+
+ gfx::Vector2dF initial_value(500.f, 100.f);
+ gfx::Vector2dF target_value(300.f, 200.f);
+ scoped_ptr<ScrollOffsetAnimationCurve> curve(
+ ScrollOffsetAnimationCurve::Create(
+ target_value,
+ EaseInOutTimingFunction::Create().Pass()));
+
+ scoped_ptr<Animation> animation(Animation::Create(
+ curve.PassAs<AnimationCurve>(), 1, 0, Animation::ScrollOffset));
+ animation->set_needs_synchronized_start_time(true);
+ controller->AddAnimation(animation.Pass());
+
+ dummy_provider.set_scroll_offset(initial_value);
+ controller->PushAnimationUpdatesTo(controller_impl.get());
+ EXPECT_TRUE(controller_impl->GetAnimation(Animation::ScrollOffset));
+ double duration = controller_impl->GetAnimation(
+ Animation::ScrollOffset)->curve()->Duration();
+
+ EXPECT_EQ(
+ duration,
+ controller->GetAnimation(Animation::ScrollOffset)->curve()->Duration());
+
+ controller->Animate(kInitialTickTime);
+ controller->UpdateState(true, NULL);
+ EXPECT_TRUE(controller->HasActiveAnimation());
+ EXPECT_EQ(initial_value, dummy.scroll_offset());
+
+ controller_impl->Animate(kInitialTickTime);
+ controller_impl->UpdateState(true, events.get());
+ EXPECT_TRUE(controller_impl->HasActiveAnimation());
+ EXPECT_EQ(initial_value, dummy_impl.scroll_offset());
+ // Scroll offset animations should not generate property updates.
+ const AnimationEvent* event = GetMostRecentPropertyUpdateEvent(events.get());
+ EXPECT_FALSE(event);
+
+ controller->NotifyAnimationStarted((*events)[0], 0.0);
+ controller->Animate(kInitialTickTime + duration/2.0);
+ controller->UpdateState(true, NULL);
+ EXPECT_TRUE(controller->HasActiveAnimation());
+ EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(400.f, 150.f), dummy.scroll_offset());
+
+ controller_impl->Animate(kInitialTickTime + duration/2.0);
+ controller_impl->UpdateState(true, events.get());
+ EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(400.f, 150.f),
+ dummy_impl.scroll_offset());
+ event = GetMostRecentPropertyUpdateEvent(events.get());
+ EXPECT_FALSE(event);
+
+ controller_impl->Animate(kInitialTickTime + duration);
+ controller_impl->UpdateState(true, events.get());
+ EXPECT_VECTOR2DF_EQ(target_value, dummy_impl.scroll_offset());
+ EXPECT_FALSE(controller_impl->HasActiveAnimation());
+ event = GetMostRecentPropertyUpdateEvent(events.get());
+ EXPECT_FALSE(event);
+
+ controller->Animate(kInitialTickTime + duration);
+ controller->UpdateState(true, NULL);
+ EXPECT_VECTOR2DF_EQ(target_value, dummy.scroll_offset());
+ EXPECT_FALSE(controller->HasActiveAnimation());
+}
+
+TEST(LayerAnimationControllerTest, ScrollOffsetTransitionOnImplOnly) {
+ FakeLayerAnimationValueObserver dummy_impl;
+ scoped_refptr<LayerAnimationController> controller_impl(
+ LayerAnimationController::Create(0));
+ controller_impl->AddValueObserver(&dummy_impl);
+ scoped_ptr<AnimationEventsVector> events(
+ make_scoped_ptr(new AnimationEventsVector));
+
+ gfx::Vector2dF initial_value(100.f, 300.f);
+ gfx::Vector2dF target_value(300.f, 200.f);
+ scoped_ptr<ScrollOffsetAnimationCurve> curve(
+ ScrollOffsetAnimationCurve::Create(
+ target_value,
+ EaseInOutTimingFunction::Create().Pass()));
+ curve->SetInitialValue(initial_value);
+ double duration = curve->Duration();
+
+ scoped_ptr<Animation> animation(Animation::Create(
+ curve.PassAs<AnimationCurve>(), 1, 0, Animation::ScrollOffset));
+ animation->set_is_impl_only(true);
+ controller_impl->AddAnimation(animation.Pass());
+
+ controller_impl->Animate(kInitialTickTime);
+ controller_impl->UpdateState(true, events.get());
+ EXPECT_TRUE(controller_impl->HasActiveAnimation());
+ EXPECT_EQ(initial_value, dummy_impl.scroll_offset());
+ // Scroll offset animations should not generate property updates.
+ const AnimationEvent* event = GetMostRecentPropertyUpdateEvent(events.get());
+ EXPECT_FALSE(event);
+
+ controller_impl->Animate(kInitialTickTime + duration/2.0);
+ controller_impl->UpdateState(true, events.get());
+ EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(200.f, 250.f),
+ dummy_impl.scroll_offset());
+ event = GetMostRecentPropertyUpdateEvent(events.get());
+ EXPECT_FALSE(event);
+
+ controller_impl->Animate(kInitialTickTime + duration);
+ controller_impl->UpdateState(true, events.get());
+ EXPECT_VECTOR2DF_EQ(target_value, dummy_impl.scroll_offset());
+ EXPECT_FALSE(controller_impl->HasActiveAnimation());
+ event = GetMostRecentPropertyUpdateEvent(events.get());
+ EXPECT_FALSE(event);
+}
+
class FakeAnimationDelegate : public AnimationDelegate {
public:
FakeAnimationDelegate()
: started_(false),
finished_(false) {}
- virtual void NotifyAnimationStarted(double time) OVERRIDE {
+ virtual void NotifyAnimationStarted(
+ double wall_clock_time,
+ base::TimeTicks monotonic_time,
+ Animation::TargetProperty target_property) OVERRIDE {
started_ = true;
}
- virtual void NotifyAnimationFinished(double time) OVERRIDE {
+ virtual void NotifyAnimationFinished(
+ double wall_clock_time,
+ base::TimeTicks monotonic_time,
+ Animation::TargetProperty target_property) OVERRIDE {
finished_ = true;
}
@@ -423,7 +813,7 @@ TEST(LayerAnimationControllerTest,
to_add->set_is_impl_only(true);
controller_impl->AddAnimation(to_add.Pass());
- controller_impl->Animate(0.0);
+ controller_impl->Animate(kInitialTickTime);
controller_impl->UpdateState(true, events.get());
// We should receive 2 events (a started notification and a property update).
@@ -440,7 +830,7 @@ TEST(LayerAnimationControllerTest,
EXPECT_TRUE(delegate.started());
events.reset(new AnimationEventsVector);
- controller_impl->Animate(1.0);
+ controller_impl->Animate(kInitialTickTime + 1.0);
controller_impl->UpdateState(true, events.get());
// We should receive 2 events (a finished notification and a property update).
@@ -477,24 +867,27 @@ TEST(LayerAnimationControllerTest,
// We should pause at the first keyframe indefinitely waiting for that
// animation to start.
controller->AddAnimation(to_add.Pass());
- controller->Animate(0.0);
+ controller->Animate(kInitialTickTime);
controller->UpdateState(true, events.get());
EXPECT_TRUE(controller->HasActiveAnimation());
EXPECT_EQ(0.f, dummy.opacity());
- controller->Animate(1.0);
+ controller->Animate(kInitialTickTime + 1.0);
controller->UpdateState(true, events.get());
EXPECT_TRUE(controller->HasActiveAnimation());
EXPECT_EQ(0.f, dummy.opacity());
- controller->Animate(2.0);
+ controller->Animate(kInitialTickTime + 2.0);
controller->UpdateState(true, events.get());
EXPECT_TRUE(controller->HasActiveAnimation());
EXPECT_EQ(0.f, dummy.opacity());
// Send the synchronized start time.
- controller->NotifyAnimationStarted(
- AnimationEvent(AnimationEvent::Started, 0, 1, Animation::Opacity, 2),
- 0.0);
- controller->Animate(5.0);
+ controller->NotifyAnimationStarted(AnimationEvent(AnimationEvent::Started,
+ 0,
+ 1,
+ Animation::Opacity,
+ kInitialTickTime + 2),
+ 0.0);
+ controller->Animate(kInitialTickTime + 5.0);
controller->UpdateState(true, events.get());
EXPECT_EQ(1.f, dummy.opacity());
EXPECT_FALSE(controller->HasActiveAnimation());
@@ -519,15 +912,15 @@ TEST(LayerAnimationControllerTest, TrivialQueuing) {
2,
Animation::Opacity));
- controller->Animate(0.0);
+ controller->Animate(kInitialTickTime);
controller->UpdateState(true, events.get());
EXPECT_TRUE(controller->HasActiveAnimation());
EXPECT_EQ(0.f, dummy.opacity());
- controller->Animate(1.0);
+ controller->Animate(kInitialTickTime + 1.0);
controller->UpdateState(true, events.get());
EXPECT_TRUE(controller->HasActiveAnimation());
EXPECT_EQ(1.f, dummy.opacity());
- controller->Animate(2.0);
+ controller->Animate(kInitialTickTime + 2.0);
controller->UpdateState(true, events.get());
EXPECT_EQ(0.5f, dummy.opacity());
EXPECT_FALSE(controller->HasActiveAnimation());
@@ -545,7 +938,7 @@ TEST(LayerAnimationControllerTest, Interrupt) {
scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(),
1,
Animation::Opacity));
- controller->Animate(0.0);
+ controller->Animate(kInitialTickTime);
controller->UpdateState(true, events.get());
EXPECT_TRUE(controller->HasActiveAnimation());
EXPECT_EQ(0.f, dummy.opacity());
@@ -555,16 +948,16 @@ TEST(LayerAnimationControllerTest, Interrupt) {
new FakeFloatTransition(1.0, 1.f, 0.5f)).Pass(),
2,
Animation::Opacity));
- to_add->SetRunState(Animation::WaitingForNextTick, 0);
+ controller->AbortAnimations(Animation::Opacity);
controller->AddAnimation(to_add.Pass());
- // Since the animation was in the WaitingForNextTick state, it should start
+ // Since the previous animation was aborted, the new animation should start
// right in this call to animate.
- controller->Animate(0.5);
+ controller->Animate(kInitialTickTime + 0.5);
controller->UpdateState(true, events.get());
EXPECT_TRUE(controller->HasActiveAnimation());
EXPECT_EQ(1.f, dummy.opacity());
- controller->Animate(1.5);
+ controller->Animate(kInitialTickTime + 1.5);
controller->UpdateState(true, events.get());
EXPECT_EQ(0.5f, dummy.opacity());
EXPECT_FALSE(controller->HasActiveAnimation());
@@ -593,17 +986,17 @@ TEST(LayerAnimationControllerTest, ScheduleTogetherWhenAPropertyIsBlocked) {
2,
Animation::Opacity));
- controller->Animate(0.0);
+ controller->Animate(kInitialTickTime);
controller->UpdateState(true, events.get());
EXPECT_EQ(0.f, dummy.opacity());
EXPECT_TRUE(controller->HasActiveAnimation());
- controller->Animate(1.0);
+ controller->Animate(kInitialTickTime + 1.0);
controller->UpdateState(true, events.get());
// Should not have started the float transition yet.
EXPECT_TRUE(controller->HasActiveAnimation());
EXPECT_EQ(0.f, dummy.opacity());
// The float animation should have started at time 1 and should be done.
- controller->Animate(2.0);
+ controller->Animate(kInitialTickTime + 2.0);
controller->UpdateState(true, events.get());
EXPECT_EQ(1.f, dummy.opacity());
EXPECT_FALSE(controller->HasActiveAnimation());
@@ -635,14 +1028,14 @@ TEST(LayerAnimationControllerTest, ScheduleTogetherWithAnAnimWaiting) {
Animation::Opacity));
// Animations with id 1 should both start now.
- controller->Animate(0.0);
+ controller->Animate(kInitialTickTime);
controller->UpdateState(true, events.get());
EXPECT_TRUE(controller->HasActiveAnimation());
EXPECT_EQ(0.f, dummy.opacity());
// The opacity animation should have finished at time 1, but the group
// of animations with id 1 don't finish until time 2 because of the length
// of the transform animation.
- controller->Animate(2.0);
+ controller->Animate(kInitialTickTime + 2.0);
controller->UpdateState(true, events.get());
// Should not have started the float transition yet.
EXPECT_TRUE(controller->HasActiveAnimation());
@@ -650,139 +1043,9 @@ TEST(LayerAnimationControllerTest, ScheduleTogetherWithAnAnimWaiting) {
// The second opacity animation should start at time 2 and should be done by
// time 3.
- controller->Animate(3.0);
- controller->UpdateState(true, events.get());
- EXPECT_EQ(0.5f, dummy.opacity());
- EXPECT_FALSE(controller->HasActiveAnimation());
-}
-
-// Tests scheduling an animation to start in the future.
-TEST(LayerAnimationControllerTest, ScheduleAnimation) {
- scoped_ptr<AnimationEventsVector> events(
- make_scoped_ptr(new AnimationEventsVector));
- FakeLayerAnimationValueObserver dummy;
- scoped_refptr<LayerAnimationController> controller(
- LayerAnimationController::Create(0));
- controller->AddValueObserver(&dummy);
-
- scoped_ptr<Animation> to_add(CreateAnimation(
- scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(),
- 1,
- Animation::Opacity));
- to_add->SetRunState(Animation::WaitingForStartTime, 0);
- to_add->set_start_time(1.f);
- controller->AddAnimation(to_add.Pass());
-
- controller->Animate(0.0);
+ controller->Animate(kInitialTickTime + 3.0);
controller->UpdateState(true, events.get());
- EXPECT_TRUE(controller->HasActiveAnimation());
- EXPECT_EQ(0.f, dummy.opacity());
- controller->Animate(1.0);
- controller->UpdateState(true, events.get());
- EXPECT_TRUE(controller->HasActiveAnimation());
- EXPECT_EQ(0.f, dummy.opacity());
- controller->Animate(2.0);
- controller->UpdateState(true, events.get());
- EXPECT_EQ(1.f, dummy.opacity());
- EXPECT_FALSE(controller->HasActiveAnimation());
-}
-
-// Tests scheduling an animation to start in the future that's interrupting a
-// running animation.
-TEST(LayerAnimationControllerTest,
- ScheduledAnimationInterruptsRunningAnimation) {
- scoped_ptr<AnimationEventsVector> events(
- make_scoped_ptr(new AnimationEventsVector));
- FakeLayerAnimationValueObserver dummy;
- scoped_refptr<LayerAnimationController> controller(
- LayerAnimationController::Create(0));
- controller->AddValueObserver(&dummy);
-
- controller->AddAnimation(CreateAnimation(
- scoped_ptr<AnimationCurve>(new FakeFloatTransition(2.0, 0.f, 1.f)).Pass(),
- 1,
- Animation::Opacity));
-
- scoped_ptr<Animation> to_add(CreateAnimation(
- scoped_ptr<AnimationCurve>(
- new FakeFloatTransition(1.0, 0.5f, 0.f)).Pass(),
- 2,
- Animation::Opacity));
- to_add->SetRunState(Animation::WaitingForStartTime, 0);
- to_add->set_start_time(1.f);
- controller->AddAnimation(to_add.Pass());
-
- // First 2s opacity transition should start immediately.
- controller->Animate(0.0);
- controller->UpdateState(true, events.get());
- EXPECT_TRUE(controller->HasActiveAnimation());
- EXPECT_EQ(0.f, dummy.opacity());
- controller->Animate(0.5);
- controller->UpdateState(true, events.get());
- EXPECT_TRUE(controller->HasActiveAnimation());
- EXPECT_EQ(0.25f, dummy.opacity());
- controller->Animate(1.0);
- controller->UpdateState(true, events.get());
- EXPECT_TRUE(controller->HasActiveAnimation());
EXPECT_EQ(0.5f, dummy.opacity());
- controller->Animate(2.0);
- controller->UpdateState(true, events.get());
- EXPECT_EQ(0.f, dummy.opacity());
- EXPECT_FALSE(controller->HasActiveAnimation());
-}
-
-// Tests scheduling an animation to start in the future that interrupts a
-// running animation and there is yet another animation queued to start later.
-TEST(LayerAnimationControllerTest,
- ScheduledAnimationInterruptsRunningAnimationWithAnimInQueue) {
- scoped_ptr<AnimationEventsVector> events(
- make_scoped_ptr(new AnimationEventsVector));
- FakeLayerAnimationValueObserver dummy;
- scoped_refptr<LayerAnimationController> controller(
- LayerAnimationController::Create(0));
- controller->AddValueObserver(&dummy);
-
- controller->AddAnimation(CreateAnimation(
- scoped_ptr<AnimationCurve>(new FakeFloatTransition(2.0, 0.f, 1.f)).Pass(),
- 1,
- Animation::Opacity));
-
- scoped_ptr<Animation> to_add(CreateAnimation(
- scoped_ptr<AnimationCurve>(
- new FakeFloatTransition(2.0, 0.5f, 0.f)).Pass(),
- 2,
- Animation::Opacity));
- to_add->SetRunState(Animation::WaitingForStartTime, 0);
- to_add->set_start_time(1.f);
- controller->AddAnimation(to_add.Pass());
-
- controller->AddAnimation(CreateAnimation(
- scoped_ptr<AnimationCurve>(
- new FakeFloatTransition(1.0, 0.f, 0.75f)).Pass(),
- 3,
- Animation::Opacity));
-
- // First 2s opacity transition should start immediately.
- controller->Animate(0.0);
- controller->UpdateState(true, events.get());
- EXPECT_TRUE(controller->HasActiveAnimation());
- EXPECT_EQ(0.f, dummy.opacity());
- controller->Animate(0.5);
- controller->UpdateState(true, events.get());
- EXPECT_TRUE(controller->HasActiveAnimation());
- EXPECT_EQ(0.25f, dummy.opacity());
- EXPECT_TRUE(controller->HasActiveAnimation());
- controller->Animate(1.0);
- controller->UpdateState(true, events.get());
- EXPECT_TRUE(controller->HasActiveAnimation());
- EXPECT_EQ(0.5f, dummy.opacity());
- controller->Animate(3.0);
- controller->UpdateState(true, events.get());
- EXPECT_TRUE(controller->HasActiveAnimation());
- EXPECT_EQ(0.f, dummy.opacity());
- controller->Animate(4.0);
- controller->UpdateState(true, events.get());
- EXPECT_EQ(0.75f, dummy.opacity());
EXPECT_FALSE(controller->HasActiveAnimation());
}
@@ -802,33 +1065,33 @@ TEST(LayerAnimationControllerTest, TrivialLooping) {
to_add->set_iterations(3);
controller->AddAnimation(to_add.Pass());
- controller->Animate(0.0);
+ controller->Animate(kInitialTickTime);
controller->UpdateState(true, events.get());
EXPECT_TRUE(controller->HasActiveAnimation());
EXPECT_EQ(0.f, dummy.opacity());
- controller->Animate(1.25);
+ controller->Animate(kInitialTickTime + 1.25);
controller->UpdateState(true, events.get());
EXPECT_TRUE(controller->HasActiveAnimation());
EXPECT_EQ(0.25f, dummy.opacity());
- controller->Animate(1.75);
+ controller->Animate(kInitialTickTime + 1.75);
controller->UpdateState(true, events.get());
EXPECT_TRUE(controller->HasActiveAnimation());
EXPECT_EQ(0.75f, dummy.opacity());
- controller->Animate(2.25);
+ controller->Animate(kInitialTickTime + 2.25);
controller->UpdateState(true, events.get());
EXPECT_TRUE(controller->HasActiveAnimation());
EXPECT_EQ(0.25f, dummy.opacity());
- controller->Animate(2.75);
+ controller->Animate(kInitialTickTime + 2.75);
controller->UpdateState(true, events.get());
EXPECT_TRUE(controller->HasActiveAnimation());
EXPECT_EQ(0.75f, dummy.opacity());
- controller->Animate(3.0);
+ controller->Animate(kInitialTickTime + 3.0);
controller->UpdateState(true, events.get());
EXPECT_FALSE(controller->HasActiveAnimation());
EXPECT_EQ(1.f, dummy.opacity());
// Just be extra sure.
- controller->Animate(4.0);
+ controller->Animate(kInitialTickTime + 4.0);
controller->UpdateState(true, events.get());
EXPECT_EQ(1.f, dummy.opacity());
}
@@ -850,31 +1113,31 @@ TEST(LayerAnimationControllerTest, InfiniteLooping) {
to_add->set_iterations(-1);
controller->AddAnimation(to_add.Pass());
- controller->Animate(0.0);
+ controller->Animate(kInitialTickTime);
controller->UpdateState(true, events.get());
EXPECT_TRUE(controller->HasActiveAnimation());
EXPECT_EQ(0.f, dummy.opacity());
- controller->Animate(1.25);
+ controller->Animate(kInitialTickTime + 1.25);
controller->UpdateState(true, events.get());
EXPECT_TRUE(controller->HasActiveAnimation());
EXPECT_EQ(0.25f, dummy.opacity());
- controller->Animate(1.75);
+ controller->Animate(kInitialTickTime + 1.75);
controller->UpdateState(true, events.get());
EXPECT_TRUE(controller->HasActiveAnimation());
EXPECT_EQ(0.75f, dummy.opacity());
- controller->Animate(1073741824.25);
+ controller->Animate(kInitialTickTime + 1073741824.25);
controller->UpdateState(true, events.get());
EXPECT_TRUE(controller->HasActiveAnimation());
EXPECT_EQ(0.25f, dummy.opacity());
- controller->Animate(1073741824.75);
+ controller->Animate(kInitialTickTime + 1073741824.75);
controller->UpdateState(true, events.get());
EXPECT_TRUE(controller->HasActiveAnimation());
EXPECT_EQ(0.75f, dummy.opacity());
EXPECT_TRUE(controller->GetAnimation(id, Animation::Opacity));
controller->GetAnimation(id, Animation::Opacity)->SetRunState(
- Animation::Aborted, 0.75);
+ Animation::Aborted, kInitialTickTime + 0.75);
EXPECT_FALSE(controller->HasActiveAnimation());
EXPECT_EQ(0.75f, dummy.opacity());
}
@@ -894,33 +1157,33 @@ TEST(LayerAnimationControllerTest, PauseResume) {
id,
Animation::Opacity));
- controller->Animate(0.0);
+ controller->Animate(kInitialTickTime);
controller->UpdateState(true, events.get());
EXPECT_TRUE(controller->HasActiveAnimation());
EXPECT_EQ(0.f, dummy.opacity());
- controller->Animate(0.5);
+ controller->Animate(kInitialTickTime + 0.5);
controller->UpdateState(true, events.get());
EXPECT_TRUE(controller->HasActiveAnimation());
EXPECT_EQ(0.5f, dummy.opacity());
EXPECT_TRUE(controller->GetAnimation(id, Animation::Opacity));
controller->GetAnimation(id, Animation::Opacity)->SetRunState(
- Animation::Paused, 0.5);
+ Animation::Paused, kInitialTickTime + 0.5);
- controller->Animate(1024);
+ controller->Animate(kInitialTickTime + 1024.0);
controller->UpdateState(true, events.get());
EXPECT_TRUE(controller->HasActiveAnimation());
EXPECT_EQ(0.5f, dummy.opacity());
EXPECT_TRUE(controller->GetAnimation(id, Animation::Opacity));
controller->GetAnimation(id, Animation::Opacity)->SetRunState(
- Animation::Running, 1024);
+ Animation::Running, kInitialTickTime + 1024);
- controller->Animate(1024.25);
+ controller->Animate(kInitialTickTime + 1024.25);
controller->UpdateState(true, events.get());
EXPECT_TRUE(controller->HasActiveAnimation());
EXPECT_EQ(0.75f, dummy.opacity());
- controller->Animate(1024.5);
+ controller->Animate(kInitialTickTime + 1024.5);
controller->UpdateState(true, events.get());
EXPECT_FALSE(controller->HasActiveAnimation());
EXPECT_EQ(1.f, dummy.opacity());
@@ -949,29 +1212,29 @@ TEST(LayerAnimationControllerTest, AbortAGroupedAnimation) {
2,
Animation::Opacity));
- controller->Animate(0.0);
+ controller->Animate(kInitialTickTime);
controller->UpdateState(true, events.get());
EXPECT_TRUE(controller->HasActiveAnimation());
EXPECT_EQ(0.f, dummy.opacity());
- controller->Animate(1.0);
+ controller->Animate(kInitialTickTime + 1.0);
controller->UpdateState(true, events.get());
EXPECT_TRUE(controller->HasActiveAnimation());
EXPECT_EQ(0.5f, dummy.opacity());
EXPECT_TRUE(controller->GetAnimation(id, Animation::Opacity));
controller->GetAnimation(id, Animation::Opacity)->SetRunState(
- Animation::Aborted, 1);
- controller->Animate(1.0);
+ Animation::Aborted, kInitialTickTime + 1.0);
+ controller->Animate(kInitialTickTime + 1.0);
controller->UpdateState(true, events.get());
EXPECT_TRUE(controller->HasActiveAnimation());
EXPECT_EQ(1.f, dummy.opacity());
- controller->Animate(2.0);
+ controller->Animate(kInitialTickTime + 2.0);
controller->UpdateState(true, events.get());
EXPECT_TRUE(!controller->HasActiveAnimation());
EXPECT_EQ(0.75f, dummy.opacity());
}
-TEST(LayerAnimationControllerTest, ForceSyncWhenSynchronizedStartTimeNeeded) {
+TEST(LayerAnimationControllerTest, PushUpdatesWhenSynchronizedStartTimeNeeded) {
FakeLayerAnimationValueObserver dummy_impl;
scoped_refptr<LayerAnimationController> controller_impl(
LayerAnimationController::Create(0));
@@ -990,15 +1253,13 @@ TEST(LayerAnimationControllerTest, ForceSyncWhenSynchronizedStartTimeNeeded) {
to_add->set_needs_synchronized_start_time(true);
controller->AddAnimation(to_add.Pass());
- controller->Animate(0.0);
+ controller->Animate(kInitialTickTime);
controller->UpdateState(true, events.get());
EXPECT_TRUE(controller->HasActiveAnimation());
Animation* active_animation = controller->GetAnimation(0, Animation::Opacity);
EXPECT_TRUE(active_animation);
EXPECT_TRUE(active_animation->needs_synchronized_start_time());
- controller->set_force_sync();
-
controller->PushAnimationUpdatesTo(controller_impl.get());
active_animation = controller_impl->GetAnimation(0, Animation::Opacity);
@@ -1021,7 +1282,7 @@ TEST(LayerAnimationControllerTest, SkipUpdateState) {
1,
Animation::Transform));
- controller->Animate(0.0);
+ controller->Animate(kInitialTickTime);
controller->UpdateState(true, events.get());
controller->AddAnimation(CreateAnimation(
@@ -1030,9 +1291,9 @@ TEST(LayerAnimationControllerTest, SkipUpdateState) {
Animation::Opacity));
// Animate but don't UpdateState.
- controller->Animate(1.0);
+ controller->Animate(kInitialTickTime + 1.0);
- controller->Animate(2.0);
+ controller->Animate(kInitialTickTime + 2.0);
events.reset(new AnimationEventsVector);
controller->UpdateState(true, events.get());
@@ -1044,7 +1305,7 @@ TEST(LayerAnimationControllerTest, SkipUpdateState) {
EXPECT_TRUE(controller->HasActiveAnimation());
EXPECT_EQ(0.f, dummy.opacity());
- controller->Animate(3.0);
+ controller->Animate(kInitialTickTime + 3.0);
controller->UpdateState(true, events.get());
// The float tranisition should now be done.
@@ -1070,7 +1331,7 @@ TEST(LayerAnimationControllerTest, InactiveObserverGetsTicked) {
// Without an observer, the animation shouldn't progress to the Starting
// state.
- controller->Animate(0.0);
+ controller->Animate(kInitialTickTime);
controller->UpdateState(true, events.get());
EXPECT_EQ(0u, events->size());
EXPECT_EQ(Animation::WaitingForTargetAvailability,
@@ -1081,7 +1342,7 @@ TEST(LayerAnimationControllerTest, InactiveObserverGetsTicked) {
// With only an inactive observer, the animation should progress to the
// Starting state and get ticked at its starting point, but should not
// progress to Running.
- controller->Animate(1.0);
+ controller->Animate(kInitialTickTime + 1.0);
controller->UpdateState(true, events.get());
EXPECT_EQ(0u, events->size());
EXPECT_EQ(Animation::Starting,
@@ -1090,7 +1351,7 @@ TEST(LayerAnimationControllerTest, InactiveObserverGetsTicked) {
// Even when already in the Starting state, the animation should stay
// there, and shouldn't be ticked past its starting point.
- controller->Animate(2.0);
+ controller->Animate(kInitialTickTime + 2.0);
controller->UpdateState(true, events.get());
EXPECT_EQ(0u, events->size());
EXPECT_EQ(Animation::Starting,
@@ -1101,7 +1362,7 @@ TEST(LayerAnimationControllerTest, InactiveObserverGetsTicked) {
// Now that an active observer has been added, the animation should still
// initially tick at its starting point, but should now progress to Running.
- controller->Animate(3.0);
+ controller->Animate(kInitialTickTime + 3.0);
controller->UpdateState(true, events.get());
EXPECT_EQ(1u, events->size());
EXPECT_EQ(Animation::Running,
@@ -1110,7 +1371,7 @@ TEST(LayerAnimationControllerTest, InactiveObserverGetsTicked) {
EXPECT_EQ(0.5f, dummy.opacity());
// The animation should now tick past its starting point.
- controller->Animate(3.5);
+ controller->Animate(kInitialTickTime + 3.5);
EXPECT_NE(0.5f, inactive_dummy.opacity());
EXPECT_NE(0.5f, dummy.opacity());
}
@@ -1154,16 +1415,16 @@ TEST(LayerAnimationControllerTest, AnimatedBounds) {
EXPECT_EQ(gfx::BoxF(1.f, 2.f, -4.f, 13.f, 19.f, 20.f).ToString(),
bounds.ToString());
- controller_impl->GetAnimation(1, Animation::Transform)->SetRunState(
- cc::Animation::Finished, 0.0);
+ controller_impl->GetAnimation(1, Animation::Transform)
+ ->SetRunState(Animation::Finished, 0.0);
// Only the unfinished animation should affect the animated bounds.
EXPECT_TRUE(controller_impl->AnimatedBoundsForBox(box, &bounds));
EXPECT_EQ(gfx::BoxF(1.f, 2.f, -4.f, 7.f, 16.f, 20.f).ToString(),
bounds.ToString());
- controller_impl->GetAnimation(2, Animation::Transform)->SetRunState(
- cc::Animation::Finished, 0.0);
+ controller_impl->GetAnimation(2, Animation::Transform)
+ ->SetRunState(Animation::Finished, 0.0);
// There are no longer any running animations.
EXPECT_TRUE(controller_impl->AnimatedBoundsForBox(box, &bounds));
@@ -1173,9 +1434,11 @@ TEST(LayerAnimationControllerTest, AnimatedBounds) {
scoped_ptr<KeyframedTransformAnimationCurve> curve3(
KeyframedTransformAnimationCurve::Create());
TransformOperations operations3;
+ gfx::Transform transform3;
+ transform3.Scale3d(1.0, 2.0, 3.0);
curve3->AddKeyframe(TransformKeyframe::Create(
0.0, operations3, scoped_ptr<TimingFunction>()));
- operations3.AppendSkew(1.0, 2.0);
+ operations3.AppendMatrix(transform3);
curve3->AddKeyframe(TransformKeyframe::Create(
1.0, operations3, scoped_ptr<TimingFunction>()));
animation = Animation::Create(
@@ -1184,5 +1447,242 @@ TEST(LayerAnimationControllerTest, AnimatedBounds) {
EXPECT_FALSE(controller_impl->AnimatedBoundsForBox(box, &bounds));
}
+// Tests that AbortAnimations aborts all animations targeting the specified
+// property.
+TEST(LayerAnimationControllerTest, AbortAnimations) {
+ FakeLayerAnimationValueObserver dummy;
+ scoped_refptr<LayerAnimationController> controller(
+ LayerAnimationController::Create(0));
+ controller->AddValueObserver(&dummy);
+
+ // Start with several animations, and allow some of them to reach the finished
+ // state.
+ controller->AddAnimation(CreateAnimation(
+ scoped_ptr<AnimationCurve>(new FakeTransformTransition(1.0)).Pass(),
+ 1,
+ Animation::Transform));
+ controller->AddAnimation(CreateAnimation(
+ scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(),
+ 2,
+ Animation::Opacity));
+ controller->AddAnimation(CreateAnimation(
+ scoped_ptr<AnimationCurve>(new FakeTransformTransition(1.0)).Pass(),
+ 3,
+ Animation::Transform));
+ controller->AddAnimation(CreateAnimation(
+ scoped_ptr<AnimationCurve>(new FakeTransformTransition(2.0)).Pass(),
+ 4,
+ Animation::Transform));
+ controller->AddAnimation(CreateAnimation(
+ scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(),
+ 5,
+ Animation::Opacity));
+
+ controller->Animate(kInitialTickTime);
+ controller->UpdateState(true, NULL);
+ controller->Animate(kInitialTickTime + 1.0);
+ controller->UpdateState(true, NULL);
+
+ EXPECT_EQ(Animation::Finished,
+ controller->GetAnimation(1, Animation::Transform)->run_state());
+ EXPECT_EQ(Animation::Finished,
+ controller->GetAnimation(2, Animation::Opacity)->run_state());
+ EXPECT_EQ(Animation::Running,
+ controller->GetAnimation(3, Animation::Transform)->run_state());
+ EXPECT_EQ(Animation::WaitingForTargetAvailability,
+ controller->GetAnimation(4, Animation::Transform)->run_state());
+ EXPECT_EQ(Animation::Running,
+ controller->GetAnimation(5, Animation::Opacity)->run_state());
+
+ controller->AbortAnimations(Animation::Transform);
+
+ // Only un-finished Transform animations should have been aborted.
+ EXPECT_EQ(Animation::Finished,
+ controller->GetAnimation(1, Animation::Transform)->run_state());
+ EXPECT_EQ(Animation::Finished,
+ controller->GetAnimation(2, Animation::Opacity)->run_state());
+ EXPECT_EQ(Animation::Aborted,
+ controller->GetAnimation(3, Animation::Transform)->run_state());
+ EXPECT_EQ(Animation::Aborted,
+ controller->GetAnimation(4, Animation::Transform)->run_state());
+ EXPECT_EQ(Animation::Running,
+ controller->GetAnimation(5, Animation::Opacity)->run_state());
+}
+
+// An animation aborted on the main thread should get deleted on both threads.
+TEST(LayerAnimationControllerTest, MainThreadAbortedAnimationGetsDeleted) {
+ FakeLayerAnimationValueObserver dummy_impl;
+ scoped_refptr<LayerAnimationController> controller_impl(
+ LayerAnimationController::Create(0));
+ controller_impl->AddValueObserver(&dummy_impl);
+ FakeLayerAnimationValueObserver dummy;
+ scoped_refptr<LayerAnimationController> controller(
+ LayerAnimationController::Create(0));
+ controller->AddValueObserver(&dummy);
+
+ AddOpacityTransitionToController(controller.get(), 1.0, 0.f, 1.f, false);
+ int group_id = controller->GetAnimation(Animation::Opacity)->group();
+
+ controller->PushAnimationUpdatesTo(controller_impl.get());
+ EXPECT_TRUE(controller_impl->GetAnimation(group_id, Animation::Opacity));
+
+ controller->AbortAnimations(Animation::Opacity);
+ EXPECT_EQ(Animation::Aborted,
+ controller->GetAnimation(Animation::Opacity)->run_state());
+ EXPECT_FALSE(dummy.animation_waiting_for_deletion());
+ EXPECT_FALSE(dummy_impl.animation_waiting_for_deletion());
+
+ controller->Animate(kInitialTickTime);
+ controller->UpdateState(true, NULL);
+ EXPECT_TRUE(dummy.animation_waiting_for_deletion());
+ EXPECT_EQ(Animation::WaitingForDeletion,
+ controller->GetAnimation(Animation::Opacity)->run_state());
+
+ controller->PushAnimationUpdatesTo(controller_impl.get());
+ EXPECT_FALSE(controller->GetAnimation(group_id, Animation::Opacity));
+ EXPECT_FALSE(controller_impl->GetAnimation(group_id, Animation::Opacity));
+}
+
+// An animation aborted on the impl thread should get deleted on both threads.
+TEST(LayerAnimationControllerTest, ImplThreadAbortedAnimationGetsDeleted) {
+ FakeLayerAnimationValueObserver dummy_impl;
+ scoped_refptr<LayerAnimationController> controller_impl(
+ LayerAnimationController::Create(0));
+ controller_impl->AddValueObserver(&dummy_impl);
+ FakeLayerAnimationValueObserver dummy;
+ scoped_refptr<LayerAnimationController> controller(
+ LayerAnimationController::Create(0));
+ controller->AddValueObserver(&dummy);
+
+ AddOpacityTransitionToController(controller.get(), 1.0, 0.f, 1.f, false);
+ int group_id = controller->GetAnimation(Animation::Opacity)->group();
+
+ controller->PushAnimationUpdatesTo(controller_impl.get());
+ EXPECT_TRUE(controller_impl->GetAnimation(group_id, Animation::Opacity));
+
+ controller_impl->AbortAnimations(Animation::Opacity);
+ EXPECT_EQ(Animation::Aborted,
+ controller_impl->GetAnimation(Animation::Opacity)->run_state());
+ EXPECT_FALSE(dummy.animation_waiting_for_deletion());
+ EXPECT_FALSE(dummy_impl.animation_waiting_for_deletion());
+
+ AnimationEventsVector events;
+ controller_impl->Animate(kInitialTickTime);
+ controller_impl->UpdateState(true, &events);
+ EXPECT_TRUE(dummy_impl.animation_waiting_for_deletion());
+ EXPECT_EQ(1u, events.size());
+ EXPECT_EQ(AnimationEvent::Aborted, events[0].type);
+ EXPECT_EQ(Animation::WaitingForDeletion,
+ controller_impl->GetAnimation(Animation::Opacity)->run_state());
+
+ controller->NotifyAnimationAborted(events[0]);
+ EXPECT_EQ(Animation::Aborted,
+ controller->GetAnimation(Animation::Opacity)->run_state());
+
+ controller->Animate(kInitialTickTime + 0.5);
+ controller->UpdateState(true, NULL);
+ EXPECT_TRUE(dummy.animation_waiting_for_deletion());
+ EXPECT_EQ(Animation::WaitingForDeletion,
+ controller->GetAnimation(Animation::Opacity)->run_state());
+
+ controller->PushAnimationUpdatesTo(controller_impl.get());
+ EXPECT_FALSE(controller->GetAnimation(group_id, Animation::Opacity));
+ EXPECT_FALSE(controller_impl->GetAnimation(group_id, Animation::Opacity));
+}
+
+// Ensure that we only generate Finished events for animations in a group
+// once all animations in that group are finished.
+TEST(LayerAnimationControllerTest, FinishedEventsForGroup) {
+ scoped_ptr<AnimationEventsVector> events(
+ make_scoped_ptr(new AnimationEventsVector));
+ FakeLayerAnimationValueObserver dummy_impl;
+ scoped_refptr<LayerAnimationController> controller_impl(
+ LayerAnimationController::Create(0));
+ controller_impl->AddValueObserver(&dummy_impl);
+
+ // Add two animations with the same group id but different durations.
+ controller_impl->AddAnimation(CreateAnimation(
+ scoped_ptr<AnimationCurve>(new FakeTransformTransition(2.0)).Pass(),
+ 1,
+ Animation::Transform));
+ controller_impl->AddAnimation(CreateAnimation(
+ scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(),
+ 1,
+ Animation::Opacity));
+
+ controller_impl->Animate(kInitialTickTime);
+ controller_impl->UpdateState(true, events.get());
+
+ // Both animations should have started.
+ EXPECT_EQ(2u, events->size());
+ EXPECT_EQ(AnimationEvent::Started, (*events)[0].type);
+ EXPECT_EQ(AnimationEvent::Started, (*events)[1].type);
+
+ events.reset(new AnimationEventsVector);
+ controller_impl->Animate(kInitialTickTime + 1.0);
+ controller_impl->UpdateState(true, events.get());
+
+ // The opacity animation should be finished, but should not have generated
+ // a Finished event yet.
+ EXPECT_EQ(0u, events->size());
+ EXPECT_EQ(Animation::Finished,
+ controller_impl->GetAnimation(1, Animation::Opacity)->run_state());
+ EXPECT_EQ(Animation::Running,
+ controller_impl->GetAnimation(1,
+ Animation::Transform)->run_state());
+
+ controller_impl->Animate(kInitialTickTime + 2.0);
+ controller_impl->UpdateState(true, events.get());
+
+ // Both animations should have generated Finished events.
+ EXPECT_EQ(2u, events->size());
+ EXPECT_EQ(AnimationEvent::Finished, (*events)[0].type);
+ EXPECT_EQ(AnimationEvent::Finished, (*events)[1].type);
+}
+
+// Ensure that when a group has a mix of aborted and finished animations,
+// we generate a Finished event for the finished animation and an Aborted
+// event for the aborted animation.
+TEST(LayerAnimationControllerTest, FinishedAndAbortedEventsForGroup) {
+ scoped_ptr<AnimationEventsVector> events(
+ make_scoped_ptr(new AnimationEventsVector));
+ FakeLayerAnimationValueObserver dummy_impl;
+ scoped_refptr<LayerAnimationController> controller_impl(
+ LayerAnimationController::Create(0));
+ controller_impl->AddValueObserver(&dummy_impl);
+
+ // Add two animations with the same group id.
+ controller_impl->AddAnimation(CreateAnimation(
+ scoped_ptr<AnimationCurve>(new FakeTransformTransition(1.0)).Pass(),
+ 1,
+ Animation::Transform));
+ controller_impl->AddAnimation(CreateAnimation(
+ scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(),
+ 1,
+ Animation::Opacity));
+
+ controller_impl->Animate(kInitialTickTime);
+ controller_impl->UpdateState(true, events.get());
+
+ // Both animations should have started.
+ EXPECT_EQ(2u, events->size());
+ EXPECT_EQ(AnimationEvent::Started, (*events)[0].type);
+ EXPECT_EQ(AnimationEvent::Started, (*events)[1].type);
+
+ controller_impl->AbortAnimations(Animation::Opacity);
+
+ events.reset(new AnimationEventsVector);
+ controller_impl->Animate(kInitialTickTime + 1.0);
+ controller_impl->UpdateState(true, events.get());
+
+ // We should have exactly 2 events: a Finished event for the tranform
+ // animation, and an Aborted event for the opacity animation.
+ EXPECT_EQ(2u, events->size());
+ EXPECT_EQ(AnimationEvent::Finished, (*events)[0].type);
+ EXPECT_EQ(Animation::Transform, (*events)[0].target_property);
+ EXPECT_EQ(AnimationEvent::Aborted, (*events)[1].type);
+ EXPECT_EQ(Animation::Opacity, (*events)[1].target_property);
+}
+
} // namespace
} // namespace cc
diff --git a/chromium/cc/animation/layer_animation_value_observer.h b/chromium/cc/animation/layer_animation_value_observer.h
index ca3cafaf129..d21ade80f48 100644
--- a/chromium/cc/animation/layer_animation_value_observer.h
+++ b/chromium/cc/animation/layer_animation_value_observer.h
@@ -13,8 +13,11 @@ class CC_EXPORT LayerAnimationValueObserver {
public:
virtual ~LayerAnimationValueObserver() {}
+ virtual void OnFilterAnimated(const FilterOperations& filters) = 0;
virtual void OnOpacityAnimated(float opacity) = 0;
virtual void OnTransformAnimated(const gfx::Transform& transform) = 0;
+ virtual void OnScrollOffsetAnimated(gfx::Vector2dF scroll_offset) = 0;
+ virtual void OnAnimationWaitingForDeletion() = 0;
virtual bool IsActive() const = 0;
};
diff --git a/chromium/cc/animation/layer_animation_value_provider.h b/chromium/cc/animation/layer_animation_value_provider.h
new file mode 100644
index 00000000000..c81496883ed
--- /dev/null
+++ b/chromium/cc/animation/layer_animation_value_provider.h
@@ -0,0 +1,25 @@
+// 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_ANIMATION_LAYER_ANIMATION_VALUE_PROVIDER_H_
+#define CC_ANIMATION_LAYER_ANIMATION_VALUE_PROVIDER_H_
+
+#include "cc/base/cc_export.h"
+#include "ui/gfx/vector2d_f.h"
+
+namespace cc {
+
+// A LayerAnimationValueProvider is used for determining the starting value
+// for animations that start at their 'current' value rather than at a
+// pre-specified value.
+class CC_EXPORT LayerAnimationValueProvider {
+ public:
+ virtual ~LayerAnimationValueProvider() {}
+
+ virtual gfx::Vector2dF ScrollOffsetForAnimation() const = 0;
+};
+
+} // namespace cc
+
+#endif // CC_ANIMATION_LAYER_ANIMATION_VALUE_PROVIDER_H_
diff --git a/chromium/cc/animation/scroll_offset_animation_curve.cc b/chromium/cc/animation/scroll_offset_animation_curve.cc
new file mode 100644
index 00000000000..362aa1ed548
--- /dev/null
+++ b/chromium/cc/animation/scroll_offset_animation_curve.cc
@@ -0,0 +1,80 @@
+// 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/animation/scroll_offset_animation_curve.h"
+
+#include <algorithm>
+#include <cmath>
+
+#include "base/logging.h"
+#include "cc/animation/timing_function.h"
+#include "ui/gfx/animation/tween.h"
+
+const double kDurationDivisor = 60.0;
+
+namespace cc {
+
+scoped_ptr<ScrollOffsetAnimationCurve> ScrollOffsetAnimationCurve::Create(
+ gfx::Vector2dF target_value,
+ scoped_ptr<TimingFunction> timing_function) {
+ return make_scoped_ptr(
+ new ScrollOffsetAnimationCurve(target_value, timing_function.Pass()));
+}
+
+ScrollOffsetAnimationCurve::ScrollOffsetAnimationCurve(
+ gfx::Vector2dF target_value,
+ scoped_ptr<TimingFunction> timing_function)
+ : target_value_(target_value),
+ duration_(0.0),
+ timing_function_(timing_function.Pass()) {}
+
+ScrollOffsetAnimationCurve::~ScrollOffsetAnimationCurve() {}
+
+void ScrollOffsetAnimationCurve::SetInitialValue(gfx::Vector2dF initial_value) {
+ initial_value_ = initial_value;
+
+ // The duration of a scroll animation depends on the size of the scroll.
+ // The exact relationship between the size and the duration isn't specified
+ // by the CSSOM View smooth scroll spec and is instead left up to user agents
+ // to decide. The calculation performed here will very likely be further
+ // tweaked before the smooth scroll API ships.
+ float delta_x = std::abs(target_value_.x() - initial_value_.x());
+ float delta_y = std::abs(target_value_.y() - initial_value_.y());
+ float max_delta = std::max(delta_x, delta_y);
+ duration_ = std::sqrt(max_delta)/kDurationDivisor;
+}
+
+gfx::Vector2dF ScrollOffsetAnimationCurve::GetValue(double t) const {
+ if (t <= 0)
+ return initial_value_;
+
+ if (t >= duration_)
+ return target_value_;
+
+ double progress = timing_function_->GetValue(t / duration_);
+ return gfx::Vector2dF(gfx::Tween::FloatValueBetween(
+ progress, initial_value_.x(), target_value_.x()),
+ gfx::Tween::FloatValueBetween(
+ progress, initial_value_.y(), target_value_.y()));
+}
+
+double ScrollOffsetAnimationCurve::Duration() const {
+ return duration_;
+}
+
+AnimationCurve::CurveType ScrollOffsetAnimationCurve::Type() const {
+ return ScrollOffset;
+}
+
+scoped_ptr<AnimationCurve> ScrollOffsetAnimationCurve::Clone() const {
+ scoped_ptr<TimingFunction> timing_function(
+ static_cast<TimingFunction*>(timing_function_->Clone().release()));
+ scoped_ptr<ScrollOffsetAnimationCurve> curve_clone =
+ Create(target_value_, timing_function.Pass());
+ curve_clone->initial_value_ = initial_value_;
+ curve_clone->duration_ = duration_;
+ return curve_clone.PassAs<AnimationCurve>();
+}
+
+} // namespace cc
diff --git a/chromium/cc/animation/scroll_offset_animation_curve.h b/chromium/cc/animation/scroll_offset_animation_curve.h
new file mode 100644
index 00000000000..ba4661518e8
--- /dev/null
+++ b/chromium/cc/animation/scroll_offset_animation_curve.h
@@ -0,0 +1,47 @@
+// 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_ANIMATION_SCROLL_OFFSET_ANIMATION_CURVE_H_
+#define CC_ANIMATION_SCROLL_OFFSET_ANIMATION_CURVE_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "cc/animation/animation_curve.h"
+#include "cc/base/cc_export.h"
+
+namespace cc {
+
+class TimingFunction;
+
+class CC_EXPORT ScrollOffsetAnimationCurve : public AnimationCurve {
+ public:
+ static scoped_ptr<ScrollOffsetAnimationCurve> Create(
+ gfx::Vector2dF target_value,
+ scoped_ptr<TimingFunction> timing_function);
+
+ virtual ~ScrollOffsetAnimationCurve();
+
+ void SetInitialValue(gfx::Vector2dF initial_value);
+ gfx::Vector2dF GetValue(double t) const;
+
+ // AnimationCurve implementation
+ virtual double Duration() const OVERRIDE;
+ virtual CurveType Type() const OVERRIDE;
+ virtual scoped_ptr<AnimationCurve> Clone() const OVERRIDE;
+
+ private:
+ ScrollOffsetAnimationCurve(gfx::Vector2dF target_value,
+ scoped_ptr <TimingFunction> timing_function);
+
+ gfx::Vector2dF initial_value_;
+ gfx::Vector2dF target_value_;
+ double duration_;
+
+ scoped_ptr<TimingFunction> timing_function_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScrollOffsetAnimationCurve);
+};
+
+} // namespace cc
+
+#endif // CC_ANIMATION_SCROLL_OFFSET_ANIMATION_CURVE_H_
diff --git a/chromium/cc/animation/scroll_offset_animation_curve_unittest.cc b/chromium/cc/animation/scroll_offset_animation_curve_unittest.cc
new file mode 100644
index 00000000000..63445d965dc
--- /dev/null
+++ b/chromium/cc/animation/scroll_offset_animation_curve_unittest.cc
@@ -0,0 +1,123 @@
+// 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/animation/scroll_offset_animation_curve.h"
+
+#include "cc/animation/timing_function.h"
+#include "cc/test/geometry_test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace cc {
+namespace {
+
+TEST(ScrollOffsetAnimationCurveTest, Duration) {
+ gfx::Vector2dF target_value(100.f, 200.f);
+ scoped_ptr<ScrollOffsetAnimationCurve> curve(
+ ScrollOffsetAnimationCurve::Create(
+ target_value,
+ EaseInOutTimingFunction::Create().Pass()));
+
+ curve->SetInitialValue(target_value);
+ EXPECT_DOUBLE_EQ(0.0, curve->Duration());
+
+ // x decreases, y stays the same.
+ curve->SetInitialValue(gfx::Vector2dF(136.f, 200.f));
+ EXPECT_DOUBLE_EQ(0.1, curve->Duration());
+
+ // x increases, y stays the same.
+ curve->SetInitialValue(gfx::Vector2dF(19.f, 200.f));
+ EXPECT_DOUBLE_EQ(0.15, curve->Duration());
+
+ // x stays the same, y decreases.
+ curve->SetInitialValue(gfx::Vector2dF(100.f, 344.f));
+ EXPECT_DOUBLE_EQ(0.2, curve->Duration());
+
+ // x stays the same, y increases.
+ curve->SetInitialValue(gfx::Vector2dF(100.f, 191.f));
+ EXPECT_DOUBLE_EQ(0.05, curve->Duration());
+
+ // x decreases, y decreases.
+ curve->SetInitialValue(gfx::Vector2dF(32500.f, 500.f));
+ EXPECT_DOUBLE_EQ(3.0, curve->Duration());
+
+ // x decreases, y increases.
+ curve->SetInitialValue(gfx::Vector2dF(150.f, 119.f));
+ EXPECT_DOUBLE_EQ(0.15, curve->Duration());
+
+ // x increases, y decreases.
+ curve->SetInitialValue(gfx::Vector2dF(0.f, 14600.f));
+ EXPECT_DOUBLE_EQ(2.0, curve->Duration());
+
+ // x increases, y increases.
+ curve->SetInitialValue(gfx::Vector2dF(95.f, 191.f));
+ EXPECT_DOUBLE_EQ(0.05, curve->Duration());
+}
+
+TEST(ScrollOffsetAnimationCurveTest, GetValue) {
+ gfx::Vector2dF initial_value(2.f, 40.f);
+ gfx::Vector2dF target_value(10.f, 20.f);
+ scoped_ptr<ScrollOffsetAnimationCurve> curve(
+ ScrollOffsetAnimationCurve::Create(
+ target_value,
+ EaseInOutTimingFunction::Create().Pass()));
+ curve->SetInitialValue(initial_value);
+
+ double duration = curve->Duration();
+ EXPECT_GT(curve->Duration(), 0);
+ EXPECT_LT(curve->Duration(), 0.1);
+
+ EXPECT_EQ(AnimationCurve::ScrollOffset, curve->Type());
+ EXPECT_EQ(duration, curve->Duration());
+
+ EXPECT_VECTOR2DF_EQ(initial_value, curve->GetValue(-1.0));
+ EXPECT_VECTOR2DF_EQ(initial_value, curve->GetValue(0.0));
+ EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(6.f, 30.f), curve->GetValue(duration/2.0));
+ EXPECT_VECTOR2DF_EQ(target_value, curve->GetValue(duration));
+ EXPECT_VECTOR2DF_EQ(target_value, curve->GetValue(duration+1.0));
+
+ // Verify that GetValue takes the timing function into account.
+ gfx::Vector2dF value = curve->GetValue(duration/4.0);
+ EXPECT_NEAR(3.0333f, value.x(), 0.00015f);
+ EXPECT_NEAR(37.4168f, value.y(), 0.00015f);
+}
+
+// Verify that a clone behaves exactly like the original.
+TEST(ScrollOffsetAnimationCurveTest, Clone) {
+ gfx::Vector2dF initial_value(2.f, 40.f);
+ gfx::Vector2dF target_value(10.f, 20.f);
+ scoped_ptr<ScrollOffsetAnimationCurve> curve(
+ ScrollOffsetAnimationCurve::Create(
+ target_value,
+ EaseInOutTimingFunction::Create().Pass()));
+ curve->SetInitialValue(initial_value);
+ double duration = curve->Duration();
+
+ scoped_ptr<AnimationCurve> clone(curve->Clone().Pass());
+
+ EXPECT_EQ(AnimationCurve::ScrollOffset, clone->Type());
+ EXPECT_EQ(duration, clone->Duration());
+
+ EXPECT_VECTOR2DF_EQ(initial_value,
+ clone->ToScrollOffsetAnimationCurve()->GetValue(-1.0));
+ EXPECT_VECTOR2DF_EQ(initial_value,
+ clone->ToScrollOffsetAnimationCurve()->GetValue(0.0));
+ EXPECT_VECTOR2DF_EQ(
+ gfx::Vector2dF(6.f, 30.f),
+ clone->ToScrollOffsetAnimationCurve()->GetValue(duration / 2.0));
+ EXPECT_VECTOR2DF_EQ(
+ target_value,
+ clone->ToScrollOffsetAnimationCurve()->GetValue(duration));
+ EXPECT_VECTOR2DF_EQ(
+ target_value,
+ clone->ToScrollOffsetAnimationCurve()->GetValue(duration + 1.0));
+
+ // Verify that the timing function was cloned correctly.
+ gfx::Vector2dF value =
+ clone->ToScrollOffsetAnimationCurve()->GetValue(duration / 4.0);
+ EXPECT_NEAR(3.0333f, value.x(), 0.00015f);
+ EXPECT_NEAR(37.4168f, value.y(), 0.00015f);
+}
+
+} // namespace
+} // namespace cc
diff --git a/chromium/cc/animation/scrollbar_animation_controller.h b/chromium/cc/animation/scrollbar_animation_controller.h
index d3667f10bca..ecef4fb2d97 100644
--- a/chromium/cc/animation/scrollbar_animation_controller.h
+++ b/chromium/cc/animation/scrollbar_animation_controller.h
@@ -24,9 +24,11 @@ class CC_EXPORT ScrollbarAnimationController {
virtual bool Animate(base::TimeTicks now) = 0;
virtual void DidScrollGestureBegin() = 0;
virtual void DidScrollGestureEnd(base::TimeTicks now) = 0;
+ virtual void DidMouseMoveOffScrollbar(base::TimeTicks now) = 0;
// Returns true if we should start an animation.
virtual bool DidScrollUpdate(base::TimeTicks now) = 0;
+ virtual bool DidMouseMoveNear(base::TimeTicks now, float distance) = 0;
};
} // namespace cc
diff --git a/chromium/cc/animation/scrollbar_animation_controller_linear_fade.cc b/chromium/cc/animation/scrollbar_animation_controller_linear_fade.cc
index eafcca08d51..863959b84c2 100644
--- a/chromium/cc/animation/scrollbar_animation_controller_linear_fade.cc
+++ b/chromium/cc/animation/scrollbar_animation_controller_linear_fade.cc
@@ -65,6 +65,11 @@ void ScrollbarAnimationControllerLinearFade::DidScrollGestureEnd(
scroll_gesture_in_progress_ = false;
}
+void ScrollbarAnimationControllerLinearFade::DidMouseMoveOffScrollbar(
+ base::TimeTicks now) {
+ // Ignore mouse move events.
+}
+
bool ScrollbarAnimationControllerLinearFade::DidScrollUpdate(
base::TimeTicks now) {
ApplyOpacityToScrollbars(1.0f);
@@ -80,6 +85,12 @@ bool ScrollbarAnimationControllerLinearFade::DidScrollUpdate(
return true;
}
+bool ScrollbarAnimationControllerLinearFade::DidMouseMoveNear(
+ base::TimeTicks now, float distance) {
+ // Ignore mouse move events.
+ return false;
+}
+
float ScrollbarAnimationControllerLinearFade::OpacityAtTime(
base::TimeTicks now) {
if (scroll_gesture_has_scrolled_)
diff --git a/chromium/cc/animation/scrollbar_animation_controller_linear_fade.h b/chromium/cc/animation/scrollbar_animation_controller_linear_fade.h
index eca4c4f86f0..85cdada5156 100644
--- a/chromium/cc/animation/scrollbar_animation_controller_linear_fade.h
+++ b/chromium/cc/animation/scrollbar_animation_controller_linear_fade.h
@@ -29,7 +29,9 @@ class CC_EXPORT ScrollbarAnimationControllerLinearFade
virtual bool Animate(base::TimeTicks now) OVERRIDE;
virtual void DidScrollGestureBegin() OVERRIDE;
virtual void DidScrollGestureEnd(base::TimeTicks now) OVERRIDE;
+ virtual void DidMouseMoveOffScrollbar(base::TimeTicks now) OVERRIDE;
virtual bool DidScrollUpdate(base::TimeTicks now) OVERRIDE;
+ virtual bool DidMouseMoveNear(base::TimeTicks now, float distance) OVERRIDE;
protected:
ScrollbarAnimationControllerLinearFade(LayerImpl* scroll_layer,
diff --git a/chromium/cc/animation/scrollbar_animation_controller_thinning.cc b/chromium/cc/animation/scrollbar_animation_controller_thinning.cc
index fcacfaab4a3..3de75989d0e 100644
--- a/chromium/cc/animation/scrollbar_animation_controller_thinning.cc
+++ b/chromium/cc/animation/scrollbar_animation_controller_thinning.cc
@@ -10,14 +10,22 @@
#include "cc/layers/layer_impl.h"
#include "cc/layers/scrollbar_layer_impl_base.h"
+namespace {
+const float kIdleThicknessScale = 0.4f;
+const float kIdleOpacity = 0.7f;
+const float kDefaultMouseMoveDistanceToTriggerAnimation = 25.f;
+const int kDefaultAnimationDelay = 500;
+const int kDefaultAnimationDuration = 300;
+}
+
namespace cc {
scoped_ptr<ScrollbarAnimationControllerThinning>
ScrollbarAnimationControllerThinning::Create(LayerImpl* scroll_layer) {
return make_scoped_ptr(new ScrollbarAnimationControllerThinning(
scroll_layer,
- base::TimeDelta::FromMilliseconds(500),
- base::TimeDelta::FromMilliseconds(300)));
+ base::TimeDelta::FromMilliseconds(kDefaultAnimationDelay),
+ base::TimeDelta::FromMilliseconds(kDefaultAnimationDuration)));
}
scoped_ptr<ScrollbarAnimationControllerThinning>
@@ -33,9 +41,17 @@ ScrollbarAnimationControllerThinning::ScrollbarAnimationControllerThinning(
base::TimeDelta animation_duration)
: ScrollbarAnimationController(),
scroll_layer_(scroll_layer),
- scroll_gesture_in_progress_(false),
+ mouse_is_over_scrollbar_(false),
+ mouse_is_near_scrollbar_(false),
+ thickness_change_(NONE),
+ opacity_change_(NONE),
+ should_delay_animation_(false),
animation_delay_(animation_delay),
- animation_duration_(animation_duration) {}
+ animation_duration_(animation_duration),
+ mouse_move_distance_to_trigger_animation_(
+ kDefaultMouseMoveDistanceToTriggerAnimation) {
+ ApplyOpacityAndThumbThicknessScale(kIdleOpacity, kIdleThicknessScale);
+}
ScrollbarAnimationControllerThinning::~ScrollbarAnimationControllerThinning() {
}
@@ -46,6 +62,8 @@ bool ScrollbarAnimationControllerThinning::IsAnimating() const {
base::TimeDelta ScrollbarAnimationControllerThinning::DelayBeforeStart(
base::TimeTicks now) const {
+ if (!should_delay_animation_)
+ return base::TimeDelta();
if (now > last_awaken_time_ + animation_delay_)
return base::TimeDelta();
return animation_delay_ - (now - last_awaken_time_);
@@ -57,58 +75,107 @@ bool ScrollbarAnimationControllerThinning::Animate(base::TimeTicks now) {
float thumb_thickness_scale = ThumbThicknessScaleAtAnimationProgress(
progress);
ApplyOpacityAndThumbThicknessScale(opacity, thumb_thickness_scale);
- if (progress == 1.f)
+ if (progress == 1.f) {
+ opacity_change_ = NONE;
+ thickness_change_ = NONE;
last_awaken_time_ = base::TimeTicks();
+ }
return IsAnimating() && DelayBeforeStart(now) == base::TimeDelta();
}
void ScrollbarAnimationControllerThinning::DidScrollGestureBegin() {
- ApplyOpacityAndThumbThicknessScale(1, 1);
- last_awaken_time_ = base::TimeTicks();
- scroll_gesture_in_progress_ = true;
}
void ScrollbarAnimationControllerThinning::DidScrollGestureEnd(
base::TimeTicks now) {
+}
+
+void ScrollbarAnimationControllerThinning::DidMouseMoveOffScrollbar(
+ base::TimeTicks now) {
+ mouse_is_over_scrollbar_ = false;
+ mouse_is_near_scrollbar_ = false;
last_awaken_time_ = now;
- scroll_gesture_in_progress_ = false;
+ should_delay_animation_ = false;
+ opacity_change_ = DECREASE;
+ thickness_change_ = DECREASE;
}
bool ScrollbarAnimationControllerThinning::DidScrollUpdate(
base::TimeTicks now) {
- ApplyOpacityAndThumbThicknessScale(1, 1);
+ ApplyOpacityAndThumbThicknessScale(
+ 1, mouse_is_near_scrollbar_ ? 1.f : kIdleThicknessScale);
last_awaken_time_ = now;
+ should_delay_animation_ = true;
+ if (!mouse_is_over_scrollbar_)
+ opacity_change_ = DECREASE;
+ return true;
+}
+
+bool ScrollbarAnimationControllerThinning::DidMouseMoveNear(
+ base::TimeTicks now, float distance) {
+ bool mouse_is_over_scrollbar = distance == 0.0;
+ bool mouse_is_near_scrollbar =
+ distance < mouse_move_distance_to_trigger_animation_;
+
+ if (mouse_is_over_scrollbar == mouse_is_over_scrollbar_ &&
+ mouse_is_near_scrollbar == mouse_is_near_scrollbar_)
+ return false;
+
+ if (mouse_is_over_scrollbar_ != mouse_is_over_scrollbar) {
+ mouse_is_over_scrollbar_ = mouse_is_over_scrollbar;
+ opacity_change_ = mouse_is_over_scrollbar_ ? INCREASE : DECREASE;
+ }
+
+ if (mouse_is_near_scrollbar_ != mouse_is_near_scrollbar) {
+ mouse_is_near_scrollbar_ = mouse_is_near_scrollbar;
+ thickness_change_ = mouse_is_near_scrollbar_ ? INCREASE : DECREASE;
+ }
+
+ last_awaken_time_ = now;
+ should_delay_animation_ = false;
return true;
}
float ScrollbarAnimationControllerThinning::AnimationProgressAtTime(
base::TimeTicks now) {
- if (scroll_gesture_in_progress_)
- return 0;
-
if (last_awaken_time_.is_null())
return 1;
base::TimeDelta delta = now - last_awaken_time_;
- float progress = (delta - animation_delay_).InSecondsF() /
- animation_duration_.InSecondsF();
+ if (should_delay_animation_)
+ delta -= animation_delay_;
+ float progress = delta.InSecondsF() / animation_duration_.InSecondsF();
return std::max(std::min(progress, 1.f), 0.f);
}
float ScrollbarAnimationControllerThinning::OpacityAtAnimationProgress(
float progress) {
- const float kIdleOpacity = 0.7f;
-
- return ((1 - kIdleOpacity) * (1.f - progress)) + kIdleOpacity;
+ if (opacity_change_ == NONE)
+ return mouse_is_over_scrollbar_ ? 1.f : kIdleOpacity;
+ float factor = opacity_change_ == INCREASE ? progress : (1.f - progress);
+ float ret = ((1.f - kIdleOpacity) * factor) + kIdleOpacity;
+ return ret;
}
float
ScrollbarAnimationControllerThinning::ThumbThicknessScaleAtAnimationProgress(
float progress) {
- const float kIdleThicknessScale = 0.4f;
+ if (thickness_change_ == NONE)
+ return mouse_is_near_scrollbar_ ? 1.f : kIdleThicknessScale;
+ float factor = thickness_change_ == INCREASE ? progress : (1.f - progress);
+ return ((1.f - kIdleThicknessScale) * factor) + kIdleThicknessScale;
+}
- return ((1 - kIdleThicknessScale) * (1.f - progress)) + kIdleThicknessScale;
+float ScrollbarAnimationControllerThinning::AdjustScale(
+ float new_value,
+ float current_value,
+ AnimationChange animation_change) {
+ if (animation_change == INCREASE && current_value > new_value)
+ return current_value;
+ if (animation_change == DECREASE && current_value < new_value)
+ return current_value;
+ return new_value;
}
void ScrollbarAnimationControllerThinning::ApplyOpacityAndThumbThicknessScale(
@@ -116,16 +183,25 @@ void ScrollbarAnimationControllerThinning::ApplyOpacityAndThumbThicknessScale(
ScrollbarLayerImplBase* horizontal_scrollbar =
scroll_layer_->horizontal_scrollbar_layer();
if (horizontal_scrollbar) {
- horizontal_scrollbar->SetOpacity(opacity);
- horizontal_scrollbar->set_thumb_thickness_scale_factor(
- thumb_thickness_scale);
+ horizontal_scrollbar->SetOpacity(
+ AdjustScale(opacity, horizontal_scrollbar->opacity(), opacity_change_));
+ horizontal_scrollbar->SetThumbThicknessScaleFactor(
+ AdjustScale(
+ thumb_thickness_scale,
+ horizontal_scrollbar->thumb_thickness_scale_factor(),
+ thickness_change_));
}
ScrollbarLayerImplBase* vertical_scrollbar =
scroll_layer_->vertical_scrollbar_layer();
if (vertical_scrollbar) {
- vertical_scrollbar->SetOpacity(opacity);
- vertical_scrollbar->set_thumb_thickness_scale_factor(thumb_thickness_scale);
+ vertical_scrollbar->SetOpacity(
+ AdjustScale(opacity, vertical_scrollbar->opacity(), opacity_change_));
+ vertical_scrollbar->SetThumbThicknessScaleFactor(
+ AdjustScale(
+ thumb_thickness_scale,
+ vertical_scrollbar->thumb_thickness_scale_factor(),
+ thickness_change_));
}
}
diff --git a/chromium/cc/animation/scrollbar_animation_controller_thinning.h b/chromium/cc/animation/scrollbar_animation_controller_thinning.h
index 0211479ef9a..07b4515ec31 100644
--- a/chromium/cc/animation/scrollbar_animation_controller_thinning.h
+++ b/chromium/cc/animation/scrollbar_animation_controller_thinning.h
@@ -26,6 +26,12 @@ class CC_EXPORT ScrollbarAnimationControllerThinning
virtual ~ScrollbarAnimationControllerThinning();
+ void set_mouse_move_distance_for_test(float distance) {
+ mouse_move_distance_to_trigger_animation_ = distance;
+ }
+ bool mouse_is_over_scrollbar() const { return mouse_is_over_scrollbar_; }
+ bool mouse_is_near_scrollbar() const { return mouse_is_near_scrollbar_; }
+
// ScrollbarAnimationController overrides.
virtual bool IsAnimating() const OVERRIDE;
virtual base::TimeDelta DelayBeforeStart(base::TimeTicks now) const OVERRIDE;
@@ -33,7 +39,9 @@ class CC_EXPORT ScrollbarAnimationControllerThinning
virtual bool Animate(base::TimeTicks now) OVERRIDE;
virtual void DidScrollGestureBegin() OVERRIDE;
virtual void DidScrollGestureEnd(base::TimeTicks now) OVERRIDE;
+ virtual void DidMouseMoveOffScrollbar(base::TimeTicks now) OVERRIDE;
virtual bool DidScrollUpdate(base::TimeTicks now) OVERRIDE;
+ virtual bool DidMouseMoveNear(base::TimeTicks now, float distance) OVERRIDE;
protected:
ScrollbarAnimationControllerThinning(LayerImpl* scroll_layer,
@@ -41,21 +49,41 @@ class CC_EXPORT ScrollbarAnimationControllerThinning
base::TimeDelta animation_duration);
private:
+ // Describes whether the current animation should INCREASE (darken / thicken)
+ // a bar or DECREASE it (lighten / thin).
+ enum AnimationChange {
+ NONE,
+ INCREASE,
+ DECREASE
+ };
// Returns how far through the animation we are as a progress value from
// 0 to 1.
float AnimationProgressAtTime(base::TimeTicks now);
float OpacityAtAnimationProgress(float progress);
float ThumbThicknessScaleAtAnimationProgress(float progress);
+ float AdjustScale(float new_value,
+ float current_value,
+ AnimationChange animation_change);
void ApplyOpacityAndThumbThicknessScale(float opacity,
float thumb_thickness_scale);
LayerImpl* scroll_layer_;
base::TimeTicks last_awaken_time_;
- bool scroll_gesture_in_progress_;
-
+ bool mouse_is_over_scrollbar_;
+ bool mouse_is_near_scrollbar_;
+ // Are we narrowing or thickening the bars.
+ AnimationChange thickness_change_;
+ // Are we darkening or lightening the bars.
+ AnimationChange opacity_change_;
+ // Should the animation be delayed or start immediately.
+ bool should_delay_animation_;
+ // If |should_delay_animation_| is true, delay the animation by this amount.
base::TimeDelta animation_delay_;
+ // The time for the animation to run.
base::TimeDelta animation_duration_;
+ // How close should the mouse be to the scrollbar before we thicken it.
+ float mouse_move_distance_to_trigger_animation_;
DISALLOW_COPY_AND_ASSIGN(ScrollbarAnimationControllerThinning);
};
diff --git a/chromium/cc/animation/scrollbar_animation_controller_thinning_unittest.cc b/chromium/cc/animation/scrollbar_animation_controller_thinning_unittest.cc
index c83bdc81b39..c915632f2fc 100644
--- a/chromium/cc/animation/scrollbar_animation_controller_thinning_unittest.cc
+++ b/chromium/cc/animation/scrollbar_animation_controller_thinning_unittest.cc
@@ -43,106 +43,194 @@ class ScrollbarAnimationControllerThinningTest : public testing::Test {
scoped_ptr<SolidColorScrollbarLayerImpl> scrollbar_layer_;
};
+// Check initialization of scrollbar.
TEST_F(ScrollbarAnimationControllerThinningTest, Idle) {
scrollbar_controller_->Animate(base::TimeTicks());
EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor());
}
-TEST_F(ScrollbarAnimationControllerThinningTest, AwakenByScrollGesture) {
+// Scroll content. Confirm the scrollbar gets dark and then becomes light
+// after stopping.
+TEST_F(ScrollbarAnimationControllerThinningTest, AwakenByProgrammaticScroll) {
base::TimeTicks time;
time += base::TimeDelta::FromSeconds(1);
- scrollbar_controller_->DidScrollGestureBegin();
- EXPECT_FALSE(scrollbar_controller_->IsAnimating());
+ EXPECT_TRUE(scrollbar_controller_->DidScrollUpdate(time));
+ EXPECT_TRUE(scrollbar_controller_->IsAnimating());
+ EXPECT_EQ(2, scrollbar_controller_->DelayBeforeStart(time).InSeconds());
EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity());
- EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
+ // Scrollbar doesn't change size if triggered by scroll.
+ EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor());
- time += base::TimeDelta::FromSeconds(100);
+ time += base::TimeDelta::FromSeconds(1);
+ EXPECT_EQ(1, scrollbar_controller_->DelayBeforeStart(time).InSeconds());
scrollbar_controller_->Animate(time);
EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity());
- EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
- scrollbar_controller_->DidScrollGestureEnd(time);
+ EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor());
- EXPECT_TRUE(scrollbar_controller_->IsAnimating());
+ // Subsequent scroll restarts animation.
+ EXPECT_TRUE(scrollbar_controller_->DidScrollUpdate(time));
EXPECT_EQ(2, scrollbar_controller_->DelayBeforeStart(time).InSeconds());
time += base::TimeDelta::FromSeconds(1);
+ EXPECT_EQ(1, scrollbar_controller_->DelayBeforeStart(time).InSeconds());
scrollbar_controller_->Animate(time);
EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity());
- EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
+ EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor());
time += base::TimeDelta::FromSeconds(1);
+ EXPECT_EQ(0, scrollbar_controller_->DelayBeforeStart(time).InSeconds());
scrollbar_controller_->Animate(time);
EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity());
- EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
+ EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor());
time += base::TimeDelta::FromSeconds(1);
scrollbar_controller_->Animate(time);
EXPECT_FLOAT_EQ(0.9f, scrollbar_layer_->opacity());
- EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->thumb_thickness_scale_factor());
+ EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor());
time += base::TimeDelta::FromSeconds(1);
scrollbar_controller_->Animate(time);
EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->opacity());
- EXPECT_FLOAT_EQ(0.6f, scrollbar_layer_->thumb_thickness_scale_factor());
+ EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor());
time += base::TimeDelta::FromSeconds(1);
+ scrollbar_controller_->Animate(time);
+ EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
+ EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor());
- scrollbar_controller_->DidScrollGestureBegin();
- scrollbar_controller_->DidScrollGestureEnd(time);
+ EXPECT_FALSE(scrollbar_controller_->IsAnimating());
+}
+// Initiate a scroll when the pointer is already near the scrollbar. It should
+// remain thick.
+TEST_F(ScrollbarAnimationControllerThinningTest, ScrollWithMouseNear) {
+ base::TimeTicks time;
time += base::TimeDelta::FromSeconds(1);
+
+ scrollbar_controller_->DidMouseMoveNear(time, 1);
+ time += base::TimeDelta::FromSeconds(3);
scrollbar_controller_->Animate(time);
+ EXPECT_FALSE(scrollbar_controller_->IsAnimating());
+ EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
+
+ EXPECT_TRUE(scrollbar_controller_->DidScrollUpdate(time));
+ EXPECT_TRUE(scrollbar_controller_->IsAnimating());
+ EXPECT_EQ(2, scrollbar_controller_->DelayBeforeStart(time).InSeconds());
EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity());
+ // Scrollbar should still be thick.
EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
+ time += base::TimeDelta::FromSeconds(5);
+ scrollbar_controller_->Animate(time);
+ EXPECT_FALSE(scrollbar_controller_->IsAnimating());
+ EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
+ EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
+}
+
+// Move the pointer near the scrollbar. Confirm it gets thick and narrow when
+// moved away.
+TEST_F(ScrollbarAnimationControllerThinningTest, MouseNear) {
+ base::TimeTicks time;
+ time += base::TimeDelta::FromSeconds(1);
+ scrollbar_controller_->DidMouseMoveNear(time, 1);
+ EXPECT_TRUE(scrollbar_controller_->IsAnimating());
+ EXPECT_EQ(0, scrollbar_controller_->DelayBeforeStart(time).InSeconds());
+ EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
+ EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor());
+
+ // Should animate to thickened but not darken.
time += base::TimeDelta::FromSeconds(1);
scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity());
+ EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
+ EXPECT_FLOAT_EQ(0.6f, scrollbar_layer_->thumb_thickness_scale_factor());
+
+ time += base::TimeDelta::FromSeconds(1);
+ scrollbar_controller_->Animate(time);
+ EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
+ EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->thumb_thickness_scale_factor());
+
+ time += base::TimeDelta::FromSeconds(1);
+ scrollbar_controller_->Animate(time);
+ EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
+ EXPECT_FALSE(scrollbar_controller_->IsAnimating());
+ // Subsequent moves should not change anything.
+ scrollbar_controller_->DidMouseMoveNear(time, 1);
+ EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
+ EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
+ EXPECT_FALSE(scrollbar_controller_->IsAnimating());
+
+ // Now move away from bar.
+ time += base::TimeDelta::FromSeconds(1);
+ scrollbar_controller_->DidMouseMoveNear(time, 26);
+ EXPECT_TRUE(scrollbar_controller_->IsAnimating());
+ EXPECT_EQ(0, scrollbar_controller_->DelayBeforeStart(time).InSeconds());
+ EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
+ EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
+
+ // Animate to narrow.
time += base::TimeDelta::FromSeconds(1);
scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(0.9f, scrollbar_layer_->opacity());
+ EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->thumb_thickness_scale_factor());
time += base::TimeDelta::FromSeconds(1);
scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->opacity());
+ EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
EXPECT_FLOAT_EQ(0.6f, scrollbar_layer_->thumb_thickness_scale_factor());
time += base::TimeDelta::FromSeconds(1);
scrollbar_controller_->Animate(time);
EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor());
+ EXPECT_FALSE(scrollbar_controller_->IsAnimating());
}
-TEST_F(ScrollbarAnimationControllerThinningTest, AwakenByProgrammaticScroll) {
+// Move the pointer over the scrollbar. Make sure it gets thick and dark
+// and that it gets thin and light when moved away.
+TEST_F(ScrollbarAnimationControllerThinningTest, MouseOver) {
base::TimeTicks time;
time += base::TimeDelta::FromSeconds(1);
- EXPECT_TRUE(scrollbar_controller_->DidScrollUpdate(time));
+ scrollbar_controller_->DidMouseMoveNear(time, 0);
EXPECT_TRUE(scrollbar_controller_->IsAnimating());
- EXPECT_EQ(2, scrollbar_controller_->DelayBeforeStart(time).InSeconds());
+ EXPECT_EQ(0, scrollbar_controller_->DelayBeforeStart(time).InSeconds());
+ EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
+ EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor());
+
+ // Should animate to thickened and darkened.
+ time += base::TimeDelta::FromSeconds(1);
scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity());
- EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
+ EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->opacity());
+ EXPECT_FLOAT_EQ(0.6f, scrollbar_layer_->thumb_thickness_scale_factor());
time += base::TimeDelta::FromSeconds(1);
scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity());
- EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
- EXPECT_TRUE(scrollbar_controller_->DidScrollUpdate(time));
+ EXPECT_FLOAT_EQ(0.9f, scrollbar_layer_->opacity());
+ EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->thumb_thickness_scale_factor());
time += base::TimeDelta::FromSeconds(1);
scrollbar_controller_->Animate(time);
EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity());
EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
+ EXPECT_FALSE(scrollbar_controller_->IsAnimating());
+ // Subsequent moves should not change anything.
+ scrollbar_controller_->DidMouseMoveNear(time, 0);
+ EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity());
+ EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
+ EXPECT_FALSE(scrollbar_controller_->IsAnimating());
+
+ // Now move away from bar.
time += base::TimeDelta::FromSeconds(1);
- scrollbar_controller_->Animate(time);
+ scrollbar_controller_->DidMouseMoveNear(time, 26);
+ EXPECT_TRUE(scrollbar_controller_->IsAnimating());
+ EXPECT_EQ(0, scrollbar_controller_->DelayBeforeStart(time).InSeconds());
EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity());
EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
+ // Animate to narrow.
time += base::TimeDelta::FromSeconds(1);
scrollbar_controller_->Animate(time);
EXPECT_FLOAT_EQ(0.9f, scrollbar_layer_->opacity());
@@ -154,31 +242,90 @@ TEST_F(ScrollbarAnimationControllerThinningTest, AwakenByProgrammaticScroll) {
EXPECT_FLOAT_EQ(0.6f, scrollbar_layer_->thumb_thickness_scale_factor());
time += base::TimeDelta::FromSeconds(1);
- EXPECT_TRUE(scrollbar_controller_->DidScrollUpdate(time));
+ scrollbar_controller_->Animate(time);
+ EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
+ EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor());
+ EXPECT_FALSE(scrollbar_controller_->IsAnimating());
+}
+
+// First move the pointer near the scrollbar, then over it, then back near
+// then far away. Confirm that first the bar gets thick, then dark, then light,
+// then narrow.
+TEST_F(ScrollbarAnimationControllerThinningTest, MouseNearThenOver) {
+ base::TimeTicks time;
time += base::TimeDelta::FromSeconds(1);
+ scrollbar_controller_->DidMouseMoveNear(time, 1);
+ EXPECT_TRUE(scrollbar_controller_->IsAnimating());
+ EXPECT_EQ(0, scrollbar_controller_->DelayBeforeStart(time).InSeconds());
+ EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
+ EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor());
+
+ // Should animate to thickened but not darken.
+ time += base::TimeDelta::FromSeconds(3);
scrollbar_controller_->Animate(time);
- EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity());
+ EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
+ EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
+ EXPECT_FALSE(scrollbar_controller_->IsAnimating());
+
+ // Now move over.
+ scrollbar_controller_->DidMouseMoveNear(time, 0);
+ EXPECT_TRUE(scrollbar_controller_->IsAnimating());
+ EXPECT_EQ(0, scrollbar_controller_->DelayBeforeStart(time).InSeconds());
+
+ // Should animate to darkened.
+ time += base::TimeDelta::FromSeconds(1);
+ scrollbar_controller_->Animate(time);
+ EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->opacity());
+ EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
+
+ time += base::TimeDelta::FromSeconds(1);
+ scrollbar_controller_->Animate(time);
+ EXPECT_FLOAT_EQ(0.9f, scrollbar_layer_->opacity());
EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
time += base::TimeDelta::FromSeconds(1);
scrollbar_controller_->Animate(time);
EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity());
EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
+ EXPECT_FALSE(scrollbar_controller_->IsAnimating());
+
+ // This is tricky. The DidMouseMoveOffScrollbar() is sent before the
+ // subsequent DidMouseMoveNear(), if the mouse moves in that direction.
+ // This results in the thumb thinning. We want to make sure that when the
+ // thumb starts expanding it doesn't first narrow to the idle thinness.
+ time += base::TimeDelta::FromSeconds(1);
+ scrollbar_controller_->DidMouseMoveOffScrollbar(time);
+ EXPECT_TRUE(scrollbar_controller_->IsAnimating());
time += base::TimeDelta::FromSeconds(1);
scrollbar_controller_->Animate(time);
EXPECT_FLOAT_EQ(0.9f, scrollbar_layer_->opacity());
EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->thumb_thickness_scale_factor());
+ scrollbar_controller_->DidMouseMoveNear(time, 1);
+ // A new animation is kicked off.
+ EXPECT_TRUE(scrollbar_controller_->IsAnimating());
+
+ time += base::TimeDelta::FromSeconds(1);
+ scrollbar_controller_->Animate(time);
+ // We will initiate the narrowing again, but it won't get decremented until
+ // the new animation catches up to it.
+ EXPECT_FLOAT_EQ(0.9f, scrollbar_layer_->opacity());
+ // Now the thickness should be increasing, but it shouldn't happen until the
+ // animation catches up.
+ EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->thumb_thickness_scale_factor());
+
time += base::TimeDelta::FromSeconds(1);
scrollbar_controller_->Animate(time);
EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->opacity());
- EXPECT_FLOAT_EQ(0.6f, scrollbar_layer_->thumb_thickness_scale_factor());
+ // The thickness now gets big again.
+ EXPECT_FLOAT_EQ(0.8f, scrollbar_layer_->thumb_thickness_scale_factor());
time += base::TimeDelta::FromSeconds(1);
scrollbar_controller_->Animate(time);
EXPECT_FLOAT_EQ(0.7f, scrollbar_layer_->opacity());
- EXPECT_FLOAT_EQ(0.4f, scrollbar_layer_->thumb_thickness_scale_factor());
+ // The thickness now gets big again.
+ EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->thumb_thickness_scale_factor());
}
} // namespace
diff --git a/chromium/cc/animation/transform_operation.cc b/chromium/cc/animation/transform_operation.cc
index 93f40f37f1a..e4d0dadf0eb 100644
--- a/chromium/cc/animation/transform_operation.cc
+++ b/chromium/cc/animation/transform_operation.cc
@@ -2,17 +2,24 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Needed on Windows to get |M_PI| from <cmath>
+#ifdef _WIN32
+#define _USE_MATH_DEFINES
+#endif
+
#include <algorithm>
#include <cmath>
#include <limits>
#include "base/logging.h"
#include "cc/animation/transform_operation.h"
+#include "cc/animation/transform_operations.h"
#include "ui/gfx/box_f.h"
+#include "ui/gfx/transform_util.h"
#include "ui/gfx/vector3d_f.h"
namespace {
-const SkMScalar kAngleEpsilon = 1e-4;
+const SkMScalar kAngleEpsilon = 1e-4f;
}
namespace cc {
@@ -158,11 +165,19 @@ bool TransformOperation::BlendTransformOperations(
SkMScalar from_perspective_depth =
IsOperationIdentity(from) ? std::numeric_limits<SkMScalar>::max()
: from->perspective_depth;
- SkMScalar to_perspective_depth = IsOperationIdentity(to)
- ? std::numeric_limits<SkMScalar>::max()
- : to->perspective_depth;
- result->ApplyPerspectiveDepth(BlendSkMScalars(
- from_perspective_depth, to_perspective_depth, progress));
+ SkMScalar to_perspective_depth =
+ IsOperationIdentity(to) ? std::numeric_limits<SkMScalar>::max()
+ : to->perspective_depth;
+ if (from_perspective_depth == 0.f || to_perspective_depth == 0.f)
+ return false;
+
+ SkMScalar blended_perspective_depth = BlendSkMScalars(
+ 1.f / from_perspective_depth, 1.f / to_perspective_depth, progress);
+
+ if (blended_perspective_depth == 0.f)
+ return false;
+
+ result->ApplyPerspectiveDepth(1.f / blended_perspective_depth);
break;
}
case TransformOperation::TransformOperationMatrix: {
@@ -185,28 +200,167 @@ bool TransformOperation::BlendTransformOperations(
return true;
}
-static void ApplyScaleToBox(float x_scale,
- float y_scale,
- float z_scale,
- gfx::BoxF* box) {
- if (x_scale < 0)
- box->set_x(-box->right());
- if (y_scale < 0)
- box->set_y(-box->bottom());
- if (z_scale < 0)
- box->set_z(-box->front());
- box->Scale(std::abs(x_scale), std::abs(y_scale), std::abs(z_scale));
+// If p = (px, py) is a point in the plane being rotated about (0, 0, nz), this
+// function computes the angles we would have to rotate from p to get to
+// (length(p), 0), (-length(p), 0), (0, length(p)), (0, -length(p)). If nz is
+// negative, these angles will need to be reversed.
+static void FindCandidatesInPlane(float px,
+ float py,
+ float nz,
+ double* candidates,
+ int* num_candidates) {
+ double phi = atan2(px, py);
+ *num_candidates = 4;
+ candidates[0] = phi;
+ for (int i = 1; i < *num_candidates; ++i)
+ candidates[i] = candidates[i - 1] + M_PI_2;
+ if (nz < 0.f) {
+ for (int i = 0; i < *num_candidates; ++i)
+ candidates[i] *= -1.f;
+ }
}
-static void UnionBoxWithZeroScale(gfx::BoxF* box) {
- float min_x = std::min(box->x(), 0.f);
- float min_y = std::min(box->y(), 0.f);
- float min_z = std::min(box->z(), 0.f);
- float max_x = std::max(box->right(), 0.f);
- float max_y = std::max(box->bottom(), 0.f);
- float max_z = std::max(box->front(), 0.f);
- *box = gfx::BoxF(
- min_x, min_y, min_z, max_x - min_x, max_y - min_y, max_z - min_z);
+static float RadiansToDegrees(float radians) {
+ return (180.f * radians) / M_PI;
+}
+
+static float DegreesToRadians(float degrees) {
+ return (M_PI * degrees) / 180.f;
+}
+
+static void BoundingBoxForArc(const gfx::Point3F& point,
+ const TransformOperation* from,
+ const TransformOperation* to,
+ SkMScalar min_progress,
+ SkMScalar max_progress,
+ gfx::BoxF* box) {
+ const TransformOperation* exemplar = from ? from : to;
+ gfx::Vector3dF axis(exemplar->rotate.axis.x,
+ exemplar->rotate.axis.y,
+ exemplar->rotate.axis.z);
+
+ const bool x_is_zero = axis.x() == 0.f;
+ const bool y_is_zero = axis.y() == 0.f;
+ const bool z_is_zero = axis.z() == 0.f;
+
+ // We will have at most 6 angles to test (excluding from->angle and
+ // to->angle).
+ static const int kMaxNumCandidates = 6;
+ double candidates[kMaxNumCandidates];
+ int num_candidates = kMaxNumCandidates;
+
+ if (x_is_zero && y_is_zero && z_is_zero)
+ return;
+
+ SkMScalar from_angle = from ? from->rotate.angle : 0.f;
+ SkMScalar to_angle = to ? to->rotate.angle : 0.f;
+
+ // If the axes of rotation are pointing in opposite directions, we need to
+ // flip one of the angles. Note, if both |from| and |to| exist, then axis will
+ // correspond to |from|.
+ if (from && to) {
+ gfx::Vector3dF other_axis(
+ to->rotate.axis.x, to->rotate.axis.y, to->rotate.axis.z);
+ if (gfx::DotProduct(axis, other_axis) < 0.f)
+ to_angle *= -1.f;
+ }
+
+ float min_degrees =
+ SkMScalarToFloat(BlendSkMScalars(from_angle, to_angle, min_progress));
+ float max_degrees =
+ SkMScalarToFloat(BlendSkMScalars(from_angle, to_angle, max_progress));
+ if (max_degrees < min_degrees)
+ std::swap(min_degrees, max_degrees);
+
+ gfx::Transform from_transform;
+ from_transform.RotateAbout(axis, min_degrees);
+ gfx::Transform to_transform;
+ to_transform.RotateAbout(axis, max_degrees);
+
+ *box = gfx::BoxF();
+
+ gfx::Point3F point_rotated_from = point;
+ from_transform.TransformPoint(&point_rotated_from);
+ gfx::Point3F point_rotated_to = point;
+ to_transform.TransformPoint(&point_rotated_to);
+
+ box->set_origin(point_rotated_from);
+ box->ExpandTo(point_rotated_to);
+
+ if (x_is_zero && y_is_zero) {
+ FindCandidatesInPlane(
+ point.x(), point.y(), axis.z(), candidates, &num_candidates);
+ } else if (x_is_zero && z_is_zero) {
+ FindCandidatesInPlane(
+ point.z(), point.x(), axis.y(), candidates, &num_candidates);
+ } else if (y_is_zero && z_is_zero) {
+ FindCandidatesInPlane(
+ point.y(), point.z(), axis.x(), candidates, &num_candidates);
+ } else {
+ gfx::Vector3dF normal = axis;
+ normal.Scale(1.f / normal.Length());
+
+ // First, find center of rotation.
+ gfx::Point3F origin;
+ gfx::Vector3dF to_point = point - origin;
+ gfx::Point3F center =
+ origin + gfx::ScaleVector3d(normal, gfx::DotProduct(to_point, normal));
+
+ // Now we need to find two vectors in the plane of rotation. One pointing
+ // towards point and another, perpendicular vector in the plane.
+ gfx::Vector3dF v1 = point - center;
+ float v1_length = v1.Length();
+ if (v1_length == 0.f)
+ return;
+
+ v1.Scale(1.f / v1_length);
+
+ gfx::Vector3dF v2 = gfx::CrossProduct(normal, v1);
+
+ // Now figure out where (1, 0, 0) and (0, 0, 1) project on the rotation
+ // plane.
+ gfx::Point3F px(1.f, 0.f, 0.f);
+ gfx::Vector3dF to_px = px - center;
+ gfx::Point3F px_projected =
+ px - gfx::ScaleVector3d(normal, gfx::DotProduct(to_px, normal));
+ gfx::Vector3dF vx = px_projected - origin;
+
+ gfx::Point3F pz(0.f, 0.f, 1.f);
+ gfx::Vector3dF to_pz = pz - center;
+ gfx::Point3F pz_projected =
+ pz - ScaleVector3d(normal, gfx::DotProduct(to_pz, normal));
+ gfx::Vector3dF vz = pz_projected - origin;
+
+ double phi_x = atan2(gfx::DotProduct(v2, vx), gfx::DotProduct(v1, vx));
+ double phi_z = atan2(gfx::DotProduct(v2, vz), gfx::DotProduct(v1, vz));
+
+ candidates[0] = atan2(normal.y(), normal.x() * normal.z()) + phi_x;
+ candidates[1] = candidates[0] + M_PI;
+ candidates[2] = atan2(-normal.z(), normal.x() * normal.y()) + phi_x;
+ candidates[3] = candidates[2] + M_PI;
+ candidates[4] = atan2(normal.y(), -normal.x() * normal.z()) + phi_z;
+ candidates[5] = candidates[4] + M_PI;
+ }
+
+ double min_radians = DegreesToRadians(min_degrees);
+ double max_radians = DegreesToRadians(max_degrees);
+
+ for (int i = 0; i < num_candidates; ++i) {
+ double radians = candidates[i];
+ while (radians < min_radians)
+ radians += 2.0 * M_PI;
+ while (radians > max_radians)
+ radians -= 2.0 * M_PI;
+ if (radians < min_radians)
+ continue;
+
+ gfx::Transform rotation;
+ rotation.RotateAbout(axis, RadiansToDegrees(radians));
+ gfx::Point3F rotated = point;
+ rotation.TransformPoint(&rotated);
+
+ box->ExpandTo(rotated);
+ }
}
bool TransformOperation::BlendedBoundsForBox(const gfx::BoxF& box,
@@ -230,80 +384,53 @@ bool TransformOperation::BlendedBoundsForBox(const gfx::BoxF& box,
interpolation_type = to->type;
switch (interpolation_type) {
- case TransformOperation::TransformOperationTranslate: {
- SkMScalar from_x, from_y, from_z;
- if (is_identity_from) {
- from_x = from_y = from_z = 0.0;
- } else {
- from_x = from->translate.x;
- from_y = from->translate.y;
- from_z = from->translate.z;
- }
- SkMScalar to_x, to_y, to_z;
- if (is_identity_to) {
- to_x = to_y = to_z = 0.0;
- } else {
- to_x = to->translate.x;
- to_y = to->translate.y;
- to_z = to->translate.z;
- }
+ case TransformOperation::TransformOperationIdentity:
*bounds = box;
- *bounds += gfx::Vector3dF(BlendSkMScalars(from_x, to_x, min_progress),
- BlendSkMScalars(from_y, to_y, min_progress),
- BlendSkMScalars(from_z, to_z, min_progress));
- gfx::BoxF bounds_max = box;
- bounds_max += gfx::Vector3dF(BlendSkMScalars(from_x, to_x, max_progress),
- BlendSkMScalars(from_y, to_y, max_progress),
- BlendSkMScalars(from_z, to_z, max_progress));
- bounds->Union(bounds_max);
return true;
- }
+ case TransformOperation::TransformOperationTranslate:
+ case TransformOperation::TransformOperationSkew:
+ case TransformOperation::TransformOperationPerspective:
case TransformOperation::TransformOperationScale: {
- SkMScalar from_x, from_y, from_z;
- if (is_identity_from) {
- from_x = from_y = from_z = 1.0;
- } else {
- from_x = from->scale.x;
- from_y = from->scale.y;
- from_z = from->scale.z;
- }
- SkMScalar to_x, to_y, to_z;
- if (is_identity_to) {
- to_x = to_y = to_z = 1.0;
- } else {
- to_x = to->scale.x;
- to_y = to->scale.y;
- to_z = to->scale.z;
- }
+ gfx::Transform from_transform;
+ gfx::Transform to_transform;
+ if (!BlendTransformOperations(from, to, min_progress, &from_transform) ||
+ !BlendTransformOperations(from, to, max_progress, &to_transform))
+ return false;
+
*bounds = box;
- ApplyScaleToBox(
- SkMScalarToFloat(BlendSkMScalars(from_x, to_x, min_progress)),
- SkMScalarToFloat(BlendSkMScalars(from_y, to_y, min_progress)),
- SkMScalarToFloat(BlendSkMScalars(from_z, to_z, min_progress)),
- bounds);
- gfx::BoxF bounds_max = box;
- ApplyScaleToBox(
- SkMScalarToFloat(BlendSkMScalars(from_x, to_x, max_progress)),
- SkMScalarToFloat(BlendSkMScalars(from_y, to_y, max_progress)),
- SkMScalarToFloat(BlendSkMScalars(from_z, to_z, max_progress)),
- &bounds_max);
- if (!bounds->IsEmpty() && !bounds_max.IsEmpty()) {
- bounds->Union(bounds_max);
- } else if (!bounds->IsEmpty()) {
- UnionBoxWithZeroScale(bounds);
- } else if (!bounds_max.IsEmpty()) {
- UnionBoxWithZeroScale(&bounds_max);
- *bounds = bounds_max;
- }
+ from_transform.TransformBox(bounds);
+
+ gfx::BoxF to_box = box;
+ to_transform.TransformBox(&to_box);
+ bounds->ExpandTo(to_box);
return true;
}
- case TransformOperation::TransformOperationIdentity:
- *bounds = box;
+ case TransformOperation::TransformOperationRotate: {
+ SkMScalar axis_x = 0;
+ SkMScalar axis_y = 0;
+ SkMScalar axis_z = 1;
+ SkMScalar from_angle = 0;
+ if (!ShareSameAxis(from, to, &axis_x, &axis_y, &axis_z, &from_angle))
+ return false;
+
+ bool first_point = true;
+ for (int i = 0; i < 8; ++i) {
+ gfx::Point3F corner = box.origin();
+ corner += gfx::Vector3dF(i & 1 ? box.width() : 0.f,
+ i & 2 ? box.height() : 0.f,
+ i & 4 ? box.depth() : 0.f);
+ gfx::BoxF box_for_arc;
+ BoundingBoxForArc(
+ corner, from, to, min_progress, max_progress, &box_for_arc);
+ if (first_point)
+ *bounds = box_for_arc;
+ else
+ bounds->Union(box_for_arc);
+ first_point = false;
+ }
return true;
- case TransformOperation::TransformOperationRotate:
- case TransformOperation::TransformOperationSkew:
- case TransformOperation::TransformOperationPerspective:
+ }
case TransformOperation::TransformOperationMatrix:
return false;
}
diff --git a/chromium/cc/animation/transform_operations_unittest.cc b/chromium/cc/animation/transform_operations_unittest.cc
index a7e4c510a52..831ce71ce37 100644
--- a/chromium/cc/animation/transform_operations_unittest.cc
+++ b/chromium/cc/animation/transform_operations_unittest.cc
@@ -4,11 +4,14 @@
#include <limits>
+#include "base/basictypes.h"
#include "base/memory/scoped_vector.h"
#include "cc/animation/transform_operations.h"
#include "cc/test/geometry_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/animation/tween.h"
#include "ui/gfx/box_f.h"
+#include "ui/gfx/rect_conversions.h"
#include "ui/gfx/vector3d_f.h"
namespace cc {
@@ -568,8 +571,7 @@ TEST(TransformOperationTest, BlendPerspectiveFromIdentity) {
SkMScalar progress = 0.5f;
gfx::Transform expected;
- expected.ApplyPerspectiveDepth(500 +
- 0.5 * std::numeric_limits<SkMScalar>::max());
+ expected.ApplyPerspectiveDepth(2000);
EXPECT_TRANSFORMATION_MATRIX_EQ(
expected, operations.Blend(*identity_operations[i], progress));
@@ -660,8 +662,7 @@ TEST(TransformOperationTest, BlendPerspectiveToIdentity) {
SkMScalar progress = 0.5f;
gfx::Transform expected;
- expected.ApplyPerspectiveDepth(500 +
- 0.5 * std::numeric_limits<SkMScalar>::max());
+ expected.ApplyPerspectiveDepth(2000);
EXPECT_TRANSFORMATION_MATRIX_EQ(
expected, identity_operations[i]->Blend(operations, progress));
@@ -676,13 +677,13 @@ TEST(TransformOperationTest, ExtrapolatePerspectiveBlending) {
operations2.AppendPerspective(500);
gfx::Transform expected;
- expected.ApplyPerspectiveDepth(250);
+ expected.ApplyPerspectiveDepth(400);
EXPECT_TRANSFORMATION_MATRIX_EQ(
expected, operations1.Blend(operations2, -0.5));
expected.MakeIdentity();
- expected.ApplyPerspectiveDepth(1250);
+ expected.ApplyPerspectiveDepth(2000);
EXPECT_TRANSFORMATION_MATRIX_EQ(
expected, operations1.Blend(operations2, 1.5));
@@ -840,6 +841,384 @@ TEST(TransformOperationTest, BlendedBoundsWithZeroScale) {
EXPECT_EQ(gfx::BoxF().ToString(), bounds.ToString());
}
+TEST(TransformOperationTest, BlendedBoundsForRotationTrivial) {
+ TransformOperations operations_from;
+ operations_from.AppendRotate(0.f, 0.f, 1.f, 0.f);
+ TransformOperations operations_to;
+ operations_to.AppendRotate(0.f, 0.f, 1.f, 360.f);
+
+ float sqrt_2 = sqrt(2.f);
+ gfx::BoxF box(
+ -sqrt_2, -sqrt_2, 0.f, sqrt_2, sqrt_2, 0.f);
+ gfx::BoxF bounds;
+
+ // Since we're rotating 360 degrees, any box with dimensions between 0 and
+ // 2 * sqrt(2) should give the same result.
+ float sizes[] = { 0.f, 0.1f, sqrt_2, 2.f * sqrt_2 };
+ for (size_t i = 0; i < arraysize(sizes); ++i) {
+ box.set_size(sizes[i], sizes[i], 0.f);
+ SkMScalar min_progress = 0.f;
+ SkMScalar max_progress = 1.f;
+ EXPECT_TRUE(operations_to.BlendedBoundsForBox(
+ box, operations_from, min_progress, max_progress, &bounds));
+ EXPECT_EQ(gfx::BoxF(-2.f, -2.f, 0.f, 4.f, 4.f, 0.f).ToString(),
+ bounds.ToString());
+ }
+}
+
+TEST(TransformOperationTest, BlendedBoundsForRotationAllExtrema) {
+ // If the normal is out of the plane, we can have up to 6 extrema (a min/max
+ // in each dimension) between the endpoints of the arc. This test ensures that
+ // we consider all 6.
+ TransformOperations operations_from;
+ operations_from.AppendRotate(1.f, 1.f, 1.f, 30.f);
+ TransformOperations operations_to;
+ operations_to.AppendRotate(1.f, 1.f, 1.f, 390.f);
+
+ gfx::BoxF box(1.f, 0.f, 0.f, 0.f, 0.f, 0.f);
+ gfx::BoxF bounds;
+
+ float min = -1.f / 3.f;
+ float max = 1.f;
+ float size = max - min;
+ EXPECT_TRUE(operations_to.BlendedBoundsForBox(
+ box, operations_from, 0.f, 1.f, &bounds));
+ EXPECT_EQ(gfx::BoxF(min, min, min, size, size, size).ToString(),
+ bounds.ToString());
+}
+
+TEST(TransformOperationTest, BlendedBoundsForRotationDifferentAxes) {
+ // We can handle rotations about a single axis. If the axes are different,
+ // we revert to matrix interpolation for which inflated bounds cannot be
+ // computed.
+ TransformOperations operations_from;
+ operations_from.AppendRotate(1.f, 1.f, 1.f, 30.f);
+ TransformOperations operations_to_same;
+ operations_to_same.AppendRotate(1.f, 1.f, 1.f, 390.f);
+ TransformOperations operations_to_opposite;
+ operations_to_opposite.AppendRotate(-1.f, -1.f, -1.f, 390.f);
+ TransformOperations operations_to_different;
+ operations_to_different.AppendRotate(1.f, 3.f, 1.f, 390.f);
+
+ gfx::BoxF box(1.f, 0.f, 0.f, 0.f, 0.f, 0.f);
+ gfx::BoxF bounds;
+
+ EXPECT_TRUE(operations_to_same.BlendedBoundsForBox(
+ box, operations_from, 0.f, 1.f, &bounds));
+ EXPECT_TRUE(operations_to_opposite.BlendedBoundsForBox(
+ box, operations_from, 0.f, 1.f, &bounds));
+ EXPECT_FALSE(operations_to_different.BlendedBoundsForBox(
+ box, operations_from, 0.f, 1.f, &bounds));
+}
+
+TEST(TransformOperationTest, BlendedBoundsForRotationPointOnAxis) {
+ // Checks that if the point to rotate is sitting on the axis of rotation, that
+ // it does not get affected.
+ TransformOperations operations_from;
+ operations_from.AppendRotate(1.f, 1.f, 1.f, 30.f);
+ TransformOperations operations_to;
+ operations_to.AppendRotate(1.f, 1.f, 1.f, 390.f);
+
+ gfx::BoxF box(1.f, 1.f, 1.f, 0.f, 0.f, 0.f);
+ gfx::BoxF bounds;
+
+ EXPECT_TRUE(operations_to.BlendedBoundsForBox(
+ box, operations_from, 0.f, 1.f, &bounds));
+ EXPECT_EQ(box.ToString(), bounds.ToString());
+}
+
+// This would have been best as anonymous structs, but |arraysize| does not get
+// along with anonymous structs (and using ARRAYSIZE_UNSAFE seemed like a worse
+// option).
+struct ProblematicAxisTest {
+ float x;
+ float y;
+ float z;
+ gfx::BoxF expected;
+};
+
+TEST(TransformOperationTest, BlendedBoundsForRotationProblematicAxes) {
+ // Zeros in the components of the axis of rotation turned out to be tricky to
+ // deal with in practice. This function tests some potentially problematic
+ // axes to ensure sane behavior.
+
+ // Some common values used in the expected boxes.
+ float dim1 = 0.292893f;
+ float dim2 = sqrt(2.f);
+ float dim3 = 2.f * dim2;
+
+ ProblematicAxisTest tests[] = {
+ { 0.f, 0.f, 0.f, gfx::BoxF(1.f, 1.f, 1.f, 0.f, 0.f, 0.f) },
+ { 1.f, 0.f, 0.f, gfx::BoxF(1.f, -dim2, -dim2, 0.f, dim3, dim3) },
+ { 0.f, 1.f, 0.f, gfx::BoxF(-dim2, 1.f, -dim2, dim3, 0.f, dim3) },
+ { 0.f, 0.f, 1.f, gfx::BoxF(-dim2, -dim2, 1.f, dim3, dim3, 0.f) },
+ { 1.f, 1.f, 0.f, gfx::BoxF(dim1, dim1, -1.f, dim2, dim2, 2.f) },
+ { 0.f, 1.f, 1.f, gfx::BoxF(-1.f, dim1, dim1, 2.f, dim2, dim2) },
+ { 1.f, 0.f, 1.f, gfx::BoxF(dim1, -1.f, dim1, dim2, 2.f, dim2) }
+ };
+
+ for (size_t i = 0; i < arraysize(tests); ++i) {
+ float x = tests[i].x;
+ float y = tests[i].y;
+ float z = tests[i].z;
+ TransformOperations operations_from;
+ operations_from.AppendRotate(x, y, z, 0.f);
+ TransformOperations operations_to;
+ operations_to.AppendRotate(x, y, z, 360.f);
+ gfx::BoxF box(1.f, 1.f, 1.f, 0.f, 0.f, 0.f);
+ gfx::BoxF bounds;
+
+ EXPECT_TRUE(operations_to.BlendedBoundsForBox(
+ box, operations_from, 0.f, 1.f, &bounds));
+ EXPECT_EQ(tests[i].expected.ToString(), bounds.ToString());
+ }
+}
+
+// These would have been best as anonymous structs, but |arraysize| does not get
+// along with anonymous structs (and using ARRAYSIZE_UNSAFE seemed like a worse
+// option).
+struct TestAxis {
+ float x;
+ float y;
+ float z;
+};
+
+struct TestAngles {
+ float theta_from;
+ float theta_to;
+};
+
+struct TestProgress {
+ float min_progress;
+ float max_progress;
+};
+
+static void ExpectBoxesApproximatelyEqual(const gfx::BoxF& lhs,
+ const gfx::BoxF& rhs,
+ float tolerance) {
+ EXPECT_NEAR(lhs.x(), rhs.x(), tolerance);
+ EXPECT_NEAR(lhs.y(), rhs.y(), tolerance);
+ EXPECT_NEAR(lhs.z(), rhs.z(), tolerance);
+ EXPECT_NEAR(lhs.width(), rhs.width(), tolerance);
+ EXPECT_NEAR(lhs.height(), rhs.height(), tolerance);
+ EXPECT_NEAR(lhs.depth(), rhs.depth(), tolerance);
+}
+
+static void EmpiricallyTestBounds(const TransformOperations& from,
+ const TransformOperations& to,
+ SkMScalar min_progress,
+ SkMScalar max_progress,
+ bool test_containment_only) {
+ gfx::BoxF box(200.f, 500.f, 100.f, 100.f, 300.f, 200.f);
+ gfx::BoxF bounds;
+ EXPECT_TRUE(
+ to.BlendedBoundsForBox(box, from, min_progress, max_progress, &bounds));
+
+ bool first_time = true;
+ gfx::BoxF empirical_bounds;
+ static const size_t kNumSteps = 10;
+ for (size_t step = 0; step < kNumSteps; ++step) {
+ float t = step / (kNumSteps - 1.f);
+ t = gfx::Tween::FloatValueBetween(t, min_progress, max_progress);
+ gfx::Transform partial_transform = to.Blend(from, t);
+ gfx::BoxF transformed = box;
+ partial_transform.TransformBox(&transformed);
+
+ if (first_time) {
+ empirical_bounds = transformed;
+ first_time = false;
+ } else {
+ empirical_bounds.Union(transformed);
+ }
+ }
+
+ if (test_containment_only) {
+ gfx::BoxF unified_bounds = bounds;
+ unified_bounds.Union(empirical_bounds);
+ // Convert to the screen space rects these boxes represent.
+ gfx::Rect bounds_rect = ToEnclosingRect(
+ gfx::RectF(bounds.x(), bounds.y(), bounds.width(), bounds.height()));
+ gfx::Rect unified_bounds_rect =
+ ToEnclosingRect(gfx::RectF(unified_bounds.x(),
+ unified_bounds.y(),
+ unified_bounds.width(),
+ unified_bounds.height()));
+ EXPECT_EQ(bounds_rect.ToString(), unified_bounds_rect.ToString());
+ } else {
+ // Our empirical estimate will be a little rough since we're only doing
+ // 100 samples.
+ static const float kTolerance = 1e-2f;
+ ExpectBoxesApproximatelyEqual(empirical_bounds, bounds, kTolerance);
+ }
+}
+
+static void EmpiricallyTestBoundsEquality(const TransformOperations& from,
+ const TransformOperations& to,
+ SkMScalar min_progress,
+ SkMScalar max_progress) {
+ EmpiricallyTestBounds(from, to, min_progress, max_progress, false);
+}
+
+static void EmpiricallyTestBoundsContainment(const TransformOperations& from,
+ const TransformOperations& to,
+ SkMScalar min_progress,
+ SkMScalar max_progress) {
+ EmpiricallyTestBounds(from, to, min_progress, max_progress, true);
+}
+
+TEST(TransformOperationTest, BlendedBoundsForRotationEmpiricalTests) {
+ // Sets up various axis angle combinations, computes the bounding box and
+ // empirically tests that the transformed bounds are indeed contained by the
+ // computed bounding box.
+
+ TestAxis axes[] = {
+ { 1.f, 1.f, 1.f },
+ { -1.f, -1.f, -1.f },
+ { -1.f, 2.f, 3.f },
+ { 1.f, -2.f, 3.f },
+ { 1.f, 2.f, -3.f },
+ { 0.f, 0.f, 0.f },
+ { 1.f, 0.f, 0.f },
+ { 0.f, 1.f, 0.f },
+ { 0.f, 0.f, 1.f },
+ { 1.f, 1.f, 0.f },
+ { 0.f, 1.f, 1.f },
+ { 1.f, 0.f, 1.f },
+ { -1.f, 0.f, 0.f },
+ { 0.f, -1.f, 0.f },
+ { 0.f, 0.f, -1.f },
+ { -1.f, -1.f, 0.f },
+ { 0.f, -1.f, -1.f },
+ { -1.f, 0.f, -1.f }
+ };
+
+ TestAngles angles[] = {
+ { 5.f, 10.f },
+ { 10.f, 5.f },
+ { 0.f, 360.f },
+ { 20.f, 180.f },
+ { -20.f, -180.f },
+ { 180.f, -220.f },
+ { 220.f, 320.f }
+ };
+
+ // We can go beyond the range [0, 1] (the bezier might slide out of this range
+ // at either end), but since the first and last knots are at (0, 0) and (1, 1)
+ // we will never go within it, so these tests are sufficient.
+ TestProgress progress[] = {
+ { 0.f, 1.f },
+ { -.25f, 1.25f },
+ };
+
+ for (size_t i = 0; i < arraysize(axes); ++i) {
+ for (size_t j = 0; j < arraysize(angles); ++j) {
+ for (size_t k = 0; k < arraysize(progress); ++k) {
+ float x = axes[i].x;
+ float y = axes[i].y;
+ float z = axes[i].z;
+ TransformOperations operations_from;
+ operations_from.AppendRotate(x, y, z, angles[j].theta_from);
+ TransformOperations operations_to;
+ operations_to.AppendRotate(x, y, z, angles[j].theta_to);
+ EmpiricallyTestBoundsContainment(operations_from,
+ operations_to,
+ progress[k].min_progress,
+ progress[k].max_progress);
+ }
+ }
+ }
+}
+
+TEST(TransformOperationTest, PerspectiveMatrixAndTransformBlendingEquivalency) {
+ TransformOperations from_operations;
+ from_operations.AppendPerspective(200);
+
+ TransformOperations to_operations;
+ to_operations.AppendPerspective(1000);
+
+ gfx::Transform from_transform;
+ from_transform.ApplyPerspectiveDepth(200);
+
+ gfx::Transform to_transform;
+ to_transform.ApplyPerspectiveDepth(1000);
+
+ static const int steps = 20;
+ for (int i = 0; i < steps; ++i) {
+ double progress = static_cast<double>(i) / (steps - 1);
+
+ gfx::Transform blended_matrix = to_transform;
+ EXPECT_TRUE(blended_matrix.Blend(from_transform, progress));
+
+ gfx::Transform blended_transform =
+ to_operations.Blend(from_operations, progress);
+
+ EXPECT_TRANSFORMATION_MATRIX_EQ(blended_matrix, blended_transform);
+ }
+}
+
+struct TestPerspectiveDepths {
+ float from_depth;
+ float to_depth;
+};
+
+TEST(TransformOperationTest, BlendedBoundsForPerspective) {
+ TestPerspectiveDepths perspective_depths[] = {
+ { 600.f, 400.f },
+ { 800.f, 1000.f },
+ { 800.f, std::numeric_limits<float>::infinity() },
+ };
+
+ TestProgress progress[] = {
+ { 0.f, 1.f },
+ { -0.1f, 1.1f },
+ };
+
+ for (size_t i = 0; i < arraysize(perspective_depths); ++i) {
+ for (size_t j = 0; j < arraysize(progress); ++j) {
+ TransformOperations operations_from;
+ operations_from.AppendPerspective(perspective_depths[i].from_depth);
+ TransformOperations operations_to;
+ operations_to.AppendPerspective(perspective_depths[i].to_depth);
+ EmpiricallyTestBoundsEquality(operations_from,
+ operations_to,
+ progress[j].min_progress,
+ progress[j].max_progress);
+ }
+ }
+}
+
+struct TestSkews {
+ float from_x;
+ float from_y;
+ float to_x;
+ float to_y;
+};
+
+TEST(TransformOperationTest, BlendedBoundsForSkew) {
+ TestSkews skews[] = {
+ { 1.f, 0.5f, 0.5f, 1.f },
+ { 2.f, 1.f, 0.5f, 0.5f },
+ };
+
+ TestProgress progress[] = {
+ { 0.f, 1.f },
+ { -0.1f, 1.1f },
+ };
+
+ for (size_t i = 0; i < arraysize(skews); ++i) {
+ for (size_t j = 0; j < arraysize(progress); ++j) {
+ TransformOperations operations_from;
+ operations_from.AppendSkew(skews[i].from_x, skews[i].from_y);
+ TransformOperations operations_to;
+ operations_to.AppendSkew(skews[i].to_x, skews[i].to_y);
+ EmpiricallyTestBoundsEquality(operations_from,
+ operations_to,
+ progress[j].min_progress,
+ progress[j].max_progress);
+ }
+ }
+}
+
TEST(TransformOperationTest, BlendedBoundsForSequence) {
TransformOperations operations_from;
operations_from.AppendTranslate(2.0, 4.0, -1.0);
diff --git a/chromium/cc/base/float_quad_unittest.cc b/chromium/cc/base/float_quad_unittest.cc
index 186624eec34..c2186fd81b4 100644
--- a/chromium/cc/base/float_quad_unittest.cc
+++ b/chromium/cc/base/float_quad_unittest.cc
@@ -15,15 +15,15 @@ namespace {
TEST(FloatQuadTest, IsRectilinearTest) {
const int kNumRectilinear = 8;
gfx::Transform rectilinear_trans[kNumRectilinear];
- rectilinear_trans[1].Rotate(90.0);
- rectilinear_trans[2].Rotate(180.0);
- rectilinear_trans[3].Rotate(270.0);
- rectilinear_trans[4].SkewX(0.00000000001);
- rectilinear_trans[5].SkewY(0.00000000001);
- rectilinear_trans[6].Scale(0.00001, 0.00001);
- rectilinear_trans[6].Rotate(180.0);
- rectilinear_trans[7].Scale(100000, 100000);
- rectilinear_trans[7].Rotate(180.0);
+ 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[6].Scale(0.00001f, 0.00001f);
+ rectilinear_trans[6].Rotate(180.f);
+ rectilinear_trans[7].Scale(100000.f, 100000.f);
+ rectilinear_trans[7].Rotate(180.f);
gfx::QuadF original(
gfx::RectF(0.01010101f, 0.01010101f, 100.01010101f, 100.01010101f));
@@ -38,16 +38,16 @@ TEST(FloatQuadTest, IsRectilinearTest) {
const int kNumNonRectilinear = 10;
gfx::Transform non_rectilinear_trans[kNumNonRectilinear];
- non_rectilinear_trans[0].Rotate(359.999);
- non_rectilinear_trans[1].Rotate(0.0000001);
- non_rectilinear_trans[2].Rotate(89.999999);
- non_rectilinear_trans[3].Rotate(90.0000001);
- non_rectilinear_trans[4].Rotate(179.999999);
- non_rectilinear_trans[5].Rotate(180.0000001);
- non_rectilinear_trans[6].Rotate(269.999999);
- non_rectilinear_trans[7].Rotate(270.0000001);
- non_rectilinear_trans[8].SkewX(0.00001);
- non_rectilinear_trans[9].SkewY(0.00001);
+ non_rectilinear_trans[0].Rotate(359.9999f);
+ non_rectilinear_trans[1].Rotate(0.0000001f);
+ non_rectilinear_trans[2].Rotate(89.9999f);
+ non_rectilinear_trans[3].Rotate(90.00001f);
+ non_rectilinear_trans[4].Rotate(179.9999f);
+ 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);
for (int i = 0; i < kNumNonRectilinear; ++i) {
bool clipped = false;
diff --git a/chromium/cc/base/invalidation_region.cc b/chromium/cc/base/invalidation_region.cc
index 2c39d25ba06..6a8f97f78fe 100644
--- a/chromium/cc/base/invalidation_region.cc
+++ b/chromium/cc/base/invalidation_region.cc
@@ -19,14 +19,6 @@ InvalidationRegion::InvalidationRegion() {}
InvalidationRegion::~InvalidationRegion() {}
void InvalidationRegion::Swap(Region* region) {
- UMA_HISTOGRAM_CUSTOM_COUNTS(
- "Renderer4.InvalidationRegionApproximateRectCount",
- region_.GetRegionComplexity(),
- 1,
- 5000,
- 50);
-
- SimplifyIfNeeded();
region_.Swap(region);
}
@@ -35,9 +27,8 @@ void InvalidationRegion::Clear() {
}
void InvalidationRegion::Union(gfx::Rect rect) {
- // TODO(vmpstr): We should simplify the region after Union() after we get a
- // good idea of what kind of regions are typical (from the UMA histogram).
region_.Union(rect);
+ SimplifyIfNeeded();
}
void InvalidationRegion::SimplifyIfNeeded() {
diff --git a/chromium/cc/base/invalidation_region.h b/chromium/cc/base/invalidation_region.h
index fd061e8cba3..33be80332ff 100644
--- a/chromium/cc/base/invalidation_region.h
+++ b/chromium/cc/base/invalidation_region.h
@@ -22,6 +22,7 @@ class CC_EXPORT InvalidationRegion {
void Swap(Region* region);
void Clear();
void Union(gfx::Rect rect);
+ bool IsEmpty() const { return region_.IsEmpty(); }
private:
void SimplifyIfNeeded();
diff --git a/chromium/cc/base/latency_info_swap_promise.cc b/chromium/cc/base/latency_info_swap_promise.cc
new file mode 100644
index 00000000000..41c0e997d11
--- /dev/null
+++ b/chromium/cc/base/latency_info_swap_promise.cc
@@ -0,0 +1,50 @@
+// 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/base/latency_info_swap_promise.h"
+
+#include "base/logging.h"
+
+namespace {
+ ui::LatencyComponentType DidNotSwapReasonToLatencyComponentType(
+ cc::SwapPromise::DidNotSwapReason reason) {
+ switch (reason) {
+ case cc::SwapPromise::DID_NOT_SWAP_UNKNOWN:
+ case cc::SwapPromise::SWAP_FAILS:
+ return ui::INPUT_EVENT_LATENCY_TERMINATED_SWAP_FAILED_COMPONENT;
+ case cc::SwapPromise::COMMIT_FAILS:
+ return ui::INPUT_EVENT_LATENCY_TERMINATED_COMMIT_FAILED_COMPONENT;
+ case cc::SwapPromise::SWAP_PROMISE_LIST_OVERFLOW:
+ return ui::LATENCY_INFO_LIST_TERMINATED_OVERFLOW_COMPONENT;
+ }
+ NOTREACHED() << "Unhandled DidNotSwapReason.";
+ return ui::INPUT_EVENT_LATENCY_TERMINATED_SWAP_FAILED_COMPONENT;
+ }
+} // namespace
+
+namespace cc {
+
+LatencyInfoSwapPromise::LatencyInfoSwapPromise(const ui::LatencyInfo& latency)
+ : latency_(latency) {
+}
+
+LatencyInfoSwapPromise::~LatencyInfoSwapPromise() {
+}
+
+void LatencyInfoSwapPromise::DidSwap(CompositorFrameMetadata* metadata) {
+ DCHECK(!latency_.terminated);
+ // TODO(miletus): Append the |latency_| into metadata's LatencyInfo list
+ // once we remove LatencyInfo merge in GPU side.
+ metadata->latency_info.MergeWith(latency_);
+}
+
+void LatencyInfoSwapPromise::DidNotSwap(DidNotSwapReason reason) {
+ latency_.AddLatencyNumber(DidNotSwapReasonToLatencyComponentType(reason),
+ 0, 0);
+ // TODO(miletus): Turn this back on once per-event LatencyInfo tracking
+ // is enabled in GPU side.
+ // DCHECK(latency_.terminated);
+}
+
+} // namespace cc
diff --git a/chromium/cc/base/latency_info_swap_promise.h b/chromium/cc/base/latency_info_swap_promise.h
new file mode 100644
index 00000000000..1a2b1d6b206
--- /dev/null
+++ b/chromium/cc/base/latency_info_swap_promise.h
@@ -0,0 +1,28 @@
+// 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_BASE_LATENCY_INFO_SWAP_PROMISE_H_
+#define CC_BASE_LATENCY_INFO_SWAP_PROMISE_H_
+
+#include "base/compiler_specific.h"
+#include "cc/base/swap_promise.h"
+#include "ui/events/latency_info.h"
+
+namespace cc {
+
+class CC_EXPORT LatencyInfoSwapPromise : public SwapPromise {
+ public:
+ explicit LatencyInfoSwapPromise(const ui::LatencyInfo& latency_info);
+ virtual ~LatencyInfoSwapPromise();
+
+ virtual void DidSwap(CompositorFrameMetadata* metadata) OVERRIDE;
+ virtual void DidNotSwap(DidNotSwapReason reason) OVERRIDE;
+
+ private:
+ ui::LatencyInfo latency_;
+};
+
+} // namespace cc
+
+#endif // CC_BASE_LATENCY_INFO_SWAP_PROMISE_H_
diff --git a/chromium/cc/base/latency_info_swap_promise_monitor.cc b/chromium/cc/base/latency_info_swap_promise_monitor.cc
new file mode 100644
index 00000000000..0f2ff7481bb
--- /dev/null
+++ b/chromium/cc/base/latency_info_swap_promise_monitor.cc
@@ -0,0 +1,43 @@
+// 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/base/latency_info_swap_promise_monitor.h"
+
+#include "cc/base/latency_info_swap_promise.h"
+#include "cc/trees/layer_tree_host.h"
+#include "cc/trees/layer_tree_host_impl.h"
+#include "cc/trees/layer_tree_impl.h"
+
+namespace cc {
+
+LatencyInfoSwapPromiseMonitor::LatencyInfoSwapPromiseMonitor(
+ ui::LatencyInfo* latency,
+ LayerTreeHost* layer_tree_host,
+ LayerTreeHostImpl* layer_tree_host_impl)
+ : SwapPromiseMonitor(layer_tree_host, layer_tree_host_impl),
+ latency_(latency) {}
+
+LatencyInfoSwapPromiseMonitor::~LatencyInfoSwapPromiseMonitor() {}
+
+void LatencyInfoSwapPromiseMonitor::OnSetNeedsCommitOnMain() {
+ if (!latency_->FindLatency(
+ ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_COMPONENT, 0, 0)) {
+ latency_->AddLatencyNumber(
+ ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_COMPONENT, 0, 0);
+ scoped_ptr<SwapPromise> swap_promise(new LatencyInfoSwapPromise(*latency_));
+ layer_tree_host_->QueueSwapPromise(swap_promise.Pass());
+ }
+}
+
+void LatencyInfoSwapPromiseMonitor::OnSetNeedsRedrawOnImpl() {
+ if (!latency_->FindLatency(
+ ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_COMPONENT, 0, 0)) {
+ latency_->AddLatencyNumber(
+ ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_COMPONENT, 0, 0);
+ scoped_ptr<SwapPromise> swap_promise(new LatencyInfoSwapPromise(*latency_));
+ layer_tree_host_impl_->active_tree()->QueueSwapPromise(swap_promise.Pass());
+ }
+}
+
+} // namespace cc
diff --git a/chromium/cc/base/latency_info_swap_promise_monitor.h b/chromium/cc/base/latency_info_swap_promise_monitor.h
new file mode 100644
index 00000000000..a463fdbeeff
--- /dev/null
+++ b/chromium/cc/base/latency_info_swap_promise_monitor.h
@@ -0,0 +1,36 @@
+// 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/compiler_specific.h"
+#include "cc/base/swap_promise_monitor.h"
+
+#ifndef CC_BASE_LATENCY_INFO_SWAP_PROMISE_MONITOR_H_
+#define CC_BASE_LATENCY_INFO_SWAP_PROMISE_MONITOR_H_
+
+namespace ui {
+struct LatencyInfo;
+} // namespace ui
+
+namespace cc {
+
+// A LatencyInfoSwapPromiseMonitor queues a LatencyInfoSwapPromise into
+// LayerTreeHost or LayerTreeHostImpl if there is compositor state change
+// while it is being mointored.
+class CC_EXPORT LatencyInfoSwapPromiseMonitor : public SwapPromiseMonitor {
+ public:
+ LatencyInfoSwapPromiseMonitor(ui::LatencyInfo* latency,
+ LayerTreeHost* layer_tree_host,
+ LayerTreeHostImpl* layer_tree_host_impl);
+ virtual ~LatencyInfoSwapPromiseMonitor();
+
+ virtual void OnSetNeedsCommitOnMain() OVERRIDE;
+ virtual void OnSetNeedsRedrawOnImpl() OVERRIDE;
+
+ private:
+ ui::LatencyInfo* latency_;
+};
+
+} // namespace cc
+
+#endif // CC_BASE_LATENCY_INFO_SWAP_PROMISE_MONITOR_H_
diff --git a/chromium/cc/base/math_util.cc b/chromium/cc/base/math_util.cc
index 40b8d11c68c..7a1bc1a8674 100644
--- a/chromium/cc/base/math_util.cc
+++ b/chromium/cc/base/math_util.cc
@@ -72,13 +72,13 @@ static HomogeneousCoordinate ComputeClippedPointForEdge(
// w plane when this is called.
DCHECK(h1.ShouldBeClipped() ^ h2.ShouldBeClipped());
- SkMScalar w = 0.00001; // or any positive non-zero small epsilon
-
+ // ...or any positive non-zero small epsilon
+ SkMScalar w = 0.00001f;
SkMScalar t = (w - h1.w()) / (h2.w() - h1.w());
- SkMScalar x = (1 - t) * h1.x() + t * h2.x();
- SkMScalar y = (1 - t) * h1.y() + t * h2.y();
- SkMScalar z = (1 - t) * h1.z() + t * h2.z();
+ SkMScalar x = (SK_MScalar1 - t) * h1.x() + t * h2.x();
+ SkMScalar y = (SK_MScalar1 - t) * h1.y() + t * h2.y();
+ SkMScalar z = (SK_MScalar1 - t) * h1.z() + t * h2.z();
return HomogeneousCoordinate(x, y, z, w);
}
@@ -466,6 +466,13 @@ gfx::RectF MathUtil::ScaleRectProportional(const gfx::RectF& input_outer_rect,
}
static inline float ScaleOnAxis(double a, double b, double c) {
+ if (!b && !c)
+ return a;
+ if (!a && !c)
+ return b;
+ if (!a && !b)
+ return c;
+
// Do the sqrt as a double to not lose precision.
return static_cast<float>(std::sqrt(a * a + b * b + c * c));
}
@@ -583,6 +590,17 @@ scoped_ptr<base::Value> MathUtil::AsValue(const gfx::Transform& transform) {
return res.PassAs<base::Value>();
}
+scoped_ptr<base::Value> MathUtil::AsValue(const gfx::BoxF& box) {
+ scoped_ptr<base::ListValue> res(new base::ListValue());
+ res->AppendInteger(box.x());
+ res->AppendInteger(box.y());
+ res->AppendInteger(box.z());
+ res->AppendInteger(box.width());
+ res->AppendInteger(box.height());
+ res->AppendInteger(box.depth());
+ return res.PassAs<base::Value>();
+}
+
scoped_ptr<base::Value> MathUtil::AsValueSafely(double value) {
return scoped_ptr<base::Value>(base::Value::CreateDoubleValue(
std::min(value, std::numeric_limits<double>::max())));
diff --git a/chromium/cc/base/math_util.h b/chromium/cc/base/math_util.h
index 7912f8a8a25..baceb7058fe 100644
--- a/chromium/cc/base/math_util.h
+++ b/chromium/cc/base/math_util.h
@@ -11,6 +11,7 @@
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "cc/base/cc_export.h"
+#include "ui/gfx/box_f.h"
#include "ui/gfx/point3_f.h"
#include "ui/gfx/point_f.h"
#include "ui/gfx/size.h"
@@ -39,24 +40,24 @@ struct HomogeneousCoordinate {
bool ShouldBeClipped() const { return w() <= 0.0; }
gfx::PointF CartesianPoint2d() const {
- if (w() == 1.0)
+ if (w() == SK_MScalar1)
return gfx::PointF(x(), y());
// For now, because this code is used privately only by MathUtil, it should
// never be called when w == 0, and we do not yet need to handle that case.
DCHECK(w());
- SkMScalar inv_w = 1.0 / w();
+ SkMScalar inv_w = SK_MScalar1 / w();
return gfx::PointF(x() * inv_w, y() * inv_w);
}
gfx::Point3F CartesianPoint3d() const {
- if (w() == 1)
+ if (w() == SK_MScalar1)
return gfx::Point3F(x(), y(), z());
// For now, because this code is used privately only by MathUtil, it should
// never be called when w == 0, and we do not yet need to handle that case.
DCHECK(w());
- SkMScalar inv_w = 1.0 / w();
+ SkMScalar inv_w = SK_MScalar1 / w();
return gfx::Point3F(x() * inv_w, y() * inv_w, z() * inv_w);
}
@@ -172,6 +173,7 @@ class CC_EXPORT MathUtil {
static scoped_ptr<base::Value> AsValue(const gfx::QuadF& q);
static scoped_ptr<base::Value> AsValue(const gfx::RectF& rect);
static scoped_ptr<base::Value> AsValue(const gfx::Transform& transform);
+ static scoped_ptr<base::Value> AsValue(const gfx::BoxF& box);
// Returns a base::Value representation of the floating point value.
// If the value is inf, returns max double/float representation.
diff --git a/chromium/cc/base/math_util_unittest.cc b/chromium/cc/base/math_util_unittest.cc
index d62280ddb5f..6e276c25d64 100644
--- a/chromium/cc/base/math_util_unittest.cc
+++ b/chromium/cc/base/math_util_unittest.cc
@@ -22,7 +22,7 @@ TEST(MathUtilTest, ProjectionOfPerpendicularPlane) {
gfx::Transform transform;
transform.MakeIdentity();
- transform.matrix().setDouble(2, 2, 0);
+ transform.matrix().set(2, 2, 0);
gfx::RectF rect = gfx::RectF(0, 0, 1, 1);
gfx::RectF projected_rect = MathUtil::ProjectClippedRect(transform, rect);
@@ -44,8 +44,10 @@ TEST(MathUtilTest, EnclosingClippedRectUsesCorrectInitialBounds) {
// then the enclosing clipped rect will be computed incorrectly.
gfx::RectF result = MathUtil::ComputeEnclosingClippedRect(h1, h2, h3, h4);
- EXPECT_FLOAT_RECT_EQ(gfx::RectF(gfx::PointF(-100, -100), gfx::SizeF(90, 90)),
- result);
+ // Due to floating point math in ComputeClippedPointForEdge this result
+ // is fairly imprecise. 0.15f was empirically determined.
+ EXPECT_RECT_NEAR(
+ gfx::RectF(gfx::PointF(-100, -100), gfx::SizeF(90, 90)), result, 0.15f);
}
TEST(MathUtilTest, EnclosingRectOfVerticesUsesCorrectInitialBounds) {
diff --git a/chromium/cc/base/ref_counted_managed.h b/chromium/cc/base/ref_counted_managed.h
new file mode 100644
index 00000000000..8bb836f0159
--- /dev/null
+++ b/chromium/cc/base/ref_counted_managed.h
@@ -0,0 +1,65 @@
+// 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_BASE_REF_COUNTED_MANAGED_H_
+#define CC_BASE_REF_COUNTED_MANAGED_H_
+
+#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+#include "cc/base/cc_export.h"
+
+namespace cc {
+
+template <typename T> class RefCountedManaged;
+
+template <typename T>
+class CC_EXPORT RefCountedManager {
+ protected:
+ RefCountedManager() : live_object_count_(0) {}
+ ~RefCountedManager() {
+ CHECK_EQ(0, live_object_count_);
+ }
+
+ virtual void Release(T* object) = 0;
+
+ private:
+ friend class RefCountedManaged<T>;
+ int live_object_count_;
+};
+
+template <typename T>
+class CC_EXPORT RefCountedManaged : public base::subtle::RefCountedBase {
+ public:
+ explicit RefCountedManaged(RefCountedManager<T>* manager)
+ : manager_(manager) {
+ manager_->live_object_count_++;
+ }
+
+ void AddRef() const {
+ base::subtle::RefCountedBase::AddRef();
+ }
+
+ void Release() {
+ if (base::subtle::RefCountedBase::Release()) {
+ DCHECK_GT(manager_->live_object_count_, 0);
+ manager_->live_object_count_--;
+
+ // This must be the last statement in case manager deletes
+ // the object immediately.
+ manager_->Release(static_cast<T*>(this));
+ }
+ }
+
+ protected:
+ ~RefCountedManaged() {}
+
+ private:
+ RefCountedManager<T>* manager_;
+
+ DISALLOW_COPY_AND_ASSIGN(RefCountedManaged<T>);
+};
+
+} // namespace cc
+
+#endif // CC_BASE_REF_COUNTED_MANAGED_H_
diff --git a/chromium/cc/base/scoped_ptr_vector.h b/chromium/cc/base/scoped_ptr_vector.h
index 856e2f51cd1..288cb6fa47b 100644
--- a/chromium/cc/base/scoped_ptr_vector.h
+++ b/chromium/cc/base/scoped_ptr_vector.h
@@ -140,6 +140,13 @@ class ScopedPtrVector {
data_.insert(position, tmp_data.begin(), tmp_data.end());
}
+ template <typename Predicate>
+ iterator partition(Predicate predicate) {
+ typename std::vector<T*>::iterator first = begin();
+ typename std::vector<T*>::iterator last = end();
+ return static_cast<iterator>(std::partition(first, last, predicate));
+ }
+
void swap(ScopedPtrVector<T>& other) {
data_.swap(other.data_);
}
diff --git a/chromium/cc/base/scoped_ptr_vector_unittest.cc b/chromium/cc/base/scoped_ptr_vector_unittest.cc
index 4e450b9c823..8190b37b83b 100644
--- a/chromium/cc/base/scoped_ptr_vector_unittest.cc
+++ b/chromium/cc/base/scoped_ptr_vector_unittest.cc
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <set>
+
#include "cc/base/scoped_ptr_vector.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -17,6 +19,11 @@ class Data {
int data_;
};
+class IsOddPredicate {
+ public:
+ bool operator()(const Data* data) { return (data->data() % 2) == 1; }
+};
+
TEST(ScopedPtrVectorTest, PushBack) {
ScopedPtrVector<Data> v;
@@ -68,5 +75,31 @@ TEST(ScopedPtrVectorTest, InsertAndTake) {
EXPECT_EQ(NULL, v2[2]);
}
+TEST(ScopedPtrVectorTest, Partition) {
+ ScopedPtrVector<Data> v;
+ v.push_back(Data::Create(1));
+ v.push_back(Data::Create(2));
+ v.push_back(Data::Create(3));
+ v.push_back(Data::Create(4));
+ v.push_back(Data::Create(5));
+
+ ScopedPtrVector<Data>::iterator it = v.partition(IsOddPredicate());
+ std::set<int> odd_numbers;
+ for (ScopedPtrVector<Data>::iterator second_it = v.begin();
+ second_it != it;
+ ++second_it) {
+ EXPECT_EQ(1, (*second_it)->data() % 2);
+ odd_numbers.insert((*second_it)->data());
+ }
+ EXPECT_EQ(3u, odd_numbers.size());
+
+ std::set<int> even_numbers;
+ for (; it != v.end(); ++it) {
+ EXPECT_EQ(0, (*it)->data() % 2);
+ even_numbers.insert((*it)->data());
+ }
+ EXPECT_EQ(2u, even_numbers.size());
+}
+
} // namespace
} // namespace cc
diff --git a/chromium/cc/base/swap_promise.h b/chromium/cc/base/swap_promise.h
new file mode 100644
index 00000000000..36a5b130a50
--- /dev/null
+++ b/chromium/cc/base/swap_promise.h
@@ -0,0 +1,50 @@
+// 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_BASE_SWAP_PROMISE_H_
+#define CC_BASE_SWAP_PROMISE_H_
+
+#include "cc/output/compositor_frame_metadata.h"
+
+namespace cc {
+
+const unsigned int kMaxQueuedSwapPromiseNumber = 100;
+
+// When a change to the compositor's state/invalidation/whatever happens, a
+// Swap Promise can be inserted into LayerTreeHost/LayerTreeImpl, to track
+// whether the compositor's reply to the new state/invaliadtion/whatever is
+// completed in the compositor, i.e. the compositor knows it has been sent
+// to its output or not.
+//
+// If the new compositor state is sent to the output, SwapPromise::DidSwap()
+// will be called, and if the compositor fails to send its new state to the
+// output, SwapPromise::DidNotSwap() will be called.
+//
+// Client wishes to use SwapPromise should have a subclass that defines
+// the behavior of DidSwap() and DidNotSwap(). Notice that the promise can
+// be broken at either main or impl thread, e.g. commit fails on main thread,
+// new frame data has no actual damage so LayerTreeHostImpl::SwapBuffers()
+// bails out early on impl thread, so don't assume that DidSwap() and
+// DidNotSwap() are called at a particular thread. It is better to let the
+// subclass carry thread-safe member data and operate on that member data in
+// DidSwap() and DidNotSwap().
+class CC_EXPORT SwapPromise {
+ public:
+ enum DidNotSwapReason {
+ DID_NOT_SWAP_UNKNOWN,
+ SWAP_FAILS,
+ COMMIT_FAILS,
+ SWAP_PROMISE_LIST_OVERFLOW,
+ };
+
+ SwapPromise() {}
+ virtual ~SwapPromise() {}
+
+ virtual void DidSwap(CompositorFrameMetadata* metadata) = 0;
+ virtual void DidNotSwap(DidNotSwapReason reason) = 0;
+};
+
+} // namespace cc
+
+#endif // CC_BASE_SWAP_PROMISE_H_
diff --git a/chromium/cc/base/swap_promise_monitor.cc b/chromium/cc/base/swap_promise_monitor.cc
new file mode 100644
index 00000000000..0c04f35ebc4
--- /dev/null
+++ b/chromium/cc/base/swap_promise_monitor.cc
@@ -0,0 +1,31 @@
+// 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/logging.h"
+#include "cc/base/swap_promise_monitor.h"
+#include "cc/trees/layer_tree_host.h"
+#include "cc/trees/layer_tree_host_impl.h"
+
+namespace cc {
+
+SwapPromiseMonitor::SwapPromiseMonitor(LayerTreeHost* layer_tree_host,
+ LayerTreeHostImpl* layer_tree_host_impl)
+ : layer_tree_host_(layer_tree_host),
+ layer_tree_host_impl_(layer_tree_host_impl) {
+ DCHECK((layer_tree_host && !layer_tree_host_impl) ||
+ (!layer_tree_host && layer_tree_host_impl));
+ if (layer_tree_host_)
+ layer_tree_host_->InsertSwapPromiseMonitor(this);
+ if (layer_tree_host_impl_)
+ layer_tree_host_impl_->InsertSwapPromiseMonitor(this);
+}
+
+SwapPromiseMonitor::~SwapPromiseMonitor() {
+ if (layer_tree_host_)
+ layer_tree_host_->RemoveSwapPromiseMonitor(this);
+ if (layer_tree_host_impl_)
+ layer_tree_host_impl_->RemoveSwapPromiseMonitor(this);
+}
+
+} // namespace cc
diff --git a/chromium/cc/base/swap_promise_monitor.h b/chromium/cc/base/swap_promise_monitor.h
new file mode 100644
index 00000000000..21a159ad32a
--- /dev/null
+++ b/chromium/cc/base/swap_promise_monitor.h
@@ -0,0 +1,44 @@
+// 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_BASE_SWAP_PROMISE_MONITOR_H_
+#define CC_BASE_SWAP_PROMISE_MONITOR_H_
+
+#include "cc/base/cc_export.h"
+
+namespace cc {
+
+class LayerTreeHost;
+class LayerTreeHostImpl;
+
+// A SwapPromiseMonitor is used to monitor compositor state change that
+// should be associated with a SwapPromise, e.g. SetNeedsCommit() is
+// called on main thread or SetNeedsRedraw() is called on impl thread.
+// Creating a SwapPromiseMonitor will insert itself into a LayerTreeHost
+// or LayerTreeHostImpl. You must provide a pointer to the appropriate
+// structure to the monitor (and only one of the two). Notification of
+// compositor state change will be sent through OnSetNeedsCommitOnMain()
+// or OnSetNeedsRedrawOnImpl(). When SwapPromiseMonitor is destroyed, it
+// will unregister itself from LayerTreeHost or LayerTreeHostImpl.
+class CC_EXPORT SwapPromiseMonitor {
+ public:
+ // If the monitor lives on the main thread, pass in layer_tree_host
+ // and set layer_tree_host_impl to NULL.
+ // If the monitor lives on the impl thread, pass in layer_tree_host_impl
+ // and set layer_tree_host to NULL.
+ SwapPromiseMonitor(LayerTreeHost* layer_tree_host,
+ LayerTreeHostImpl* layer_tree_host_impl);
+ virtual ~SwapPromiseMonitor();
+
+ virtual void OnSetNeedsCommitOnMain() = 0;
+ virtual void OnSetNeedsRedrawOnImpl() = 0;
+
+ protected:
+ LayerTreeHost* layer_tree_host_;
+ LayerTreeHostImpl* layer_tree_host_impl_;
+};
+
+} // namespace cc
+
+#endif // CC_BASE_SWAP_PROMISE_MONITOR_H_
diff --git a/chromium/cc/base/switches.cc b/chromium/cc/base/switches.cc
index 87e10ce0089..ddba9cbd444 100644
--- a/chromium/cc/base/switches.cc
+++ b/chromium/cc/base/switches.cc
@@ -36,10 +36,10 @@ const char kEnableImplSidePainting[] = "enable-impl-side-painting";
const char kEnableTopControlsPositionCalculation[] =
"enable-top-controls-position-calculation";
-// For any layers that can get drawn directly to screen, draw them with the Skia
-// GPU backend. Only valid with gl rendering + threaded compositing + impl-side
-// painting.
-const char kForceDirectLayerDrawing[] = "force-direct-layer-drawing";
+// Allow heuristics to determine when a layer tile should be drawn with
+// the Skia GPU backend. Only valid with GPU accelerated compositing +
+// impl-side painting.
+const char kEnableGPURasterization[] = "enable-gpu-rasterization";
// The height of the movable top controls.
const char kTopControlsHeight[] = "top-controls-height";
@@ -62,10 +62,6 @@ const char kTraceOverdraw[] = "trace-overdraw";
// complete, such as --slow-down-raster-scale-factor=25.
const char kSlowDownRasterScaleFactor[] = "slow-down-raster-scale-factor";
-// The scale factor for low resolution tile contents.
-const char kLowResolutionContentsScaleFactor[] =
- "low-resolution-contents-scale-factor";
-
// Max tiles allowed for each tilings interest area.
const char kMaxTilesForInterestArea[] = "max-tiles-for-interest-area";
@@ -101,6 +97,10 @@ const char kUIShowCompositedLayerBorders[] = "ui-show-layer-borders";
const char kShowFPSCounter[] = "show-fps-counter";
const char kUIShowFPSCounter[] = "ui-show-fps-counter";
+// Renders a border that represents the bounding box for the layer's animation.
+const char kShowLayerAnimationBounds[] = "show-layer-animation-bounds";
+const char kUIShowLayerAnimationBounds[] = "ui-show-layer-animation-bounds";
+
// Show rects in the HUD around layers whose properties have changed.
const char kShowPropertyChangedRects[] = "show-property-changed-rects";
const char kUIShowPropertyChangedRects[] = "ui-show-property-changed-rects";
@@ -141,14 +141,21 @@ const char kDisableMapImage[] = "disable-map-image";
// Prevents the layer tree unit tests from timing out.
const char kCCLayerTreeTestNoTimeout[] = "cc-layer-tree-test-no-timeout";
+// Makes pixel tests write their output instead of read it.
+const char kCCRebaselinePixeltests[] = "cc-rebaseline-pixeltests";
+
// Disable textures using RGBA_4444 layout.
const char kDisable4444Textures[] = "disable-4444-textures";
+// Disable touch hit testing in the compositor.
+const char kDisableCompositorTouchHitTesting[] =
+ "disable-compositor-touch-hit-testing";
+
bool IsLCDTextEnabled() {
const CommandLine* command_line = CommandLine::ForCurrentProcess();
- if (command_line->HasSwitch(cc::switches::kDisableLCDText))
+ if (command_line->HasSwitch(switches::kDisableLCDText))
return false;
- else if (command_line->HasSwitch(cc::switches::kEnableLCDText))
+ else if (command_line->HasSwitch(switches::kEnableLCDText))
return true;
#if defined(OS_ANDROID)
@@ -158,12 +165,13 @@ bool IsLCDTextEnabled() {
#endif
}
-bool IsImplSidePaintingEnabled() {
+namespace {
+bool CheckImplSidePaintingStatus() {
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
- if (command_line.HasSwitch(cc::switches::kDisableImplSidePainting))
+ if (command_line.HasSwitch(switches::kDisableImplSidePainting))
return false;
- else if (command_line.HasSwitch(cc::switches::kEnableImplSidePainting))
+ else if (command_line.HasSwitch(switches::kEnableImplSidePainting))
return true;
#if defined(OS_ANDROID)
@@ -173,12 +181,29 @@ bool IsImplSidePaintingEnabled() {
#endif
}
+bool CheckGPURasterizationStatus() {
+ const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ return command_line.HasSwitch(switches::kEnableGPURasterization);
+}
+
+} // namespace
+
+bool IsImplSidePaintingEnabled() {
+ static bool enabled = CheckImplSidePaintingStatus();
+ return enabled;
+}
+
+bool IsGPURasterizationEnabled() {
+ static bool enabled = CheckGPURasterizationStatus();
+ return enabled;
+}
+
bool IsMapImageEnabled() {
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
- if (command_line.HasSwitch(cc::switches::kDisableMapImage))
+ if (command_line.HasSwitch(switches::kDisableMapImage))
return false;
- else if (command_line.HasSwitch(cc::switches::kEnableMapImage))
+ else if (command_line.HasSwitch(switches::kEnableMapImage))
return true;
return false;
diff --git a/chromium/cc/base/switches.h b/chromium/cc/base/switches.h
index 97fe833390c..19cba57bb98 100644
--- a/chromium/cc/base/switches.h
+++ b/chromium/cc/base/switches.h
@@ -24,7 +24,7 @@ CC_EXPORT extern const char kDisableCompositedAntialiasing[];
CC_EXPORT extern const char kEnableLCDText[];
CC_EXPORT extern const char kEnableImplSidePainting[];
CC_EXPORT extern const char kEnableTopControlsPositionCalculation[];
-CC_EXPORT extern const char kForceDirectLayerDrawing[];
+CC_EXPORT extern const char kEnableGPURasterization[];
CC_EXPORT extern const char kJankInsteadOfCheckerboard[];
CC_EXPORT extern const char kNumRasterThreads[];
CC_EXPORT extern const char kTopControlsHeight[];
@@ -32,7 +32,6 @@ CC_EXPORT extern const char kTopControlsHideThreshold[];
CC_EXPORT extern const char kTraceOverdraw[];
CC_EXPORT extern const char kTopControlsShowThreshold[];
CC_EXPORT extern const char kSlowDownRasterScaleFactor[];
-CC_EXPORT extern const char kLowResolutionContentsScaleFactor[];
CC_EXPORT extern const char kCompositeToMailbox[];
CC_EXPORT extern const char kMaxTilesForInterestArea[];
CC_EXPORT extern const char kMaxUnusedResourceMemoryUsagePercentage[];
@@ -42,6 +41,7 @@ CC_EXPORT extern const char kStrictLayerPropertyChangeChecking[];
CC_EXPORT extern const char kEnableMapImage[];
CC_EXPORT extern const char kDisableMapImage[];
CC_EXPORT extern const char kDisable4444Textures[];
+CC_EXPORT extern const char kDisableCompositorTouchHitTesting[];
// Switches for both the renderer and ui compositors.
CC_EXPORT extern const char kUIDisablePartialSwap[];
@@ -53,6 +53,8 @@ CC_EXPORT extern const char kShowCompositedLayerBorders[];
CC_EXPORT extern const char kUIShowCompositedLayerBorders[];
CC_EXPORT extern const char kShowFPSCounter[];
CC_EXPORT extern const char kUIShowFPSCounter[];
+CC_EXPORT extern const char kShowLayerAnimationBounds[];
+CC_EXPORT extern const char kUIShowLayerAnimationBounds[];
CC_EXPORT extern const char kShowPropertyChangedRects[];
CC_EXPORT extern const char kUIShowPropertyChangedRects[];
CC_EXPORT extern const char kShowSurfaceDamageRects[];
@@ -68,9 +70,11 @@ CC_EXPORT extern const char kUIShowNonOccludingRects[];
// Unit test related.
CC_EXPORT extern const char kCCLayerTreeTestNoTimeout[];
+CC_EXPORT extern const char kCCRebaselinePixeltests[];
CC_EXPORT bool IsLCDTextEnabled();
CC_EXPORT bool IsImplSidePaintingEnabled();
+CC_EXPORT bool IsGPURasterizationEnabled();
CC_EXPORT bool IsMapImageEnabled();
} // namespace switches
diff --git a/chromium/cc/base/util.h b/chromium/cc/base/util.h
index 1d716ae2a42..bd511786dca 100644
--- a/chromium/cc/base/util.h
+++ b/chromium/cc/base/util.h
@@ -8,6 +8,9 @@
#include <limits>
#include "base/basictypes.h"
+#include "cc/resources/resource_provider.h"
+#include "third_party/khronos/GLES2/gl2.h"
+#include "third_party/khronos/GLES2/gl2ext.h"
namespace cc {
@@ -24,6 +27,36 @@ template <typename T> T RoundDown(T n, T mul) {
: ((n - mul + 1) / mul) * mul;
}
+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, // LUMINANCE_8
+ GL_UNSIGNED_SHORT_5_6_5, // RGB_565,
+ GL_UNSIGNED_BYTE // ETC1
+ };
+ 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_LUMINANCE, // LUMINANCE_8
+ GL_RGB, // RGB_565
+ GL_ETC1_RGB8_OES // ETC1
+ };
+ return format_gl_data_format[format];
+}
+
+inline GLenum GLInternalFormat(ResourceFormat format) {
+ return GLDataFormat(format);
+}
+
} // namespace cc
#endif // CC_BASE_UTIL_H_
diff --git a/chromium/cc/cc.gyp b/chromium/cc/cc.gyp
index ffc86153f29..7af063df2a6 100644
--- a/chromium/cc/cc.gyp
+++ b/chromium/cc/cc.gyp
@@ -17,8 +17,9 @@
'<(DEPTH)/media/media.gyp:media',
'<(DEPTH)/skia/skia.gyp:skia',
'<(DEPTH)/third_party/WebKit/public/blink.gyp:blink_minimal',
+ '<(DEPTH)/ui/events/events.gyp:events_base',
+ '<(DEPTH)/ui/gfx/gfx.gyp:gfx',
'<(DEPTH)/ui/gl/gl.gyp:gl',
- '<(DEPTH)/ui/ui.gyp:ui',
],
'defines': [
'CC_IMPLEMENTATION=1',
@@ -41,6 +42,9 @@
'animation/layer_animation_controller.h',
'animation/layer_animation_event_observer.h',
'animation/layer_animation_value_observer.h',
+ 'animation/layer_animation_value_provider.h',
+ 'animation/scroll_offset_animation_curve.cc',
+ 'animation/scroll_offset_animation_curve.h',
'animation/scrollbar_animation_controller.h',
'animation/scrollbar_animation_controller_linear_fade.cc',
'animation/scrollbar_animation_controller_linear_fade.h',
@@ -55,46 +59,68 @@
'base/completion_event.h',
'base/invalidation_region.cc',
'base/invalidation_region.h',
+ 'base/latency_info_swap_promise.cc',
+ 'base/latency_info_swap_promise.h',
+ 'base/latency_info_swap_promise_monitor.cc',
+ 'base/latency_info_swap_promise_monitor.h',
'base/math_util.cc',
'base/math_util.h',
+ 'base/ref_counted_managed.h',
'base/region.cc',
'base/region.h',
'base/scoped_ptr_algorithm.h',
'base/scoped_ptr_deque.h',
'base/scoped_ptr_vector.h',
+ 'base/swap_promise.h',
+ 'base/swap_promise_monitor.cc',
+ 'base/swap_promise_monitor.h',
'base/switches.cc',
'base/switches.h',
'base/tiling_data.cc',
'base/tiling_data.h',
'base/util.h',
+ 'debug/benchmark_instrumentation.cc',
+ 'debug/benchmark_instrumentation.h',
'debug/debug_colors.cc',
'debug/debug_colors.h',
'debug/debug_rect_history.cc',
'debug/debug_rect_history.h',
'debug/devtools_instrumentation.h',
- 'debug/fake_web_graphics_context_3d.cc',
- 'debug/fake_web_graphics_context_3d.h',
'debug/frame_rate_counter.cc',
'debug/frame_rate_counter.h',
'debug/layer_tree_debug_state.cc',
'debug/layer_tree_debug_state.h',
+ 'debug/micro_benchmark.cc',
+ 'debug/micro_benchmark.h',
+ 'debug/micro_benchmark_impl.cc',
+ 'debug/micro_benchmark_impl.h',
+ 'debug/micro_benchmark_controller.cc',
+ 'debug/micro_benchmark_controller.h',
+ 'debug/micro_benchmark_controller_impl.cc',
+ 'debug/micro_benchmark_controller_impl.h',
'debug/overdraw_metrics.cc',
'debug/overdraw_metrics.h',
'debug/paint_time_counter.cc',
'debug/paint_time_counter.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',
+ 'debug/rasterize_and_record_benchmark_impl.h',
'debug/rendering_stats.cc',
'debug/rendering_stats.h',
'debug/rendering_stats_instrumentation.cc',
'debug/rendering_stats_instrumentation.h',
'debug/ring_buffer.h',
- 'debug/test_context_provider.cc',
- 'debug/test_context_provider.h',
- 'debug/test_web_graphics_context_3d.cc',
- 'debug/test_web_graphics_context_3d.h',
'debug/traced_picture.cc',
'debug/traced_picture.h',
'debug/traced_value.cc',
'debug/traced_value.h',
+ 'debug/unittest_only_benchmark.cc',
+ 'debug/unittest_only_benchmark.h',
+ 'debug/unittest_only_benchmark_impl.cc',
+ 'debug/unittest_only_benchmark_impl.h',
'input/input_handler.h',
'input/page_scale_animation.cc',
'input/page_scale_animation.h',
@@ -108,9 +134,12 @@
'layers/content_layer_client.h',
'layers/contents_scaling_layer.cc',
'layers/contents_scaling_layer.h',
+ 'layers/delegated_frame_provider.cc',
+ 'layers/delegated_frame_provider.h',
+ 'layers/delegated_frame_resource_collection.cc',
+ 'layers/delegated_frame_resource_collection.h',
'layers/delegated_renderer_layer.cc',
'layers/delegated_renderer_layer.h',
- 'layers/delegated_renderer_layer_client.h',
'layers/delegated_renderer_layer_impl.cc',
'layers/delegated_renderer_layer_impl.h',
'layers/draw_properties.h',
@@ -178,6 +207,10 @@
'layers/tiled_layer.h',
'layers/tiled_layer_impl.cc',
'layers/tiled_layer_impl.h',
+ 'layers/ui_resource_layer.cc',
+ 'layers/ui_resource_layer.h',
+ 'layers/ui_resource_layer_impl.cc',
+ 'layers/ui_resource_layer_impl.h',
'layers/video_frame_provider.h',
'layers/video_frame_provider_client_impl.cc',
'layers/video_frame_provider_client_impl.h',
@@ -272,6 +305,8 @@
'resources/caching_bitmap_content_layer_updater.h',
'resources/content_layer_updater.cc',
'resources/content_layer_updater.h',
+ 'resources/etc1_pixel_ref.cc',
+ 'resources/etc1_pixel_ref.h',
'resources/image_layer_updater.cc',
'resources/image_layer_updater.h',
'resources/image_raster_worker_pool.cc',
@@ -334,12 +369,13 @@
'resources/scoped_resource.h',
'resources/scoped_ui_resource.cc',
'resources/scoped_ui_resource.h',
+ 'resources/shared_bitmap.cc',
+ 'resources/shared_bitmap.h',
+ 'resources/shared_bitmap_manager.h',
'resources/single_release_callback.cc',
'resources/single_release_callback.h',
'resources/skpicture_content_layer_updater.cc',
'resources/skpicture_content_layer_updater.h',
- 'resources/sync_point_helper.cc',
- 'resources/sync_point_helper.h',
'resources/texture_mailbox.cc',
'resources/texture_mailbox.h',
'resources/texture_mailbox_deleter.cc',
@@ -355,6 +391,8 @@
'resources/ui_resource_bitmap.cc',
'resources/ui_resource_bitmap.h',
'resources/ui_resource_client.h',
+ 'resources/ui_resource_request.cc',
+ 'resources/ui_resource_request.h',
'resources/video_resource_updater.cc',
'resources/video_resource_updater.h',
'resources/worker_pool.cc',
@@ -363,8 +401,6 @@
'scheduler/delay_based_time_source.h',
'scheduler/frame_rate_controller.cc',
'scheduler/frame_rate_controller.h',
- 'scheduler/rate_limiter.cc',
- 'scheduler/rate_limiter.h',
'scheduler/rolling_time_delta_history.cc',
'scheduler/rolling_time_delta_history.h',
'scheduler/scheduler.cc',
diff --git a/chromium/cc/cc_tests.gyp b/chromium/cc/cc_tests.gyp
index f271a7074be..4974ad39e18 100644
--- a/chromium/cc/cc_tests.gyp
+++ b/chromium/cc/cc_tests.gyp
@@ -9,6 +9,7 @@
'animation/animation_unittest.cc',
'animation/keyframed_animation_curve_unittest.cc',
'animation/layer_animation_controller_unittest.cc',
+ 'animation/scroll_offset_animation_curve_unittest.cc',
'animation/scrollbar_animation_controller_linear_fade_unittest.cc',
'animation/scrollbar_animation_controller_thinning_unittest.cc',
'animation/timing_function_unittest.cc',
@@ -19,11 +20,15 @@
'base/scoped_ptr_vector_unittest.cc',
'base/tiling_data_unittest.cc',
'base/util_unittest.cc',
+ 'debug/micro_benchmark_controller_unittest.cc',
'input/top_controls_manager_unittest.cc',
'layers/content_layer_unittest.cc',
'layers/contents_scaling_layer_unittest.cc',
+ 'layers/delegated_frame_provider_unittest.cc',
+ 'layers/delegated_frame_resource_collection_unittest.cc',
'layers/delegated_renderer_layer_impl_unittest.cc',
'layers/heads_up_display_unittest.cc',
+ 'layers/heads_up_display_layer_impl_unittest.cc',
'layers/layer_impl_unittest.cc',
'layers/layer_iterator_unittest.cc',
'layers/layer_position_constraint_unittest.cc',
@@ -39,12 +44,13 @@
'layers/texture_layer_unittest.cc',
'layers/tiled_layer_impl_unittest.cc',
'layers/tiled_layer_unittest.cc',
+ 'layers/ui_resource_layer_impl_unittest.cc',
+ 'layers/ui_resource_layer_unittest.cc',
'output/delegating_renderer_unittest.cc',
'output/filter_operations_unittest.cc',
'output/gl_renderer_unittest.cc',
'output/output_surface_unittest.cc',
'output/renderer_pixeltest.cc',
- 'output/render_surface_filters_unittest.cc',
'output/shader_unittest.cc',
'output/software_renderer_unittest.cc',
'quads/draw_quad_unittest.cc',
@@ -72,18 +78,21 @@
'scheduler/scheduler_state_machine_unittest.cc',
'scheduler/scheduler_unittest.cc',
'scheduler/texture_uploader_unittest.cc',
- 'test/fake_web_graphics_context_3d_unittest.cc',
+ 'test/layer_tree_json_parser_unittest.cc',
+ 'test/test_web_graphics_context_3d_unittest.cc',
'trees/damage_tracker_unittest.cc',
'trees/layer_sorter_unittest.cc',
'trees/layer_tree_host_common_unittest.cc',
'trees/layer_tree_host_impl_unittest.cc',
+ 'trees/layer_tree_host_pixeltest_blending.cc',
'trees/layer_tree_host_pixeltest_filters.cc',
'trees/layer_tree_host_pixeltest_masks.cc',
'trees/layer_tree_host_pixeltest_on_demand_raster.cc',
'trees/layer_tree_host_pixeltest_readback.cc',
- 'trees/layer_tree_host_unittest_animation.cc',
'trees/layer_tree_host_unittest.cc',
+ 'trees/layer_tree_host_unittest_animation.cc',
'trees/layer_tree_host_unittest_context.cc',
+ 'trees/layer_tree_host_unittest_copyrequest.cc',
'trees/layer_tree_host_unittest_damage.cc',
'trees/layer_tree_host_unittest_delegated.cc',
'trees/layer_tree_host_unittest_occlusion.cc',
@@ -108,12 +117,18 @@
'test/fake_delegated_renderer_layer_impl.cc',
'test/fake_delegated_renderer_layer_impl.h',
'test/fake_impl_proxy.h',
+ 'test/fake_layer_tree_host.cc',
+ 'test/fake_layer_tree_host.h',
'test/fake_layer_tree_host_client.cc',
'test/fake_layer_tree_host_client.h',
'test/fake_layer_tree_host_impl.cc',
+ 'test/fake_layer_tree_host_impl.h',
'test/fake_layer_tree_host_impl_client.cc',
'test/fake_layer_tree_host_impl_client.h',
- 'test/fake_layer_tree_host_impl.h',
+ 'test/fake_output_surface.cc',
+ 'test/fake_output_surface.h',
+ 'test/fake_output_surface_client.cc',
+ 'test/fake_output_surface_client.h',
'test/fake_painted_scrollbar_layer.cc',
'test/fake_painted_scrollbar_layer.h',
'test/fake_picture_layer.cc',
@@ -127,54 +142,70 @@
'test/fake_proxy.cc',
'test/fake_proxy.h',
'test/fake_rendering_stats_instrumentation.h',
+ 'test/fake_scoped_ui_resource.cc',
+ 'test/fake_scoped_ui_resource.h',
'test/fake_scrollbar.cc',
'test/fake_scrollbar.h',
'test/fake_tile_manager.cc',
'test/fake_tile_manager.h',
- 'test/fake_tile_manager_client.h',
'test/fake_tile_manager_client.cc',
- 'test/fake_output_surface.cc',
- 'test/fake_output_surface.h',
- 'test/fake_output_surface_client.cc',
- 'test/fake_output_surface_client.h',
- 'test/fake_scoped_ui_resource.cc',
- 'test/fake_scoped_ui_resource.h',
+ 'test/fake_tile_manager_client.h',
+ 'test/fake_ui_resource_layer_tree_host_impl.cc',
+ 'test/fake_ui_resource_layer_tree_host_impl.h',
'test/fake_video_frame_provider.cc',
'test/fake_video_frame_provider.h',
+ 'test/fake_web_graphics_context_3d.cc',
+ 'test/fake_web_graphics_context_3d.h',
'test/geometry_test_utils.cc',
'test/geometry_test_utils.h',
'test/impl_side_painting_settings.h',
'test/layer_test_common.cc',
'test/layer_test_common.h',
+ 'test/layer_tree_json_parser.cc',
+ 'test/layer_tree_json_parser.h',
'test/layer_tree_pixel_test.cc',
'test/layer_tree_pixel_test.h',
'test/layer_tree_test.cc',
'test/layer_tree_test.h',
- 'test/layer_tree_json_parser.cc',
- 'test/layer_tree_json_parser.h',
'test/mock_quad_culler.cc',
'test/mock_quad_culler.h',
'test/occlusion_tracker_test_common.h',
+ 'test/ordered_texture_map.cc',
+ 'test/ordered_texture_map.h',
'test/paths.cc',
'test/paths.h',
+ 'test/pixel_comparator.cc',
+ 'test/pixel_comparator.h',
'test/pixel_test.cc',
'test/pixel_test.h',
'test/pixel_test_output_surface.cc',
'test/pixel_test_output_surface.h',
'test/pixel_test_software_output_device.cc',
'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',
'test/scheduler_test_common.h',
- 'test/solid_color_content_layer_client.h',
- 'test/solid_color_content_layer_client.cc',
'test/skia_common.cc',
'test/skia_common.h',
+ 'test/solid_color_content_layer_client.cc',
+ 'test/solid_color_content_layer_client.h',
+ 'test/test_context_provider.cc',
+ 'test/test_context_provider.h',
+ 'test/test_context_support.cc',
+ 'test/test_context_support.h',
+ 'test/test_gles2_interface.cc',
+ 'test/test_gles2_interface.h',
+ 'test/test_texture.cc',
+ 'test/test_texture.h',
'test/test_tile_priorities.cc',
'test/test_tile_priorities.h',
+ 'test/test_web_graphics_context_3d.cc',
+ 'test/test_web_graphics_context_3d.h',
'test/tiled_layer_test_common.cc',
'test/tiled_layer_test_common.h',
],
@@ -186,15 +217,16 @@
'dependencies': [
'../base/base.gyp:test_support_base',
'../gpu/gpu.gyp:gpu',
+ '../gpu/gpu.gyp:gpu_unittest_utils',
'../media/media.gyp:media',
'../skia/skia.gyp:skia',
'../testing/gmock.gyp:gmock',
'../testing/gtest.gyp:gtest',
- '../ui/ui.gyp:ui',
+ '../ui/events/events.gyp:events_base',
+ '../ui/gfx/gfx.gyp:gfx',
'../webkit/common/gpu/webkit_gpu.gyp:webkit_gpu',
'cc.gyp:cc',
'cc_test_support',
- 'cc_test_utils',
],
'sources': [
'test/run_all_unittests.cc',
@@ -235,23 +267,27 @@
'type': '<(gtest_target_type)',
'dependencies': [
'../base/base.gyp:test_support_base',
+ '../gpu/gpu.gyp:gpu',
+ '../gpu/gpu.gyp:gpu_unittest_utils',
'../media/media.gyp:media',
'../skia/skia.gyp:skia',
'../testing/gmock.gyp:gmock',
'../testing/gtest.gyp:gtest',
'../testing/perf/perf_test.gyp:*',
- '../ui/ui.gyp:ui',
+ '../ui/gfx/gfx.gyp:gfx',
'cc.gyp:cc',
'cc_test_support',
],
'sources': [
+ 'layers/layer_perftest.cc',
'resources/picture_layer_tiling_perftest.cc',
'resources/raster_worker_pool_perftest.cc',
'resources/tile_manager_perftest.cc',
'resources/worker_pool_perftest.cc',
'test/cc_test_suite.cc',
'test/lap_timer.cc',
- 'test/run_all_unittests.cc',
+ 'test/run_all_perftests.cc',
+ 'trees/layer_tree_host_common_perftest.cc',
'trees/layer_tree_host_perftest.cc',
],
'include_dirs': [
@@ -287,13 +323,17 @@
'..',
],
'dependencies': [
+ '../base/base.gyp:base',
+ '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
+ '../gpu/gpu.gyp:gpu_unittest_utils',
'../skia/skia.gyp:skia',
'../testing/gmock.gyp:gmock',
'../testing/gtest.gyp:gtest',
'../third_party/WebKit/public/blink.gyp:blink_minimal',
'../third_party/mesa/mesa.gyp:osmesa',
+ '../ui/gfx/gfx.gyp:gfx',
'../ui/gl/gl.gyp:gl',
- '../ui/ui.gyp:ui',
+ '../ui/ui_unittests.gyp:ui_test_support',
],
'sources': [
'<@(cc_tests_support_files)',
@@ -301,23 +341,6 @@
# TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
'msvs_disabled_warnings': [ 4267, ],
},
- {
- 'target_name': 'cc_test_utils',
- 'type': 'static_library',
- 'include_dirs': [
- '..'
- ],
- 'sources': [
- 'test/pixel_comparator.cc',
- 'test/pixel_comparator.h',
- 'test/pixel_test_utils.cc',
- 'test/pixel_test_utils.h',
- ],
- 'dependencies': [
- '../skia/skia.gyp:skia',
- '../ui/ui.gyp:ui', # for png_codec
- ],
- },
],
'conditions': [
# Special target to wrap a gtest_target_type==shared_library
diff --git a/chromium/cc/debug/OWNERS b/chromium/cc/debug/OWNERS
index a46edeee25d..2de2d9b11bd 100644
--- a/chromium/cc/debug/OWNERS
+++ b/chromium/cc/debug/OWNERS
@@ -2,3 +2,6 @@
per-file benchmark_instrumentation.h=set noparent
per-file benchmark_instrumentation.h=ernstm@chromium.org
per-file benchmark_instrumentation.h=nduca@chromium.org
+per-file benchmark_instrumentation.cc=set noparent
+per-file benchmark_instrumentation.cc=ernstm@chromium.org
+per-file benchmark_instrumentation.cc=nduca@chromium.org
diff --git a/chromium/cc/debug/benchmark_instrumentation.cc b/chromium/cc/debug/benchmark_instrumentation.cc
new file mode 100644
index 00000000000..bf2b0222720
--- /dev/null
+++ b/chromium/cc/debug/benchmark_instrumentation.cc
@@ -0,0 +1,30 @@
+// 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/debug/trace_event.h"
+#include "cc/debug/benchmark_instrumentation.h"
+
+namespace cc {
+
+// Please do not change the trace events in this file without updating
+// tools/perf/measurements/rendering_stats.py accordingly.
+// The benchmarks search for events and their arguments by name.
+
+void BenchmarkInstrumentation::IssueMainThreadRenderingStatsEvent(
+ const MainThreadRenderingStats& stats) {
+ TRACE_EVENT_INSTANT1("benchmark",
+ "BenchmarkInstrumentation::MainThreadRenderingStats",
+ TRACE_EVENT_SCOPE_THREAD,
+ "data", stats.AsTraceableData());
+}
+
+void BenchmarkInstrumentation::IssueImplThreadRenderingStatsEvent(
+ const ImplThreadRenderingStats& stats) {
+ TRACE_EVENT_INSTANT1("benchmark",
+ "BenchmarkInstrumentation::ImplThreadRenderingStats",
+ TRACE_EVENT_SCOPE_THREAD,
+ "data", stats.AsTraceableData());
+}
+
+} // namespace cc
diff --git a/chromium/cc/debug/benchmark_instrumentation.h b/chromium/cc/debug/benchmark_instrumentation.h
index 615fbe90622..2614814914c 100644
--- a/chromium/cc/debug/benchmark_instrumentation.h
+++ b/chromium/cc/debug/benchmark_instrumentation.h
@@ -5,28 +5,18 @@
#ifndef CC_DEBUG_BENCHMARK_INSTRUMENTATION_H_
#define CC_DEBUG_BENCHMARK_INSTRUMENTATION_H_
-#include "base/debug/trace_event.h"
+#include "cc/debug/rendering_stats.h"
namespace cc {
-namespace benchmark_instrumentation {
-// Please do not change the string constants in this file (or the TRACE_EVENT
-// calls that use them) without updating
-// tools/perf/measurements/rasterize_and_record_benchmark.py accordingly.
-// The benchmark searches for events and their arguments by name.
-const char kCategory[] = "cc,benchmark";
-const char kSourceFrameNumber[] = "source_frame_number";
-const char kData[] = "data";
-const char kWidth[] = "width";
-const char kHeight[] = "height";
-const char kNumPixelsRasterized[] = "num_pixels_rasterized";
-const char kLayerTreeHostUpdateLayers[] = "LayerTreeHost::UpdateLayers";
-const char kPictureLayerUpdate[] = "PictureLayer::Update";
-const char kRunRasterOnThread[] = "RasterWorkerPoolTaskImpl::RunRasterOnThread";
-const char kRecordLoop[] = "RecordLoop";
-const char kRasterLoop[] = "RasterLoop";
-const char kPictureRecord[] = "Picture::Record";
-const char kPictureRaster[] = "Picture::Raster";
-} // namespace benchmark_instrumentation
+
+class CC_EXPORT BenchmarkInstrumentation {
+ public:
+ static void IssueMainThreadRenderingStatsEvent(
+ const MainThreadRenderingStats& stats);
+ static void IssueImplThreadRenderingStatsEvent(
+ const ImplThreadRenderingStats& stats);
+};
+
} // namespace cc
#endif // CC_DEBUG_BENCHMARK_INSTRUMENTATION_H_
diff --git a/chromium/cc/debug/debug_colors.cc b/chromium/cc/debug/debug_colors.cc
index e6f3e28a238..9fee7551b3d 100644
--- a/chromium/cc/debug/debug_colors.cc
+++ b/chromium/cc/debug/debug_colors.cc
@@ -253,6 +253,15 @@ SkColor DebugColors::NonFastScrollableRectFillColor() {
return SkColorSetARGB(30, 238, 163, 59);
}
+// Animation bounds are lime-green.
+SkColor DebugColors::LayerAnimationBoundsBorderColor() {
+ return SkColorSetARGB(255, 112, 229, 0);
+}
+int DebugColors::LayerAnimationBoundsBorderWidth() { return 2; }
+SkColor DebugColors::LayerAnimationBoundsFillColor() {
+ return SkColorSetARGB(30, 112, 229, 0);
+}
+
// Non-Painted rects in cyan.
SkColor DebugColors::NonPaintedFillColor() { return SK_ColorCYAN; }
diff --git a/chromium/cc/debug/debug_colors.h b/chromium/cc/debug/debug_colors.h
index a1335e37e96..9edfb377bad 100644
--- a/chromium/cc/debug/debug_colors.h
+++ b/chromium/cc/debug/debug_colors.h
@@ -106,6 +106,10 @@ class DebugColors {
static int NonFastScrollableRectBorderWidth();
static SkColor NonFastScrollableRectFillColor();
+ static SkColor LayerAnimationBoundsBorderColor();
+ static int LayerAnimationBoundsBorderWidth();
+ static SkColor LayerAnimationBoundsFillColor();
+
static SkColor NonPaintedFillColor();
static SkColor MissingPictureFillColor();
static SkColor PictureBorderColor();
diff --git a/chromium/cc/debug/debug_rect_history.cc b/chromium/cc/debug/debug_rect_history.cc
index 24ba86eae59..679beafdbb4 100644
--- a/chromium/cc/debug/debug_rect_history.cc
+++ b/chromium/cc/debug/debug_rect_history.cc
@@ -58,6 +58,9 @@ void DebugRectHistory::SaveDebugRectsForCurrentFrame(
if (debug_state.show_non_occluding_rects)
SaveNonOccludingRects(non_occluding_screen_space_rects);
+
+ if (debug_state.show_layer_animation_bounds_rects)
+ SaveLayerAnimationBoundsRects(render_surface_layer_list);
}
void DebugRectHistory::SavePaintRects(LayerImpl* layer) {
@@ -105,8 +108,7 @@ void DebugRectHistory::SavePropertyChangedRects(
if (layer->LayerIsAlwaysDamaged())
continue;
- if (layer->LayerPropertyChanged() ||
- layer->LayerSurfacePropertyChanged()) {
+ if (layer->LayerPropertyChanged()) {
debug_rects_.push_back(
DebugRect(PROPERTY_CHANGED_RECT_TYPE,
MathUtil::MapClippedRect(
@@ -233,4 +235,28 @@ void DebugRectHistory::SaveNonFastScrollableRectsCallback(LayerImpl* layer) {
}
}
+void DebugRectHistory::SaveLayerAnimationBoundsRects(
+ const LayerImplList& render_surface_layer_list) {
+ typedef LayerIterator<LayerImpl,
+ LayerImplList,
+ RenderSurfaceImpl,
+ LayerIteratorActions::FrontToBack> LayerIteratorType;
+ LayerIteratorType end = LayerIteratorType::End(&render_surface_layer_list);
+ for (LayerIteratorType it =
+ LayerIteratorType::Begin(&render_surface_layer_list);
+ it != end; ++it) {
+ if (!it.represents_itself())
+ continue;
+ gfx::BoxF inflated_bounds;
+ if (!(*it)->GetAnimationBounds(&inflated_bounds))
+ continue;
+
+ debug_rects_.push_back(DebugRect(ANIMATION_BOUNDS_RECT_TYPE,
+ gfx::RectF(inflated_bounds.x(),
+ inflated_bounds.y(),
+ inflated_bounds.width(),
+ inflated_bounds.height())));
+ }
+}
+
} // namespace cc
diff --git a/chromium/cc/debug/debug_rect_history.h b/chromium/cc/debug/debug_rect_history.h
index 346148a93fc..0dae431bd5f 100644
--- a/chromium/cc/debug/debug_rect_history.h
+++ b/chromium/cc/debug/debug_rect_history.h
@@ -53,6 +53,7 @@ enum DebugRectType {
TOUCH_EVENT_HANDLER_RECT_TYPE,
WHEEL_EVENT_HANDLER_RECT_TYPE,
NON_FAST_SCROLLABLE_RECT_TYPE,
+ ANIMATION_BOUNDS_RECT_TYPE,
};
struct DebugRect {
@@ -103,6 +104,8 @@ class DebugRectHistory {
void SaveWheelEventHandlerRectsCallback(LayerImpl* layer);
void SaveNonFastScrollableRects(LayerImpl* layer);
void SaveNonFastScrollableRectsCallback(LayerImpl* layer);
+ void SaveLayerAnimationBoundsRects(
+ const LayerImplList& render_surface_layer_list);
std::vector<DebugRect> debug_rects_;
diff --git a/chromium/cc/debug/devtools_instrumentation.h b/chromium/cc/debug/devtools_instrumentation.h
index eea9e62f02a..3caa81ea6d5 100644
--- a/chromium/cc/debug/devtools_instrumentation.h
+++ b/chromium/cc/debug/devtools_instrumentation.h
@@ -12,17 +12,18 @@ namespace devtools_instrumentation {
namespace internal {
const char kCategory[] = "cc,devtools";
+const char kFrameId[] = "frameId";
const char kLayerId[] = "layerId";
const char kLayerTreeId[] = "layerTreeId";
const char kPixelRefId[] = "pixelRefId";
const char kImageDecodeTask[] = "ImageDecodeTask";
-}
+const char kBeginFrame[] = "BeginFrame";
+const char kActivateLayerTree[] = "ActivateLayerTree";
+} // namespace internal
-const char kPaintLayer[] = "PaintLayer";
const char kRasterTask[] = "RasterTask";
const char kPaintSetup[] = "PaintSetup";
-const char kUpdateLayer[] = "UpdateLayer";
class ScopedLayerTask {
public:
@@ -57,10 +58,11 @@ class ScopedLayerTreeTask {
public:
ScopedLayerTreeTask(const char* event_name,
int layer_id,
- uint64 tree_id)
+ int layer_tree_host_id)
: event_name_(event_name) {
TRACE_EVENT_BEGIN2(internal::kCategory, event_name_,
- internal::kLayerId, layer_id, internal::kLayerTreeId, tree_id);
+ internal::kLayerId, layer_id,
+ internal::kLayerTreeId, layer_tree_host_id);
}
~ScopedLayerTreeTask() {
TRACE_EVENT_END0(internal::kCategory, event_name_);
@@ -84,6 +86,21 @@ struct ScopedLayerObjectTracker
DISALLOW_COPY_AND_ASSIGN(ScopedLayerObjectTracker);
};
+inline void didActivateLayerTree(int layer_tree_host_id, int frame_id) {
+ TRACE_EVENT_INSTANT2(internal::kCategory,
+ internal::kActivateLayerTree,
+ TRACE_EVENT_SCOPE_THREAD,
+ internal::kLayerTreeId, layer_tree_host_id,
+ internal::kFrameId, frame_id);
+}
+
+inline void didBeginFrame(int layer_tree_host_id) {
+ TRACE_EVENT_INSTANT1(internal::kCategory,
+ internal::kBeginFrame,
+ TRACE_EVENT_SCOPE_THREAD,
+ internal::kLayerTreeId, layer_tree_host_id);
+}
+
} // namespace devtools_instrumentation
} // namespace cc
diff --git a/chromium/cc/debug/fake_web_graphics_context_3d.cc b/chromium/cc/debug/fake_web_graphics_context_3d.cc
deleted file mode 100644
index f493dc1d854..00000000000
--- a/chromium/cc/debug/fake_web_graphics_context_3d.cc
+++ /dev/null
@@ -1,347 +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/fake_web_graphics_context_3d.h"
-
-#include "base/logging.h"
-#include "third_party/khronos/GLES2/gl2.h"
-
-using WebKit::WGC3Dboolean;
-using WebKit::WGC3Denum;
-using WebKit::WebGLId;
-using WebKit::WebGraphicsContext3D;
-
-namespace cc {
-
-FakeWebGraphicsContext3D::FakeWebGraphicsContext3D()
- : WebKit::WebGraphicsContext3D() {
-}
-
-FakeWebGraphicsContext3D::~FakeWebGraphicsContext3D() {
-}
-
-bool FakeWebGraphicsContext3D::makeContextCurrent() {
- return true;
-}
-
-int FakeWebGraphicsContext3D::width() {
- return 1;
-}
-
-int FakeWebGraphicsContext3D::height() {
- return 1;
-}
-
-void FakeWebGraphicsContext3D::reshape(int width, int height) {
-}
-
-bool FakeWebGraphicsContext3D::isGLES2Compliant() {
- return false;
-}
-
-WebGLId FakeWebGraphicsContext3D::getPlatformTextureId() {
- return 0;
-}
-
-bool FakeWebGraphicsContext3D::isContextLost() {
- return false;
-}
-
-WGC3Denum FakeWebGraphicsContext3D::getGraphicsResetStatusARB() {
- return GL_NO_ERROR;
-}
-
-void* FakeWebGraphicsContext3D::mapBufferSubDataCHROMIUM(
- WGC3Denum target,
- WebKit::WGC3Dintptr offset,
- WebKit::WGC3Dsizeiptr size,
- WGC3Denum access) {
- return 0;
-}
-
-void* FakeWebGraphicsContext3D::mapTexSubImage2DCHROMIUM(
- WGC3Denum target,
- WebKit::WGC3Dint level,
- WebKit::WGC3Dint xoffset,
- WebKit::WGC3Dint yoffset,
- WebKit::WGC3Dsizei width,
- WebKit::WGC3Dsizei height,
- WGC3Denum format,
- WGC3Denum type,
- WGC3Denum access) {
- return 0;
-}
-
-WebKit::WebString FakeWebGraphicsContext3D::getRequestableExtensionsCHROMIUM() {
- return WebKit::WebString();
-}
-
-WGC3Denum FakeWebGraphicsContext3D::checkFramebufferStatus(
- WGC3Denum target) {
- return GL_FRAMEBUFFER_COMPLETE;
-}
-
-bool FakeWebGraphicsContext3D::getActiveAttrib(
- WebGLId program,
- WebKit::WGC3Duint index,
- ActiveInfo&) {
- return false;
-}
-
-bool FakeWebGraphicsContext3D::getActiveUniform(
- WebGLId program,
- WebKit::WGC3Duint index,
- ActiveInfo&) {
- return false;
-}
-
-WebKit::WGC3Dint FakeWebGraphicsContext3D::getAttribLocation(
- WebGLId program,
- const WebKit::WGC3Dchar* name) {
- return 0;
-}
-
-WebGraphicsContext3D::Attributes
- FakeWebGraphicsContext3D::getContextAttributes() {
- return WebGraphicsContext3D::Attributes();
-}
-
-WGC3Denum FakeWebGraphicsContext3D::getError() {
- return 0;
-}
-
-void FakeWebGraphicsContext3D::getIntegerv(
- WGC3Denum pname,
- WebKit::WGC3Dint* value) {
- if (pname == GL_MAX_TEXTURE_SIZE)
- *value = 1024;
- else if (pname == GL_ACTIVE_TEXTURE)
- *value = GL_TEXTURE0;
-}
-
-void FakeWebGraphicsContext3D::getProgramiv(
- WebGLId program,
- WGC3Denum pname,
- WebKit::WGC3Dint* value) {
- if (pname == GL_LINK_STATUS)
- *value = 1;
-}
-
-WebKit::WebString FakeWebGraphicsContext3D::getProgramInfoLog(
- WebGLId program) {
- return WebKit::WebString();
-}
-
-void FakeWebGraphicsContext3D::getShaderiv(
- WebGLId shader,
- WGC3Denum pname,
- WebKit::WGC3Dint* value) {
- if (pname == GL_COMPILE_STATUS)
- *value = 1;
-}
-
-WebKit::WebString FakeWebGraphicsContext3D::getShaderInfoLog(
- WebGLId shader) {
- return WebKit::WebString();
-}
-
-void FakeWebGraphicsContext3D::getShaderPrecisionFormat(
- WebKit::WGC3Denum shadertype,
- WebKit::WGC3Denum precisiontype,
- WebKit::WGC3Dint* range,
- WebKit::WGC3Dint* precision) {
- // Return the minimum precision requirements of the GLES specificatin.
- switch (precisiontype) {
- case GL_LOW_INT:
- range[0] = 8;
- range[1] = 8;
- *precision = 0;
- break;
- case GL_MEDIUM_INT:
- range[0] = 10;
- range[1] = 10;
- *precision = 0;
- break;
- case GL_HIGH_INT:
- range[0] = 16;
- range[1] = 16;
- *precision = 0;
- break;
- case GL_LOW_FLOAT:
- range[0] = 8;
- range[1] = 8;
- *precision = 8;
- break;
- case GL_MEDIUM_FLOAT:
- range[0] = 14;
- range[1] = 14;
- *precision = 10;
- break;
- case GL_HIGH_FLOAT:
- range[0] = 62;
- range[1] = 62;
- *precision = 16;
- break;
- default:
- NOTREACHED();
- break;
- }
-}
-
-WebKit::WebString FakeWebGraphicsContext3D::getShaderSource(
- WebGLId shader) {
- return WebKit::WebString();
-}
-
-WebKit::WebString FakeWebGraphicsContext3D::getString(WGC3Denum name) {
- return WebKit::WebString();
-}
-
-WebKit::WGC3Dint FakeWebGraphicsContext3D::getUniformLocation(
- WebGLId program,
- const WebKit::WGC3Dchar* name) {
- return 0;
-}
-
-WebKit::WGC3Dsizeiptr FakeWebGraphicsContext3D::getVertexAttribOffset(
- WebKit::WGC3Duint index,
- WGC3Denum pname) {
- return 0;
-}
-
-WGC3Dboolean FakeWebGraphicsContext3D::isBuffer(
- WebGLId buffer) {
- return false;
-}
-
-WGC3Dboolean FakeWebGraphicsContext3D::isEnabled(
- WGC3Denum cap) {
- return false;
-}
-
-WGC3Dboolean FakeWebGraphicsContext3D::isFramebuffer(
- WebGLId framebuffer) {
- return false;
-}
-
-WGC3Dboolean FakeWebGraphicsContext3D::isProgram(
- WebGLId program) {
- return false;
-}
-
-WGC3Dboolean FakeWebGraphicsContext3D::isRenderbuffer(
- WebGLId renderbuffer) {
- return false;
-}
-
-WGC3Dboolean FakeWebGraphicsContext3D::isShader(
- WebGLId shader) {
- return false;
-}
-
-WGC3Dboolean FakeWebGraphicsContext3D::isTexture(
- WebGLId texture) {
- return false;
-}
-
-WebGLId FakeWebGraphicsContext3D::createBuffer() {
- return 1;
-}
-
-void FakeWebGraphicsContext3D::deleteBuffer(WebKit::WebGLId id) {
-}
-
-WebGLId FakeWebGraphicsContext3D::createFramebuffer() {
- return 1;
-}
-
-void FakeWebGraphicsContext3D::deleteFramebuffer(WebKit::WebGLId id) {
-}
-
-WebGLId FakeWebGraphicsContext3D::createProgram() {
- return 1;
-}
-
-void FakeWebGraphicsContext3D::deleteProgram(WebKit::WebGLId id) {
-}
-
-WebGLId FakeWebGraphicsContext3D::createRenderbuffer() {
- return 1;
-}
-
-void FakeWebGraphicsContext3D::deleteRenderbuffer(WebKit::WebGLId id) {
-}
-
-WebGLId FakeWebGraphicsContext3D::createShader(WGC3Denum) {
- return 1;
-}
-
-void FakeWebGraphicsContext3D::deleteShader(WebKit::WebGLId id) {
-}
-
-WebGLId FakeWebGraphicsContext3D::createTexture() {
- return 1;
-}
-
-void FakeWebGraphicsContext3D::deleteTexture(WebGLId texture_id) {
-}
-
-void FakeWebGraphicsContext3D::attachShader(WebGLId program, WebGLId shader) {
-}
-
-void FakeWebGraphicsContext3D::useProgram(WebGLId program) {
-}
-
-void FakeWebGraphicsContext3D::bindBuffer(WGC3Denum target, WebGLId buffer) {
-}
-
-void FakeWebGraphicsContext3D::bindFramebuffer(
- WGC3Denum target, WebGLId framebuffer) {
-}
-
-void FakeWebGraphicsContext3D::bindRenderbuffer(
- WGC3Denum target, WebGLId renderbuffer) {
-}
-
-void FakeWebGraphicsContext3D::bindTexture(
- WGC3Denum target, WebGLId texture_id) {
-}
-
-WebGLId FakeWebGraphicsContext3D::createQueryEXT() {
- return 1;
-}
-
-WGC3Dboolean FakeWebGraphicsContext3D::isQueryEXT(WebGLId query) {
- return true;
-}
-
-void FakeWebGraphicsContext3D::endQueryEXT(WebKit::WGC3Denum target) {
-}
-
-void FakeWebGraphicsContext3D::getQueryObjectuivEXT(
- WebKit::WebGLId query,
- WebKit::WGC3Denum pname,
- WebKit::WGC3Duint* params) {
-}
-
-void FakeWebGraphicsContext3D::setContextLostCallback(
- WebGraphicsContextLostCallback* callback) {
-}
-
-void FakeWebGraphicsContext3D::loseContextCHROMIUM(WGC3Denum current,
- WGC3Denum other) {
-}
-
-WebKit::WGC3Duint FakeWebGraphicsContext3D::createImageCHROMIUM(
- WebKit::WGC3Dsizei width, WebKit::WGC3Dsizei height,
- WebKit::WGC3Denum internalformat) {
- return 0;
-}
-
-void* FakeWebGraphicsContext3D::mapImageCHROMIUM(WebKit::WGC3Duint image_id,
- WebKit::WGC3Denum access) {
- return 0;
-}
-
-} // namespace cc
diff --git a/chromium/cc/debug/fake_web_graphics_context_3d.h b/chromium/cc/debug/fake_web_graphics_context_3d.h
deleted file mode 100644
index 04c983de006..00000000000
--- a/chromium/cc/debug/fake_web_graphics_context_3d.h
+++ /dev/null
@@ -1,608 +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_FAKE_WEB_GRAPHICS_CONTEXT_3D_H_
-#define CC_DEBUG_FAKE_WEB_GRAPHICS_CONTEXT_3D_H_
-
-#include <string>
-
-#include "base/compiler_specific.h"
-#include "cc/base/cc_export.h"
-#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
-
-namespace cc {
-
-// WebGraphicsContext3D base class for use in unit tests.
-// All operations are no-ops (returning 0 if necessary).
-class CC_EXPORT FakeWebGraphicsContext3D
- : public NON_EXPORTED_BASE(WebKit::WebGraphicsContext3D) {
- public:
- FakeWebGraphicsContext3D();
- virtual ~FakeWebGraphicsContext3D();
-
- virtual bool makeContextCurrent();
-
- virtual int width();
- virtual int height();
-
- virtual void reshape(int width, int height);
-
- virtual bool isGLES2Compliant();
-
- virtual WebKit::WebGLId getPlatformTextureId();
-
- virtual void prepareTexture() {}
-
- virtual void postSubBufferCHROMIUM(int x, int y, int width, int height) {}
-
- virtual void synthesizeGLError(WebKit::WGC3Denum) {}
-
- virtual bool isContextLost();
- virtual WebKit::WGC3Denum getGraphicsResetStatusARB();
-
- virtual void* mapBufferSubDataCHROMIUM(
- WebKit::WGC3Denum target,
- WebKit::WGC3Dintptr offset,
- WebKit::WGC3Dsizeiptr size,
- WebKit::WGC3Denum access);
-
- virtual void unmapBufferSubDataCHROMIUM(const void*) {}
- virtual void* mapTexSubImage2DCHROMIUM(
- WebKit::WGC3Denum target,
- WebKit::WGC3Dint level,
- WebKit::WGC3Dint xoffset,
- WebKit::WGC3Dint yoffset,
- WebKit::WGC3Dsizei width,
- WebKit::WGC3Dsizei height,
- WebKit::WGC3Denum format,
- WebKit::WGC3Denum type,
- WebKit::WGC3Denum access);
- virtual void unmapTexSubImage2DCHROMIUM(const void*) {}
-
- virtual void setVisibilityCHROMIUM(bool visible) {}
-
- virtual void discardFramebufferEXT(
- WebKit::WGC3Denum target,
- WebKit::WGC3Dsizei num_attachments,
- const WebKit::WGC3Denum* attachments) {}
-
- virtual WebKit::WebString getRequestableExtensionsCHROMIUM();
- virtual void requestExtensionCHROMIUM(const char*) {}
-
- virtual void blitFramebufferCHROMIUM(
- WebKit::WGC3Dint src_x0,
- WebKit::WGC3Dint src_y0,
- WebKit::WGC3Dint src_x1,
- WebKit::WGC3Dint src_y1,
- WebKit::WGC3Dint dst_x0,
- WebKit::WGC3Dint dst_y0,
- WebKit::WGC3Dint dst_x1,
- WebKit::WGC3Dint dst_y1,
- WebKit::WGC3Dbitfield mask,
- WebKit::WGC3Denum filter) {}
- virtual void renderbufferStorageMultisampleCHROMIUM(
- WebKit::WGC3Denum target,
- WebKit::WGC3Dsizei samples,
- WebKit::WGC3Denum internalformat,
- WebKit::WGC3Dsizei width,
- WebKit::WGC3Dsizei height) {}
-
- virtual void activeTexture(WebKit::WGC3Denum texture) {}
- virtual void attachShader(WebKit::WebGLId program, WebKit::WebGLId shader);
- virtual void bindAttribLocation(
- WebKit::WebGLId program,
- WebKit::WGC3Duint index,
- const WebKit::WGC3Dchar* name) {}
- virtual void bindBuffer(WebKit::WGC3Denum target, WebKit::WebGLId buffer);
- virtual void bindFramebuffer(
- WebKit::WGC3Denum target, WebKit::WebGLId framebuffer);
- virtual void bindRenderbuffer(
- WebKit::WGC3Denum target, WebKit::WebGLId renderbuffer);
- virtual void bindTexture(
- WebKit::WGC3Denum target,
- WebKit::WebGLId texture_id);
- virtual void blendColor(
- WebKit::WGC3Dclampf red,
- WebKit::WGC3Dclampf green,
- WebKit::WGC3Dclampf blue,
- WebKit::WGC3Dclampf alpha) {}
- virtual void blendEquation(WebKit::WGC3Denum mode) {}
- virtual void blendEquationSeparate(
- WebKit::WGC3Denum mode_rgb,
- WebKit::WGC3Denum mode_alpha) {}
- virtual void blendFunc(
- WebKit::WGC3Denum sfactor,
- WebKit::WGC3Denum dfactor) {}
- virtual void blendFuncSeparate(
- WebKit::WGC3Denum src_rgb,
- WebKit::WGC3Denum dst_rgb,
- WebKit::WGC3Denum src_alpha,
- WebKit::WGC3Denum dst_alpha) {}
-
- virtual void bufferData(
- WebKit::WGC3Denum target,
- WebKit::WGC3Dsizeiptr size,
- const void* data,
- WebKit::WGC3Denum usage) {}
- virtual void bufferSubData(
- WebKit::WGC3Denum target,
- WebKit::WGC3Dintptr offset,
- WebKit::WGC3Dsizeiptr size,
- const void* data) {}
-
- virtual WebKit::WGC3Denum checkFramebufferStatus(WebKit::WGC3Denum target);
-
- virtual void clear(WebKit::WGC3Dbitfield mask) {}
- virtual void clearColor(
- WebKit::WGC3Dclampf red,
- WebKit::WGC3Dclampf green,
- WebKit::WGC3Dclampf blue,
- WebKit::WGC3Dclampf alpha) {}
- virtual void clearDepth(WebKit::WGC3Dclampf depth) {}
- virtual void clearStencil(WebKit::WGC3Dint s) {}
- virtual void colorMask(
- WebKit::WGC3Dboolean red,
- WebKit::WGC3Dboolean green,
- WebKit::WGC3Dboolean blue,
- WebKit::WGC3Dboolean alpha) {}
- virtual void compileShader(WebKit::WebGLId shader) {}
-
- virtual void compressedTexImage2D(
- WebKit::WGC3Denum target,
- WebKit::WGC3Dint level,
- WebKit::WGC3Denum internal_format,
- WebKit::WGC3Dsizei width,
- WebKit::WGC3Dsizei height,
- WebKit::WGC3Dint border,
- WebKit::WGC3Dsizei image_size,
- const void* data) {}
- virtual void compressedTexSubImage2D(
- WebKit::WGC3Denum target,
- WebKit::WGC3Dint level,
- WebKit::WGC3Dint xoffset,
- WebKit::WGC3Dint yoffset,
- WebKit::WGC3Dsizei width,
- WebKit::WGC3Dsizei height,
- WebKit::WGC3Denum format,
- WebKit::WGC3Dsizei image_size,
- const void* data) {}
- virtual void copyTexImage2D(
- WebKit::WGC3Denum target,
- WebKit::WGC3Dint level,
- WebKit::WGC3Denum internalformat,
- WebKit::WGC3Dint x,
- WebKit::WGC3Dint y,
- WebKit::WGC3Dsizei width,
- WebKit::WGC3Dsizei height,
- WebKit::WGC3Dint border) {}
- virtual void copyTexSubImage2D(
- WebKit::WGC3Denum target,
- WebKit::WGC3Dint level,
- WebKit::WGC3Dint xoffset,
- WebKit::WGC3Dint yoffset,
- WebKit::WGC3Dint x,
- WebKit::WGC3Dint y,
- WebKit::WGC3Dsizei width,
- WebKit::WGC3Dsizei height) {}
- virtual void cullFace(WebKit::WGC3Denum mode) {}
- virtual void depthFunc(WebKit::WGC3Denum func) {}
- virtual void depthMask(WebKit::WGC3Dboolean flag) {}
- virtual void depthRange(
- WebKit::WGC3Dclampf z_near,
- WebKit::WGC3Dclampf z_far) {}
- virtual void detachShader(WebKit::WebGLId program, WebKit::WebGLId shader) {}
- virtual void disable(WebKit::WGC3Denum cap) {}
- virtual void disableVertexAttribArray(WebKit::WGC3Duint index) {}
- virtual void drawArrays(
- WebKit::WGC3Denum mode,
- WebKit::WGC3Dint first,
- WebKit::WGC3Dsizei count) {}
- virtual void drawElements(
- WebKit::WGC3Denum mode,
- WebKit::WGC3Dsizei count,
- WebKit::WGC3Denum type,
- WebKit::WGC3Dintptr offset) {}
-
- virtual void enable(WebKit::WGC3Denum cap) {}
- virtual void enableVertexAttribArray(WebKit::WGC3Duint index) {}
- virtual void finish() {}
- virtual void flush() {}
- virtual void framebufferRenderbuffer(
- WebKit::WGC3Denum target,
- WebKit::WGC3Denum attachment,
- WebKit::WGC3Denum renderbuffertarget,
- WebKit::WebGLId renderbuffer) {}
- virtual void framebufferTexture2D(
- WebKit::WGC3Denum target,
- WebKit::WGC3Denum attachment,
- WebKit::WGC3Denum textarget,
- WebKit::WebGLId texture,
- WebKit::WGC3Dint level) {}
- virtual void frontFace(WebKit::WGC3Denum mode) {}
- virtual void generateMipmap(WebKit::WGC3Denum target) {}
-
- virtual bool getActiveAttrib(
- WebKit::WebGLId program,
- WebKit::WGC3Duint index, ActiveInfo&);
- virtual bool getActiveUniform(
- WebKit::WebGLId program,
- WebKit::WGC3Duint index,
- ActiveInfo&);
- virtual void getAttachedShaders(
- WebKit::WebGLId program,
- WebKit::WGC3Dsizei max_count,
- WebKit::WGC3Dsizei* count,
- WebKit::WebGLId* shaders) {}
- virtual WebKit::WGC3Dint getAttribLocation(
- WebKit::WebGLId program,
- const WebKit::WGC3Dchar* name);
- virtual void getBooleanv(
- WebKit::WGC3Denum pname,
- WebKit::WGC3Dboolean* value) {}
- virtual void getBufferParameteriv(
- WebKit::WGC3Denum target,
- WebKit::WGC3Denum pname,
- WebKit::WGC3Dint* value) {}
- virtual Attributes getContextAttributes();
- virtual WebKit::WGC3Denum getError();
- virtual void getFloatv(
- WebKit::WGC3Denum pname,
- WebKit::WGC3Dfloat* value) {}
- virtual void getFramebufferAttachmentParameteriv(
- WebKit::WGC3Denum target,
- WebKit::WGC3Denum attachment,
- WebKit::WGC3Denum pname,
- WebKit::WGC3Dint* value) {}
-
- virtual void getIntegerv(
- WebKit::WGC3Denum pname,
- WebKit::WGC3Dint* value);
-
- virtual void getProgramiv(
- WebKit::WebGLId program,
- WebKit::WGC3Denum pname,
- WebKit::WGC3Dint* value);
-
- virtual WebKit::WebString getProgramInfoLog(WebKit::WebGLId program);
- virtual void getRenderbufferParameteriv(
- WebKit::WGC3Denum target,
- WebKit::WGC3Denum pname,
- WebKit::WGC3Dint* value) {}
-
- virtual void getShaderiv(
- WebKit::WebGLId shader,
- WebKit::WGC3Denum pname,
- WebKit::WGC3Dint* value);
-
- virtual WebKit::WebString getShaderInfoLog(WebKit::WebGLId shader);
- virtual void getShaderPrecisionFormat(
- WebKit::WGC3Denum shadertype,
- WebKit::WGC3Denum precisiontype,
- WebKit::WGC3Dint* range,
- WebKit::WGC3Dint* precision);
- virtual WebKit::WebString getShaderSource(WebKit::WebGLId shader);
- virtual WebKit::WebString getString(WebKit::WGC3Denum name);
- virtual void getTexParameterfv(
- WebKit::WGC3Denum target,
- WebKit::WGC3Denum pname,
- WebKit::WGC3Dfloat* value) {}
- virtual void getTexParameteriv(
- WebKit::WGC3Denum target,
- WebKit::WGC3Denum pname,
- WebKit::WGC3Dint* value) {}
- virtual void getUniformfv(
- WebKit::WebGLId program,
- WebKit::WGC3Dint location,
- WebKit::WGC3Dfloat* value) {}
- virtual void getUniformiv(
- WebKit::WebGLId program,
- WebKit::WGC3Dint location,
- WebKit::WGC3Dint* value) {}
- virtual WebKit::WGC3Dint getUniformLocation(
- WebKit::WebGLId program,
- const WebKit::WGC3Dchar* name);
- virtual void getVertexAttribfv(
- WebKit::WGC3Duint index,
- WebKit::WGC3Denum pname,
- WebKit::WGC3Dfloat* value) {}
- virtual void getVertexAttribiv(
- WebKit::WGC3Duint index,
- WebKit::WGC3Denum pname,
- WebKit::WGC3Dint* value) {}
- virtual WebKit::WGC3Dsizeiptr getVertexAttribOffset(
- WebKit::WGC3Duint index,
- WebKit::WGC3Denum pname);
-
- virtual void hint(WebKit::WGC3Denum target, WebKit::WGC3Denum mode) {}
- virtual WebKit::WGC3Dboolean isBuffer(WebKit::WebGLId buffer);
- virtual WebKit::WGC3Dboolean isEnabled(WebKit::WGC3Denum cap);
- virtual WebKit::WGC3Dboolean isFramebuffer(WebKit::WebGLId framebuffer);
- virtual WebKit::WGC3Dboolean isProgram(WebKit::WebGLId program);
- virtual WebKit::WGC3Dboolean isRenderbuffer(WebKit::WebGLId renderbuffer);
- virtual WebKit::WGC3Dboolean isShader(WebKit::WebGLId shader);
- virtual WebKit::WGC3Dboolean isTexture(WebKit::WebGLId texture);
- virtual void lineWidth(WebKit::WGC3Dfloat) {}
- virtual void linkProgram(WebKit::WebGLId program) {}
- virtual void pixelStorei(WebKit::WGC3Denum pname, WebKit::WGC3Dint param) {}
- virtual void polygonOffset(
- WebKit::WGC3Dfloat factor,
- WebKit::WGC3Dfloat units) {}
-
- virtual void readPixels(
- WebKit::WGC3Dint x,
- WebKit::WGC3Dint y,
- WebKit::WGC3Dsizei width,
- WebKit::WGC3Dsizei height,
- WebKit::WGC3Denum format,
- WebKit::WGC3Denum type,
- void* pixels) {}
-
- virtual void releaseShaderCompiler() {}
-
- virtual void renderbufferStorage(
- WebKit::WGC3Denum target,
- WebKit::WGC3Denum internalformat,
- WebKit::WGC3Dsizei width,
- WebKit::WGC3Dsizei height) {}
- virtual void sampleCoverage(
- WebKit::WGC3Dclampf value,
- WebKit::WGC3Dboolean invert) {}
- virtual void scissor(
- WebKit::WGC3Dint x,
- WebKit::WGC3Dint y,
- WebKit::WGC3Dsizei width,
- WebKit::WGC3Dsizei height) {}
- virtual void shaderSource(
- WebKit::WebGLId shader,
- const WebKit::WGC3Dchar* string) {}
- virtual void stencilFunc(
- WebKit::WGC3Denum func,
- WebKit::WGC3Dint ref,
- WebKit::WGC3Duint mask) {}
- virtual void stencilFuncSeparate(
- WebKit::WGC3Denum face,
- WebKit::WGC3Denum func,
- WebKit::WGC3Dint ref,
- WebKit::WGC3Duint mask) {}
- virtual void stencilMask(WebKit::WGC3Duint mask) {}
- virtual void stencilMaskSeparate(
- WebKit::WGC3Denum face,
- WebKit::WGC3Duint mask) {}
- virtual void stencilOp(
- WebKit::WGC3Denum fail,
- WebKit::WGC3Denum zfail,
- WebKit::WGC3Denum zpass) {}
- virtual void stencilOpSeparate(
- WebKit::WGC3Denum face,
- WebKit::WGC3Denum fail,
- WebKit::WGC3Denum zfail,
- WebKit::WGC3Denum zpass) {}
-
- virtual void texImage2D(
- WebKit::WGC3Denum target,
- WebKit::WGC3Dint level,
- WebKit::WGC3Denum internalformat,
- WebKit::WGC3Dsizei width,
- WebKit::WGC3Dsizei height,
- WebKit::WGC3Dint border,
- WebKit::WGC3Denum format,
- WebKit::WGC3Denum type,
- const void* pixels) {}
-
- virtual void texParameterf(
- WebKit::WGC3Denum target,
- WebKit::WGC3Denum pname,
- WebKit::WGC3Dfloat param) {}
- virtual void texParameteri(
- WebKit::WGC3Denum target,
- WebKit::WGC3Denum pname,
- WebKit::WGC3Dint param) {}
-
- virtual void texSubImage2D(
- WebKit::WGC3Denum target,
- WebKit::WGC3Dint level,
- WebKit::WGC3Dint xoffset,
- WebKit::WGC3Dint yoffset,
- WebKit::WGC3Dsizei width,
- WebKit::WGC3Dsizei height,
- WebKit::WGC3Denum format,
- WebKit::WGC3Denum type,
- const void* pixels) {}
-
- virtual void uniform1f(WebKit::WGC3Dint location, WebKit::WGC3Dfloat x) {}
- virtual void uniform1fv(
- WebKit::WGC3Dint location,
- WebKit::WGC3Dsizei count,
- const WebKit::WGC3Dfloat* v) {}
- virtual void uniform1i(WebKit::WGC3Dint location, WebKit::WGC3Dint x) {}
- virtual void uniform1iv(
- WebKit::WGC3Dint location,
- WebKit::WGC3Dsizei count,
- const WebKit::WGC3Dint* v) {}
- virtual void uniform2f(
- WebKit::WGC3Dint location,
- WebKit::WGC3Dfloat x,
- WebKit::WGC3Dfloat y) {}
- virtual void uniform2fv(
- WebKit::WGC3Dint location,
- WebKit::WGC3Dsizei count,
- const WebKit::WGC3Dfloat* v) {}
- virtual void uniform2i(
- WebKit::WGC3Dint location,
- WebKit::WGC3Dint x,
- WebKit::WGC3Dint y) {}
- virtual void uniform2iv(
- WebKit::WGC3Dint location,
- WebKit::WGC3Dsizei count,
- const WebKit::WGC3Dint* v) {}
- virtual void uniform3f(
- WebKit::WGC3Dint location,
- WebKit::WGC3Dfloat x,
- WebKit::WGC3Dfloat y,
- WebKit::WGC3Dfloat z) {}
- virtual void uniform3fv(
- WebKit::WGC3Dint location,
- WebKit::WGC3Dsizei count,
- const WebKit::WGC3Dfloat* v) {}
- virtual void uniform3i(
- WebKit::WGC3Dint location,
- WebKit::WGC3Dint x,
- WebKit::WGC3Dint y,
- WebKit::WGC3Dint z) {}
- virtual void uniform3iv(
- WebKit::WGC3Dint location,
- WebKit::WGC3Dsizei count,
- const WebKit::WGC3Dint* v) {}
- virtual void uniform4f(
- WebKit::WGC3Dint location,
- WebKit::WGC3Dfloat x,
- WebKit::WGC3Dfloat y,
- WebKit::WGC3Dfloat z,
- WebKit::WGC3Dfloat w) {}
- virtual void uniform4fv(
- WebKit::WGC3Dint location,
- WebKit::WGC3Dsizei count,
- const WebKit::WGC3Dfloat* v) {}
- virtual void uniform4i(
- WebKit::WGC3Dint location,
- WebKit::WGC3Dint x,
- WebKit::WGC3Dint y,
- WebKit::WGC3Dint z,
- WebKit::WGC3Dint w) {}
- virtual void uniform4iv(
- WebKit::WGC3Dint location,
- WebKit::WGC3Dsizei count,
- const WebKit::WGC3Dint* v) {}
- virtual void uniformMatrix2fv(
- WebKit::WGC3Dint location,
- WebKit::WGC3Dsizei count,
- WebKit::WGC3Dboolean transpose,
- const WebKit::WGC3Dfloat* value) {}
- virtual void uniformMatrix3fv(
- WebKit::WGC3Dint location,
- WebKit::WGC3Dsizei count,
- WebKit::WGC3Dboolean transpose,
- const WebKit::WGC3Dfloat* value) {}
- virtual void uniformMatrix4fv(
- WebKit::WGC3Dint location,
- WebKit::WGC3Dsizei count,
- WebKit::WGC3Dboolean transpose,
- const WebKit::WGC3Dfloat* value) {}
-
- virtual void useProgram(WebKit::WebGLId program);
- virtual void validateProgram(WebKit::WebGLId program) {}
-
- virtual void vertexAttrib1f(WebKit::WGC3Duint index, WebKit::WGC3Dfloat x) {}
- virtual void vertexAttrib1fv(
- WebKit::WGC3Duint index,
- const WebKit::WGC3Dfloat* values) {}
- virtual void vertexAttrib2f(
- WebKit::WGC3Duint index,
- WebKit::WGC3Dfloat x,
- WebKit::WGC3Dfloat y) {}
- virtual void vertexAttrib2fv(
- WebKit::WGC3Duint index,
- const WebKit::WGC3Dfloat* values) {}
- virtual void vertexAttrib3f(
- WebKit::WGC3Duint index,
- WebKit::WGC3Dfloat x,
- WebKit::WGC3Dfloat y,
- WebKit::WGC3Dfloat z) {}
- virtual void vertexAttrib3fv(
- WebKit::WGC3Duint index,
- const WebKit::WGC3Dfloat* values) {}
- virtual void vertexAttrib4f(
- WebKit::WGC3Duint index,
- WebKit::WGC3Dfloat x,
- WebKit::WGC3Dfloat y,
- WebKit::WGC3Dfloat z,
- WebKit::WGC3Dfloat w) {}
- virtual void vertexAttrib4fv(
- WebKit::WGC3Duint index,
- const WebKit::WGC3Dfloat* values) {}
- virtual void vertexAttribPointer(
- WebKit::WGC3Duint index,
- WebKit::WGC3Dint size,
- WebKit::WGC3Denum type,
- WebKit::WGC3Dboolean normalized,
- WebKit::WGC3Dsizei stride,
- WebKit::WGC3Dintptr offset) {}
-
- virtual void viewport(
- WebKit::WGC3Dint x,
- WebKit::WGC3Dint y,
- WebKit::WGC3Dsizei width,
- WebKit::WGC3Dsizei height) {}
-
- virtual WebKit::WebGLId createBuffer();
- virtual WebKit::WebGLId createFramebuffer();
- virtual WebKit::WebGLId createProgram();
- virtual WebKit::WebGLId createRenderbuffer();
- virtual WebKit::WebGLId createShader(WebKit::WGC3Denum);
- virtual WebKit::WebGLId createTexture();
-
- virtual void deleteBuffer(WebKit::WebGLId id);
- virtual void deleteFramebuffer(WebKit::WebGLId id);
- virtual void deleteProgram(WebKit::WebGLId id);
- virtual void deleteRenderbuffer(WebKit::WebGLId id);
- virtual void deleteShader(WebKit::WebGLId id);
- virtual void deleteTexture(WebKit::WebGLId texture_id);
-
- virtual void texStorage2DEXT(
- WebKit::WGC3Denum target,
- WebKit::WGC3Dint levels,
- WebKit::WGC3Duint internalformat,
- WebKit::WGC3Dint width,
- WebKit::WGC3Dint height) {}
-
- virtual WebKit::WebGLId createQueryEXT();
- virtual void deleteQueryEXT(WebKit::WebGLId query) {}
- virtual WebKit::WGC3Dboolean isQueryEXT(WebKit::WebGLId query);
- virtual void beginQueryEXT(
- WebKit::WGC3Denum target,
- WebKit::WebGLId query) {}
- virtual void endQueryEXT(WebKit::WGC3Denum target);
- virtual void getQueryivEXT(
- WebKit::WGC3Denum target,
- WebKit::WGC3Denum pname,
- WebKit::WGC3Dint* params) {}
- virtual void getQueryObjectuivEXT(
- WebKit::WebGLId query,
- WebKit::WGC3Denum pname,
- WebKit::WGC3Duint* params);
-
- virtual void setContextLostCallback(
- WebGraphicsContextLostCallback* callback);
-
- virtual void loseContextCHROMIUM(WebKit::WGC3Denum current,
- WebKit::WGC3Denum other);
-
- virtual void drawBuffersEXT(WebKit::WGC3Dsizei m,
- const WebKit::WGC3Denum* bufs) {}
-
- virtual void bindTexImage2DCHROMIUM(WebKit::WGC3Denum target,
- WebKit::WGC3Dint image_id) {}
-
- // GL_CHROMIUM_gpu_memory_buffer
- virtual WebKit::WGC3Duint createImageCHROMIUM(
- WebKit::WGC3Dsizei width,
- WebKit::WGC3Dsizei height,
- WebKit::WGC3Denum internalformat);
- virtual void destroyImageCHROMIUM(WebKit::WGC3Duint image_id) {}
- virtual void getImageParameterivCHROMIUM(
- WebKit::WGC3Duint image_id,
- WebKit::WGC3Denum pname,
- WebKit::WGC3Dint* params) {}
- virtual void* mapImageCHROMIUM(
- WebKit::WGC3Duint image_id,
- WebKit::WGC3Denum access);
- virtual void unmapImageCHROMIUM(WebKit::WGC3Duint image_id) {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(FakeWebGraphicsContext3D);
-};
-
-} // namespace cc
-
-#endif // CC_DEBUG_FAKE_WEB_GRAPHICS_CONTEXT_3D_H_
diff --git a/chromium/cc/debug/layer_tree_debug_state.cc b/chromium/cc/debug/layer_tree_debug_state.cc
index 72c3a9ff18c..95245e0f0b2 100644
--- a/chromium/cc/debug/layer_tree_debug_state.cc
+++ b/chromium/cc/debug/layer_tree_debug_state.cc
@@ -23,6 +23,7 @@ LayerTreeDebugState::LayerTreeDebugState()
show_touch_event_handler_rects(false),
show_wheel_event_handler_rects(false),
show_non_fast_scrollable_rects(false),
+ show_layer_animation_bounds_rects(false),
slow_down_raster_scale_factor(0),
rasterize_only_visible_content(false),
show_picture_borders(false),
@@ -48,7 +49,8 @@ bool LayerTreeDebugState::ShowHudRects() const {
show_surface_damage_rects || show_screen_space_rects ||
show_replica_screen_space_rects || show_occluding_rects ||
show_non_occluding_rects || show_touch_event_handler_rects ||
- show_wheel_event_handler_rects || show_non_fast_scrollable_rects;
+ show_wheel_event_handler_rects || show_non_fast_scrollable_rects ||
+ show_layer_animation_bounds_rects;
}
bool LayerTreeDebugState::ShowMemoryStats() const {
@@ -74,6 +76,8 @@ bool LayerTreeDebugState::Equal(const LayerTreeDebugState& a,
b.show_wheel_event_handler_rects &&
a.show_non_fast_scrollable_rects ==
b.show_non_fast_scrollable_rects &&
+ a.show_layer_animation_bounds_rects ==
+ b.show_layer_animation_bounds_rects &&
a.slow_down_raster_scale_factor == b.slow_down_raster_scale_factor &&
a.rasterize_only_visible_content ==
b.rasterize_only_visible_content &&
@@ -99,6 +103,7 @@ LayerTreeDebugState LayerTreeDebugState::Unite(const LayerTreeDebugState& a,
r.show_touch_event_handler_rects |= b.show_touch_event_handler_rects;
r.show_wheel_event_handler_rects |= b.show_wheel_event_handler_rects;
r.show_non_fast_scrollable_rects |= b.show_non_fast_scrollable_rects;
+ r.show_layer_animation_bounds_rects |= b.show_layer_animation_bounds_rects;
if (b.slow_down_raster_scale_factor)
r.slow_down_raster_scale_factor = b.slow_down_raster_scale_factor;
diff --git a/chromium/cc/debug/layer_tree_debug_state.h b/chromium/cc/debug/layer_tree_debug_state.h
index 1233a4e36f0..24196de13d6 100644
--- a/chromium/cc/debug/layer_tree_debug_state.h
+++ b/chromium/cc/debug/layer_tree_debug_state.h
@@ -29,6 +29,7 @@ class CC_EXPORT LayerTreeDebugState {
bool show_touch_event_handler_rects;
bool show_wheel_event_handler_rects;
bool show_non_fast_scrollable_rects;
+ bool show_layer_animation_bounds_rects;
int slow_down_raster_scale_factor;
bool rasterize_only_visible_content;
diff --git a/chromium/cc/debug/micro_benchmark.cc b/chromium/cc/debug/micro_benchmark.cc
new file mode 100644
index 00000000000..464d0cb625d
--- /dev/null
+++ b/chromium/cc/debug/micro_benchmark.cc
@@ -0,0 +1,54 @@
+// 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/micro_benchmark.h"
+
+#include "base/callback.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/values.h"
+#include "cc/debug/micro_benchmark_impl.h"
+
+namespace cc {
+
+MicroBenchmark::MicroBenchmark(const DoneCallback& callback)
+ : callback_(callback),
+ is_done_(false),
+ processed_for_benchmark_impl_(false) {}
+
+MicroBenchmark::~MicroBenchmark() {}
+
+bool MicroBenchmark::IsDone() const {
+ return is_done_;
+}
+
+void MicroBenchmark::DidUpdateLayers(LayerTreeHost* host) {}
+
+void MicroBenchmark::NotifyDone(scoped_ptr<base::Value> result) {
+ callback_.Run(result.Pass());
+ is_done_ = true;
+}
+
+void MicroBenchmark::RunOnLayer(Layer* layer) {}
+
+void MicroBenchmark::RunOnLayer(PictureLayer* layer) {}
+
+bool MicroBenchmark::ProcessedForBenchmarkImpl() const {
+ return processed_for_benchmark_impl_;
+}
+
+scoped_ptr<MicroBenchmarkImpl> MicroBenchmark::GetBenchmarkImpl(
+ scoped_refptr<base::MessageLoopProxy> origin_loop) {
+ DCHECK(!processed_for_benchmark_impl_);
+ processed_for_benchmark_impl_ = true;
+ return CreateBenchmarkImpl(origin_loop);
+}
+
+scoped_ptr<MicroBenchmarkImpl> MicroBenchmark::CreateBenchmarkImpl(
+ scoped_refptr<base::MessageLoopProxy> origin_loop) {
+ return make_scoped_ptr<MicroBenchmarkImpl>(NULL);
+}
+
+} // namespace cc
diff --git a/chromium/cc/debug/micro_benchmark.h b/chromium/cc/debug/micro_benchmark.h
new file mode 100644
index 00000000000..f179fb9544d
--- /dev/null
+++ b/chromium/cc/debug/micro_benchmark.h
@@ -0,0 +1,54 @@
+// 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_MICRO_BENCHMARK_H_
+#define CC_DEBUG_MICRO_BENCHMARK_H_
+
+#include "base/callback.h"
+#include "base/memory/scoped_ptr.h"
+#include "cc/base/cc_export.h"
+
+namespace base {
+class Value;
+class MessageLoopProxy;
+} // namespace base
+
+namespace cc {
+
+class LayerTreeHost;
+class Layer;
+class PictureLayer;
+class MicroBenchmarkImpl;
+class CC_EXPORT MicroBenchmark {
+ public:
+ typedef base::Callback<void(scoped_ptr<base::Value>)> DoneCallback;
+
+ explicit MicroBenchmark(const DoneCallback& callback);
+ virtual ~MicroBenchmark();
+
+ bool IsDone() const;
+ virtual void DidUpdateLayers(LayerTreeHost* host);
+
+ virtual void RunOnLayer(Layer* layer);
+ virtual void RunOnLayer(PictureLayer* layer);
+
+ bool ProcessedForBenchmarkImpl() const;
+ scoped_ptr<MicroBenchmarkImpl> GetBenchmarkImpl(
+ scoped_refptr<base::MessageLoopProxy> origin_loop);
+
+ protected:
+ void NotifyDone(scoped_ptr<base::Value> result);
+
+ virtual scoped_ptr<MicroBenchmarkImpl> CreateBenchmarkImpl(
+ scoped_refptr<base::MessageLoopProxy> origin_loop);
+
+ private:
+ DoneCallback callback_;
+ bool is_done_;
+ bool processed_for_benchmark_impl_;
+};
+
+} // namespace cc
+
+#endif // CC_DEBUG_MICRO_BENCHMARK_H_
diff --git a/chromium/cc/debug/micro_benchmark_controller.cc b/chromium/cc/debug/micro_benchmark_controller.cc
new file mode 100644
index 00000000000..7d9025c1c42
--- /dev/null
+++ b/chromium/cc/debug/micro_benchmark_controller.cc
@@ -0,0 +1,106 @@
+// 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/micro_benchmark_controller.h"
+
+#include <string>
+
+#include "base/callback.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/values.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"
+#include "cc/trees/layer_tree_host_impl.h"
+
+namespace cc {
+
+namespace {
+
+scoped_ptr<MicroBenchmark> CreateBenchmark(
+ const std::string& name,
+ scoped_ptr<base::Value> value,
+ const MicroBenchmark::DoneCallback& callback) {
+ if (name == "picture_record_benchmark") {
+ return scoped_ptr<MicroBenchmark>(
+ new PictureRecordBenchmark(value.Pass(), callback));
+ } else if (name == "rasterize_and_record_benchmark") {
+ return scoped_ptr<MicroBenchmark>(
+ new RasterizeAndRecordBenchmark(value.Pass(), callback));
+ } else if (name == "unittest_only_benchmark") {
+ return scoped_ptr<MicroBenchmark>(
+ new UnittestOnlyBenchmark(value.Pass(), callback));
+ }
+ return scoped_ptr<MicroBenchmark>();
+}
+
+class IsDonePredicate {
+ public:
+ typedef const MicroBenchmark* argument_type;
+ typedef bool result_type;
+
+ result_type operator()(argument_type benchmark) const {
+ return benchmark->IsDone();
+ }
+};
+
+} // namespace
+
+MicroBenchmarkController::MicroBenchmarkController(LayerTreeHost* host)
+ : host_(host),
+ main_controller_message_loop_(base::MessageLoopProxy::current().get()) {
+ DCHECK(host_);
+}
+
+MicroBenchmarkController::~MicroBenchmarkController() {}
+
+bool MicroBenchmarkController::ScheduleRun(
+ const std::string& micro_benchmark_name,
+ scoped_ptr<base::Value> value,
+ const MicroBenchmark::DoneCallback& callback) {
+ scoped_ptr<MicroBenchmark> benchmark =
+ CreateBenchmark(micro_benchmark_name, value.Pass(), callback);
+ if (benchmark.get()) {
+ benchmarks_.push_back(benchmark.Pass());
+ host_->SetNeedsCommit();
+ return true;
+ }
+ return false;
+}
+
+void MicroBenchmarkController::ScheduleImplBenchmarks(
+ LayerTreeHostImpl* host_impl) {
+ for (ScopedPtrVector<MicroBenchmark>::iterator it = benchmarks_.begin();
+ it != benchmarks_.end();
+ ++it) {
+ scoped_ptr<MicroBenchmarkImpl> benchmark_impl;
+ if (!(*it)->ProcessedForBenchmarkImpl()) {
+ benchmark_impl =
+ (*it)->GetBenchmarkImpl(main_controller_message_loop_);
+ }
+
+ if (benchmark_impl.get())
+ host_impl->ScheduleMicroBenchmark(benchmark_impl.Pass());
+ }
+}
+
+void MicroBenchmarkController::DidUpdateLayers() {
+ for (ScopedPtrVector<MicroBenchmark>::iterator it = benchmarks_.begin();
+ it != benchmarks_.end();
+ ++it) {
+ if (!(*it)->IsDone())
+ (*it)->DidUpdateLayers(host_);
+ }
+
+ CleanUpFinishedBenchmarks();
+}
+
+void MicroBenchmarkController::CleanUpFinishedBenchmarks() {
+ benchmarks_.erase(
+ benchmarks_.partition(std::not1(IsDonePredicate())),
+ benchmarks_.end());
+}
+
+} // namespace cc
diff --git a/chromium/cc/debug/micro_benchmark_controller.h b/chromium/cc/debug/micro_benchmark_controller.h
new file mode 100644
index 00000000000..7220dc1778f
--- /dev/null
+++ b/chromium/cc/debug/micro_benchmark_controller.h
@@ -0,0 +1,49 @@
+// 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_MICRO_BENCHMARK_CONTROLLER_H_
+#define CC_DEBUG_MICRO_BENCHMARK_CONTROLLER_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "cc/base/scoped_ptr_vector.h"
+#include "cc/debug/micro_benchmark.h"
+
+namespace base {
+class Value;
+class MessageLoopProxy;
+} // namespace base
+
+namespace cc {
+
+class LayerTreeHost;
+class LayerTreeHostImpl;
+class CC_EXPORT MicroBenchmarkController {
+ public:
+ explicit MicroBenchmarkController(LayerTreeHost* host);
+ ~MicroBenchmarkController();
+
+ void DidUpdateLayers();
+
+ bool ScheduleRun(const std::string& micro_benchmark_name,
+ scoped_ptr<base::Value> value,
+ const MicroBenchmark::DoneCallback& callback);
+
+ void ScheduleImplBenchmarks(LayerTreeHostImpl* host_impl);
+
+ private:
+ void CleanUpFinishedBenchmarks();
+
+ LayerTreeHost* host_;
+ ScopedPtrVector<MicroBenchmark> benchmarks_;
+ scoped_refptr<base::MessageLoopProxy> main_controller_message_loop_;
+
+ DISALLOW_COPY_AND_ASSIGN(MicroBenchmarkController);
+};
+
+} // namespace cc
+
+#endif // CC_DEBUG_MICRO_BENCHMARK_CONTROLLER_H_
diff --git a/chromium/cc/debug/micro_benchmark_controller_impl.cc b/chromium/cc/debug/micro_benchmark_controller_impl.cc
new file mode 100644
index 00000000000..821ba5f8d44
--- /dev/null
+++ b/chromium/cc/debug/micro_benchmark_controller_impl.cc
@@ -0,0 +1,59 @@
+// 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/micro_benchmark_controller_impl.h"
+
+#include <string>
+
+#include "base/callback.h"
+#include "base/values.h"
+#include "cc/trees/layer_tree_host_impl.h"
+
+namespace cc {
+
+namespace {
+
+class IsDonePredicate {
+ public:
+ typedef const MicroBenchmarkImpl* argument_type;
+ typedef bool result_type;
+
+ result_type operator()(argument_type benchmark) const {
+ return benchmark->IsDone();
+ }
+};
+
+} // namespace
+
+MicroBenchmarkControllerImpl::MicroBenchmarkControllerImpl(
+ LayerTreeHostImpl* host)
+ : host_(host) {
+ DCHECK(host_);
+}
+
+MicroBenchmarkControllerImpl::~MicroBenchmarkControllerImpl() {}
+
+void MicroBenchmarkControllerImpl::ScheduleRun(
+ scoped_ptr<MicroBenchmarkImpl> benchmark) {
+ benchmarks_.push_back(benchmark.Pass());
+}
+
+void MicroBenchmarkControllerImpl::DidCompleteCommit() {
+ for (ScopedPtrVector<MicroBenchmarkImpl>::iterator it = benchmarks_.begin();
+ it != benchmarks_.end();
+ ++it) {
+ DCHECK(!(*it)->IsDone());
+ (*it)->DidCompleteCommit(host_);
+ }
+
+ CleanUpFinishedBenchmarks();
+}
+
+void MicroBenchmarkControllerImpl::CleanUpFinishedBenchmarks() {
+ benchmarks_.erase(
+ benchmarks_.partition(std::not1(IsDonePredicate())),
+ benchmarks_.end());
+}
+
+} // namespace cc
diff --git a/chromium/cc/debug/micro_benchmark_controller_impl.h b/chromium/cc/debug/micro_benchmark_controller_impl.h
new file mode 100644
index 00000000000..734bf63ce6b
--- /dev/null
+++ b/chromium/cc/debug/micro_benchmark_controller_impl.h
@@ -0,0 +1,37 @@
+// 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_MICRO_BENCHMARK_CONTROLLER_IMPL_H_
+#define CC_DEBUG_MICRO_BENCHMARK_CONTROLLER_IMPL_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "cc/base/scoped_ptr_vector.h"
+#include "cc/debug/micro_benchmark_impl.h"
+
+namespace cc {
+
+class LayerTreeHostImpl;
+class CC_EXPORT MicroBenchmarkControllerImpl {
+ public:
+ explicit MicroBenchmarkControllerImpl(LayerTreeHostImpl* host);
+ ~MicroBenchmarkControllerImpl();
+
+ void DidCompleteCommit();
+
+ void ScheduleRun(scoped_ptr<MicroBenchmarkImpl> benchmark);
+
+ private:
+ void CleanUpFinishedBenchmarks();
+
+ LayerTreeHostImpl* host_;
+ ScopedPtrVector<MicroBenchmarkImpl> benchmarks_;
+
+ DISALLOW_COPY_AND_ASSIGN(MicroBenchmarkControllerImpl);
+};
+
+} // namespace cc
+
+#endif // CC_DEBUG_MICRO_BENCHMARK_CONTROLLER_IMPL_H_
diff --git a/chromium/cc/debug/micro_benchmark_controller_unittest.cc b/chromium/cc/debug/micro_benchmark_controller_unittest.cc
new file mode 100644
index 00000000000..4894947a6da
--- /dev/null
+++ b/chromium/cc/debug/micro_benchmark_controller_unittest.cc
@@ -0,0 +1,141 @@
+// 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/callback.h"
+#include "base/memory/scoped_ptr.h"
+#include "cc/debug/micro_benchmark.h"
+#include "cc/debug/micro_benchmark_controller.h"
+#include "cc/layers/layer.h"
+#include "cc/resources/resource_update_queue.h"
+#include "cc/test/fake_layer_tree_host.h"
+#include "cc/test/fake_layer_tree_host_impl.h"
+#include "cc/test/fake_proxy.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace cc {
+namespace {
+
+class MicroBenchmarkControllerTest : public testing::Test {
+ public:
+ virtual void SetUp() OVERRIDE {
+ impl_proxy_ = make_scoped_ptr(new FakeImplProxy);
+ layer_tree_host_impl_ =
+ make_scoped_ptr(new FakeLayerTreeHostImpl(impl_proxy_.get()));
+
+ layer_tree_host_ = FakeLayerTreeHost::Create();
+ layer_tree_host_->SetRootLayer(Layer::Create());
+ layer_tree_host_->InitializeForTesting(scoped_ptr<Proxy>(new FakeProxy));
+ }
+
+ virtual void TearDown() OVERRIDE {
+ layer_tree_host_impl_.reset();
+ layer_tree_host_.reset();
+ impl_proxy_.reset();
+ }
+
+ scoped_ptr<FakeLayerTreeHost> layer_tree_host_;
+ scoped_ptr<FakeLayerTreeHostImpl> layer_tree_host_impl_;
+ scoped_ptr<FakeImplProxy> impl_proxy_;
+};
+
+void Noop(scoped_ptr<base::Value> value) {
+}
+
+void IncrementCallCount(int* count, scoped_ptr<base::Value> value) {
+ ++(*count);
+}
+
+TEST_F(MicroBenchmarkControllerTest, ScheduleFail) {
+ bool result = layer_tree_host_->ScheduleMicroBenchmark(
+ "non_existant_benchmark", scoped_ptr<base::Value>(), base::Bind(&Noop));
+ EXPECT_FALSE(result);
+}
+
+TEST_F(MicroBenchmarkControllerTest, CommitScheduled) {
+ EXPECT_FALSE(layer_tree_host_->needs_commit());
+ bool result = layer_tree_host_->ScheduleMicroBenchmark(
+ "unittest_only_benchmark", scoped_ptr<base::Value>(), base::Bind(&Noop));
+ EXPECT_TRUE(result);
+ EXPECT_TRUE(layer_tree_host_->needs_commit());
+}
+
+TEST_F(MicroBenchmarkControllerTest, BenchmarkRan) {
+ int run_count = 0;
+ bool result = layer_tree_host_->ScheduleMicroBenchmark(
+ "unittest_only_benchmark",
+ scoped_ptr<base::Value>(),
+ base::Bind(&IncrementCallCount, base::Unretained(&run_count)));
+ EXPECT_TRUE(result);
+
+ scoped_ptr<ResourceUpdateQueue> queue(new ResourceUpdateQueue);
+ layer_tree_host_->SetOutputSurfaceLostForTesting(false);
+ layer_tree_host_->UpdateLayers(queue.get());
+
+ EXPECT_EQ(1, run_count);
+}
+
+TEST_F(MicroBenchmarkControllerTest, MultipleBenchmarkRan) {
+ int run_count = 0;
+ bool result = layer_tree_host_->ScheduleMicroBenchmark(
+ "unittest_only_benchmark",
+ scoped_ptr<base::Value>(),
+ base::Bind(&IncrementCallCount, base::Unretained(&run_count)));
+ EXPECT_TRUE(result);
+ result = layer_tree_host_->ScheduleMicroBenchmark(
+ "unittest_only_benchmark",
+ scoped_ptr<base::Value>(),
+ base::Bind(&IncrementCallCount, base::Unretained(&run_count)));
+ EXPECT_TRUE(result);
+
+ scoped_ptr<ResourceUpdateQueue> queue(new ResourceUpdateQueue);
+ layer_tree_host_->SetOutputSurfaceLostForTesting(false);
+ layer_tree_host_->UpdateLayers(queue.get());
+
+ EXPECT_EQ(2, run_count);
+
+ result = layer_tree_host_->ScheduleMicroBenchmark(
+ "unittest_only_benchmark",
+ scoped_ptr<base::Value>(),
+ base::Bind(&IncrementCallCount, base::Unretained(&run_count)));
+ EXPECT_TRUE(result);
+ result = layer_tree_host_->ScheduleMicroBenchmark(
+ "unittest_only_benchmark",
+ scoped_ptr<base::Value>(),
+ base::Bind(&IncrementCallCount, base::Unretained(&run_count)));
+ EXPECT_TRUE(result);
+
+ layer_tree_host_->UpdateLayers(queue.get());
+ EXPECT_EQ(4, run_count);
+
+ layer_tree_host_->UpdateLayers(queue.get());
+ EXPECT_EQ(4, run_count);
+}
+
+TEST_F(MicroBenchmarkControllerTest, BenchmarkImplRan) {
+ int run_count = 0;
+ scoped_ptr<base::DictionaryValue> settings(new base::DictionaryValue);
+ settings->SetBoolean("run_benchmark_impl", true);
+
+ // Schedule a main thread benchmark.
+ bool result = layer_tree_host_->ScheduleMicroBenchmark(
+ "unittest_only_benchmark",
+ settings.PassAs<base::Value>(),
+ base::Bind(&IncrementCallCount, base::Unretained(&run_count)));
+ EXPECT_TRUE(result);
+
+ // Schedule impl benchmarks. In production code, this is run in commit.
+ layer_tree_host_->GetMicroBenchmarkController()->ScheduleImplBenchmarks(
+ layer_tree_host_impl_.get());
+
+ // Now complete the commit (as if on the impl thread).
+ layer_tree_host_impl_->CommitComplete();
+
+ // Make sure all posted messages run.
+ base::MessageLoop::current()->RunUntilIdle();
+
+ EXPECT_EQ(1, run_count);
+}
+
+} // namespace
+} // namespace cc
diff --git a/chromium/cc/debug/micro_benchmark_impl.cc b/chromium/cc/debug/micro_benchmark_impl.cc
new file mode 100644
index 00000000000..7ec58c8de0b
--- /dev/null
+++ b/chromium/cc/debug/micro_benchmark_impl.cc
@@ -0,0 +1,48 @@
+// 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/micro_benchmark_impl.h"
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "base/values.h"
+
+namespace cc {
+
+namespace {
+
+void RunCallback(const MicroBenchmarkImpl::DoneCallback& callback,
+ scoped_ptr<base::Value> result) {
+ callback.Run(result.Pass());
+}
+
+}
+
+MicroBenchmarkImpl::MicroBenchmarkImpl(
+ const DoneCallback& callback,
+ scoped_refptr<base::MessageLoopProxy> origin_loop)
+ : callback_(callback), is_done_(false), origin_loop_(origin_loop) {}
+
+MicroBenchmarkImpl::~MicroBenchmarkImpl() {}
+
+bool MicroBenchmarkImpl::IsDone() const {
+ return is_done_;
+}
+
+void MicroBenchmarkImpl::DidCompleteCommit(LayerTreeHostImpl* host) {}
+
+void MicroBenchmarkImpl::NotifyDone(scoped_ptr<base::Value> result) {
+ origin_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(RunCallback, callback_, base::Passed(&result)));
+ is_done_ = true;
+}
+
+void MicroBenchmarkImpl::RunOnLayer(LayerImpl* layer) {}
+
+void MicroBenchmarkImpl::RunOnLayer(PictureLayerImpl* layer) {}
+
+} // namespace cc
diff --git a/chromium/cc/debug/micro_benchmark_impl.h b/chromium/cc/debug/micro_benchmark_impl.h
new file mode 100644
index 00000000000..4f3f74f6516
--- /dev/null
+++ b/chromium/cc/debug/micro_benchmark_impl.h
@@ -0,0 +1,48 @@
+// 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_MICRO_BENCHMARK_IMPL_H_
+#define CC_DEBUG_MICRO_BENCHMARK_IMPL_H_
+
+#include "base/callback.h"
+#include "base/memory/scoped_ptr.h"
+#include "cc/base/cc_export.h"
+
+namespace base {
+class Value;
+class MessageLoopProxy;
+} // namespace base
+
+namespace cc {
+
+class LayerTreeHostImpl;
+class LayerImpl;
+class PictureLayerImpl;
+class CC_EXPORT MicroBenchmarkImpl {
+ public:
+ typedef base::Callback<void(scoped_ptr<base::Value>)> DoneCallback;
+
+ explicit MicroBenchmarkImpl(
+ const DoneCallback& callback,
+ scoped_refptr<base::MessageLoopProxy> origin_loop);
+ virtual ~MicroBenchmarkImpl();
+
+ bool IsDone() const;
+ virtual void DidCompleteCommit(LayerTreeHostImpl* host);
+
+ virtual void RunOnLayer(LayerImpl* layer);
+ virtual void RunOnLayer(PictureLayerImpl* layer);
+
+ protected:
+ void NotifyDone(scoped_ptr<base::Value> result);
+
+ private:
+ DoneCallback callback_;
+ bool is_done_;
+ scoped_refptr<base::MessageLoopProxy> origin_loop_;
+};
+
+} // namespace cc
+
+#endif // CC_DEBUG_MICRO_BENCHMARK_IMPL_H_
diff --git a/chromium/cc/debug/picture_record_benchmark.cc b/chromium/cc/debug/picture_record_benchmark.cc
new file mode 100644
index 00000000000..430d1d0bcd9
--- /dev/null
+++ b/chromium/cc/debug/picture_record_benchmark.cc
@@ -0,0 +1,126 @@
+// 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/trees/layer_tree_host.h"
+#include "cc/trees/layer_tree_host_common.h"
+#include "ui/gfx/rect.h"
+
+namespace cc {
+
+namespace {
+
+const int kPositionIncrement = 100;
+const int kTileGridSize = 512;
+const int kTileGridBorder = 1;
+
+} // namespace
+
+PictureRecordBenchmark::PictureRecordBenchmark(
+ scoped_ptr<base::Value> value,
+ const MicroBenchmark::DoneCallback& callback)
+ : MicroBenchmark(callback) {
+ if (!value)
+ return;
+
+ base::ListValue* list = NULL;
+ value->GetAsList(&list);
+ if (!list)
+ return;
+
+ for (base::ListValue::iterator it = list->begin(); it != list->end(); ++it) {
+ base::DictionaryValue* dictionary = NULL;
+ (*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(),
+ base::Bind(&PictureRecordBenchmark::Run, base::Unretained(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.PassAs<base::Value>());
+}
+
+void PictureRecordBenchmark::Run(Layer* layer) {
+ layer->RunMicroBenchmark(this);
+}
+
+void PictureRecordBenchmark::RunOnLayer(PictureLayer* layer) {
+ ContentLayerClient* painter = layer->client();
+ gfx::Size content_bounds = layer->content_bounds();
+
+ SkTileGridPicture::TileGridInfo tile_grid_info;
+ tile_grid_info.fTileInterval.set(kTileGridSize - 2 * kTileGridBorder,
+ kTileGridSize - 2 * kTileGridBorder);
+ tile_grid_info.fMargin.set(kTileGridBorder, kTileGridBorder);
+ tile_grid_info.fOffset.set(-kTileGridBorder, -kTileGridBorder);
+
+ 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, content_bounds.height() - height);
+ int x_limit = std::max(1, content_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::HighResNow();
+
+ scoped_refptr<Picture> picture = Picture::Create(rect);
+ picture->Record(painter, tile_grid_info);
+
+ base::TimeTicks end = base::TimeTicks::HighResNow();
+ 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
new file mode 100644
index 00000000000..89f2bc0781e
--- /dev/null
+++ b/chromium/cc/debug/picture_record_benchmark.h
@@ -0,0 +1,39 @@
+// 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);
+ virtual ~PictureRecordBenchmark();
+
+ // Implements MicroBenchmark interface.
+ virtual void DidUpdateLayers(LayerTreeHost* host) OVERRIDE;
+ virtual void RunOnLayer(PictureLayer* layer) OVERRIDE;
+
+ private:
+ void Run(Layer* layer);
+
+ 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
new file mode 100644
index 00000000000..4646afd6bce
--- /dev/null
+++ b/chromium/cc/debug/rasterize_and_record_benchmark.cc
@@ -0,0 +1,142 @@
+// 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/rasterize_and_record_benchmark.h"
+
+#include <algorithm>
+#include <limits>
+
+#include "base/basictypes.h"
+#include "base/values.h"
+#include "cc/debug/rasterize_and_record_benchmark_impl.h"
+#include "cc/layers/layer.h"
+#include "cc/layers/picture_layer.h"
+#include "cc/trees/layer_tree_host.h"
+#include "cc/trees/layer_tree_host_common.h"
+#include "ui/gfx/rect.h"
+
+namespace cc {
+
+namespace {
+
+const int kDefaultRecordRepeatCount = 100;
+
+base::TimeTicks Now() {
+ return base::TimeTicks::IsThreadNowSupported()
+ ? base::TimeTicks::ThreadNow()
+ : base::TimeTicks::HighResNow();
+}
+
+} // namespace
+
+RasterizeAndRecordBenchmark::RasterizeAndRecordBenchmark(
+ scoped_ptr<base::Value> value,
+ const MicroBenchmark::DoneCallback& callback)
+ : MicroBenchmark(callback),
+ record_repeat_count_(kDefaultRecordRepeatCount),
+ settings_(value.Pass()),
+ main_thread_benchmark_done_(false),
+ host_(NULL),
+ weak_ptr_factory_(this) {
+ base::DictionaryValue* settings = NULL;
+ settings_->GetAsDictionary(&settings);
+ if (!settings)
+ return;
+
+ if (settings->HasKey("record_repeat_count"))
+ settings->GetInteger("record_repeat_count", &record_repeat_count_);
+}
+
+RasterizeAndRecordBenchmark::~RasterizeAndRecordBenchmark() {
+ weak_ptr_factory_.InvalidateWeakPtrs();
+}
+
+void RasterizeAndRecordBenchmark::DidUpdateLayers(LayerTreeHost* host) {
+ host_ = host;
+ LayerTreeHostCommon::CallFunctionForSubtree(
+ host->root_layer(),
+ base::Bind(&RasterizeAndRecordBenchmark::Run, base::Unretained(this)));
+
+ DCHECK(!results_.get());
+ results_ = make_scoped_ptr(new base::DictionaryValue);
+ results_->SetInteger("pixels_recorded", record_results_.pixels_recorded);
+ results_->SetDouble("record_time_ms",
+ record_results_.total_best_time.InMillisecondsF());
+ main_thread_benchmark_done_ = true;
+}
+
+void RasterizeAndRecordBenchmark::RecordRasterResults(
+ scoped_ptr<base::Value> results_value) {
+ DCHECK(main_thread_benchmark_done_);
+
+ base::DictionaryValue* results = NULL;
+ results_value->GetAsDictionary(&results);
+
+ DCHECK(results);
+ DCHECK(results->HasKey("pixels_rasterized"));
+ DCHECK(results->HasKey("rasterize_time_ms"));
+
+ int pixels_rasterized;
+ results->GetInteger("pixels_rasterized", &pixels_rasterized);
+ double rasterize_time_ms;
+ results->GetDouble("rasterize_time_ms", &rasterize_time_ms);
+
+ results_->SetInteger("pixels_rasterized", pixels_rasterized);
+ results_->SetDouble("rasterize_time_ms", rasterize_time_ms);
+
+ NotifyDone(results_.PassAs<base::Value>());
+}
+
+scoped_ptr<MicroBenchmarkImpl> RasterizeAndRecordBenchmark::CreateBenchmarkImpl(
+ scoped_refptr<base::MessageLoopProxy> origin_loop) {
+ return scoped_ptr<MicroBenchmarkImpl>(new RasterizeAndRecordBenchmarkImpl(
+ origin_loop,
+ settings_.get(),
+ base::Bind(&RasterizeAndRecordBenchmark::RecordRasterResults,
+ weak_ptr_factory_.GetWeakPtr())));
+}
+
+void RasterizeAndRecordBenchmark::Run(Layer* layer) {
+ layer->RunMicroBenchmark(this);
+}
+
+void RasterizeAndRecordBenchmark::RunOnLayer(PictureLayer* layer) {
+ ContentLayerClient* painter = layer->client();
+ gfx::Size content_bounds = layer->content_bounds();
+
+ DCHECK(host_);
+ gfx::Size tile_grid_size = host_->settings().default_tile_size;
+
+ SkTileGridPicture::TileGridInfo tile_grid_info;
+ PicturePileBase::ComputeTileGridInfo(tile_grid_size, &tile_grid_info);
+
+ gfx::Rect visible_content_rect = gfx::ScaleToEnclosingRect(
+ layer->visible_content_rect(), 1.f / layer->contents_scale_x());
+ if (visible_content_rect.IsEmpty())
+ return;
+
+ scoped_refptr<Picture> picture = Picture::Create(visible_content_rect);
+
+ base::TimeDelta min_time =
+ base::TimeDelta::FromInternalValue(std::numeric_limits<int64>::max());
+ for (int i = 0; i < record_repeat_count_; ++i) {
+ base::TimeTicks start = Now();
+ picture->Record(painter, tile_grid_info);
+ base::TimeTicks end = Now();
+ base::TimeDelta duration = end - start;
+ if (duration < min_time)
+ min_time = duration;
+ }
+
+ record_results_.pixels_recorded +=
+ visible_content_rect.width() * visible_content_rect.height();
+ record_results_.total_best_time += min_time;
+}
+
+RasterizeAndRecordBenchmark::RecordResults::RecordResults()
+ : pixels_recorded(0) {}
+
+RasterizeAndRecordBenchmark::RecordResults::~RecordResults() {}
+
+} // namespace cc
diff --git a/chromium/cc/debug/rasterize_and_record_benchmark.h b/chromium/cc/debug/rasterize_and_record_benchmark.h
new file mode 100644
index 00000000000..2cea16a2f4e
--- /dev/null
+++ b/chromium/cc/debug/rasterize_and_record_benchmark.h
@@ -0,0 +1,66 @@
+// 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_RASTERIZE_AND_RECORD_BENCHMARK_H_
+#define CC_DEBUG_RASTERIZE_AND_RECORD_BENCHMARK_H_
+
+#include <map>
+#include <utility>
+#include <vector>
+
+#include "base/memory/weak_ptr.h"
+#include "base/time/time.h"
+#include "cc/debug/micro_benchmark_controller.h"
+
+namespace base {
+class DictionaryValue;
+}
+
+namespace cc {
+
+class LayerTreeHost;
+class Layer;
+class RasterizeAndRecordBenchmark : public MicroBenchmark {
+ public:
+ explicit RasterizeAndRecordBenchmark(
+ scoped_ptr<base::Value> value,
+ const MicroBenchmark::DoneCallback& callback);
+ virtual ~RasterizeAndRecordBenchmark();
+
+ // Implements MicroBenchmark interface.
+ virtual void DidUpdateLayers(LayerTreeHost* host) OVERRIDE;
+ virtual void RunOnLayer(PictureLayer* layer) OVERRIDE;
+
+ virtual scoped_ptr<MicroBenchmarkImpl> CreateBenchmarkImpl(
+ scoped_refptr<base::MessageLoopProxy> origin_loop) OVERRIDE;
+
+ private:
+ void Run(Layer* layer);
+
+ void RecordRasterResults(scoped_ptr<base::Value> results);
+
+ struct RecordResults {
+ RecordResults();
+ ~RecordResults();
+
+ int pixels_recorded;
+ base::TimeDelta total_best_time;
+ };
+
+ RecordResults record_results_;
+ int record_repeat_count_;
+ scoped_ptr<base::Value> settings_;
+ scoped_ptr<base::DictionaryValue> results_;
+
+ // The following is used in DCHECKs.
+ bool main_thread_benchmark_done_;
+
+ LayerTreeHost* host_;
+
+ base::WeakPtrFactory<RasterizeAndRecordBenchmark> weak_ptr_factory_;
+};
+
+} // namespace cc
+
+#endif // CC_DEBUG_RASTERIZE_AND_RECORD_BENCHMARK_H_
diff --git a/chromium/cc/debug/rasterize_and_record_benchmark_impl.cc b/chromium/cc/debug/rasterize_and_record_benchmark_impl.cc
new file mode 100644
index 00000000000..f2904a3bebf
--- /dev/null
+++ b/chromium/cc/debug/rasterize_and_record_benchmark_impl.cc
@@ -0,0 +1,120 @@
+// 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/rasterize_and_record_benchmark_impl.h"
+
+#include <algorithm>
+#include <limits>
+
+#include "base/basictypes.h"
+#include "base/values.h"
+#include "cc/layers/layer_impl.h"
+#include "cc/layers/picture_layer_impl.h"
+#include "cc/trees/layer_tree_host_common.h"
+#include "cc/trees/layer_tree_host_impl.h"
+#include "ui/gfx/rect.h"
+
+namespace cc {
+
+namespace {
+
+const int kDefaultRasterizeRepeatCount = 100;
+
+base::TimeTicks Now() {
+ return base::TimeTicks::IsThreadNowSupported()
+ ? base::TimeTicks::ThreadNow()
+ : base::TimeTicks::HighResNow();
+}
+
+} // namespace
+
+RasterizeAndRecordBenchmarkImpl::RasterizeAndRecordBenchmarkImpl(
+ scoped_refptr<base::MessageLoopProxy> origin_loop,
+ base::Value* value,
+ const MicroBenchmarkImpl::DoneCallback& callback)
+ : MicroBenchmarkImpl(callback, origin_loop),
+ rasterize_repeat_count_(kDefaultRasterizeRepeatCount) {
+ base::DictionaryValue* settings = NULL;
+ value->GetAsDictionary(&settings);
+ if (!settings)
+ return;
+
+ if (settings->HasKey("rasterize_repeat_count"))
+ settings->GetInteger("rasterize_repeat_count", &rasterize_repeat_count_);
+}
+
+RasterizeAndRecordBenchmarkImpl::~RasterizeAndRecordBenchmarkImpl() {}
+
+void RasterizeAndRecordBenchmarkImpl::DidCompleteCommit(
+ LayerTreeHostImpl* host) {
+ LayerTreeHostCommon::CallFunctionForSubtree(
+ host->RootLayer(),
+ base::Bind(&RasterizeAndRecordBenchmarkImpl::Run,
+ base::Unretained(this)));
+
+ scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue());
+ result->SetInteger("pixels_rasterized", rasterize_results_.pixels_rasterized);
+ result->SetDouble("rasterize_time_ms",
+ rasterize_results_.total_best_time.InMillisecondsF());
+
+ NotifyDone(result.PassAs<base::Value>());
+}
+
+void RasterizeAndRecordBenchmarkImpl::Run(LayerImpl* layer) {
+ layer->RunMicroBenchmark(this);
+}
+
+void RasterizeAndRecordBenchmarkImpl::RunOnLayer(PictureLayerImpl* layer) {
+ if (layer->visible_content_rect().IsEmpty())
+ return;
+
+ PictureLayerTilingSet tiling_set(layer, layer->content_bounds());
+
+ PictureLayerTiling* tiling = tiling_set.AddTiling(layer->contents_scale_x());
+ tiling->CreateAllTilesForTesting();
+ for (PictureLayerTiling::CoverageIterator it(
+ tiling, layer->contents_scale_x(), layer->visible_content_rect());
+ it;
+ ++it) {
+ DCHECK(*it);
+
+ PicturePileImpl* picture_pile = (*it)->picture_pile();
+ gfx::Rect content_rect = (*it)->content_rect();
+ float contents_scale = (*it)->contents_scale();
+
+ base::TimeDelta min_time =
+ base::TimeDelta::FromInternalValue(std::numeric_limits<int64>::max());
+ for (int i = 0; i < rasterize_repeat_count_; ++i) {
+ SkBitmap bitmap;
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config,
+ content_rect.width(),
+ content_rect.height());
+ bitmap.allocPixels();
+
+ SkBitmapDevice device(bitmap);
+ SkCanvas canvas(&device);
+ PicturePileImpl::Analysis analysis;
+
+ base::TimeTicks start = Now();
+ picture_pile->AnalyzeInRect(
+ content_rect, contents_scale, &analysis, NULL);
+ picture_pile->RasterToBitmap(&canvas, content_rect, contents_scale, NULL);
+ base::TimeTicks end = Now();
+ base::TimeDelta duration = end - start;
+ if (duration < min_time)
+ min_time = duration;
+ }
+
+ rasterize_results_.pixels_rasterized +=
+ content_rect.width() * content_rect.height();
+ rasterize_results_.total_best_time += min_time;
+ }
+}
+
+RasterizeAndRecordBenchmarkImpl::RasterizeResults::RasterizeResults()
+ : pixels_rasterized(0) {}
+
+RasterizeAndRecordBenchmarkImpl::RasterizeResults::~RasterizeResults() {}
+
+} // namespace cc
diff --git a/chromium/cc/debug/rasterize_and_record_benchmark_impl.h b/chromium/cc/debug/rasterize_and_record_benchmark_impl.h
new file mode 100644
index 00000000000..0f9de9ba4f4
--- /dev/null
+++ b/chromium/cc/debug/rasterize_and_record_benchmark_impl.h
@@ -0,0 +1,49 @@
+// 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_RASTERIZE_AND_RECORD_BENCHMARK_IMPL_H_
+#define CC_DEBUG_RASTERIZE_AND_RECORD_BENCHMARK_IMPL_H_
+
+#include <map>
+#include <utility>
+#include <vector>
+
+#include "base/time/time.h"
+#include "cc/debug/micro_benchmark_impl.h"
+
+namespace cc {
+
+class LayerTreeHostImpl;
+class PictureLayerImpl;
+class LayerImpl;
+class RasterizeAndRecordBenchmarkImpl : public MicroBenchmarkImpl {
+ public:
+ explicit RasterizeAndRecordBenchmarkImpl(
+ scoped_refptr<base::MessageLoopProxy> origin_loop,
+ base::Value* value,
+ const MicroBenchmarkImpl::DoneCallback& callback);
+ virtual ~RasterizeAndRecordBenchmarkImpl();
+
+ // Implements MicroBenchmark interface.
+ virtual void DidCompleteCommit(LayerTreeHostImpl* host) OVERRIDE;
+ virtual void RunOnLayer(PictureLayerImpl* layer) OVERRIDE;
+
+ private:
+ void Run(LayerImpl* layer);
+
+ struct RasterizeResults {
+ RasterizeResults();
+ ~RasterizeResults();
+
+ int pixels_rasterized;
+ base::TimeDelta total_best_time;
+ };
+
+ RasterizeResults rasterize_results_;
+ int rasterize_repeat_count_;
+};
+
+} // namespace cc
+
+#endif // CC_DEBUG_RASTERIZE_AND_RECORD_BENCHMARK_IMPL_H_
diff --git a/chromium/cc/debug/rendering_stats.cc b/chromium/cc/debug/rendering_stats.cc
index 64cf69e0fe3..abce5ae562b 100644
--- a/chromium/cc/debug/rendering_stats.cc
+++ b/chromium/cc/debug/rendering_stats.cc
@@ -8,184 +8,67 @@
namespace cc {
MainThreadRenderingStats::MainThreadRenderingStats()
- : animation_frame_count(0),
- screen_frame_count(0),
- commit_count(0),
- painted_pixel_count(0),
- recorded_pixel_count(0),
- image_gathering_count(0) {}
+ : frame_count(0),
+ painted_pixel_count(0),
+ recorded_pixel_count(0) {}
-ImplThreadRenderingStats::ImplThreadRenderingStats()
- : screen_frame_count(0),
- dropped_frame_count(0),
- rasterized_pixel_count(0),
- impl_thread_scroll_count(0),
- main_thread_scroll_count(0),
- drawn_layer_count(0),
- missing_tile_count(0),
- deferred_image_decode_count(0),
- deferred_image_cache_hit_count(0),
- tile_analysis_count(0),
- solid_color_tile_analysis_count(0) {}
-
-void RenderingStats::EnumerateFields(Enumerator* enumerator) const {
- enumerator->AddInt64("numAnimationFrames",
- main_stats.animation_frame_count);
- enumerator->AddInt64("numFramesSentToScreen", main_stats.screen_frame_count +
- impl_stats.screen_frame_count);
- enumerator->AddDouble("totalPaintTimeInSeconds",
- main_stats.paint_time.InSecondsF());
- enumerator->AddDouble("totalRecordTimeInSeconds",
- main_stats.record_time.InSecondsF());
- enumerator->AddDouble("totalCommitTimeInSeconds",
- main_stats.commit_time.InSecondsF());
- enumerator->AddInt64("totalCommitCount", main_stats.commit_count);
- enumerator->AddInt64("totalPixelsPainted", main_stats.painted_pixel_count);
- enumerator->AddInt64("totalPixelsRecorded", main_stats.recorded_pixel_count);
- enumerator->AddInt64("totalImageGatheringCount",
- main_stats.image_gathering_count);
- enumerator->AddDouble("totalImageGatheringTimeInSeconds",
- main_stats.image_gathering_time.InSecondsF());
- enumerator->AddInt64("droppedFrameCount", impl_stats.dropped_frame_count);
- enumerator->AddDouble("totalRasterizeTimeInSeconds",
- impl_stats.rasterize_time.InSecondsF());
- enumerator->AddDouble(
- "totalRasterizeTimeForNowBinsOnPendingTree",
- impl_stats.rasterize_time_for_now_bins_on_pending_tree.InSecondsF());
- enumerator->AddDouble("bestRasterizeTimeInSeconds",
- impl_stats.best_rasterize_time.InSecondsF());
- enumerator->AddInt64("totalPixelsRasterized",
- impl_stats.rasterized_pixel_count);
- enumerator->AddInt64("numImplThreadScrolls",
- impl_stats.impl_thread_scroll_count);
- enumerator->AddInt64("numMainThreadScrolls",
- impl_stats.main_thread_scroll_count);
- enumerator->AddInt64("numLayersDrawn", impl_stats.drawn_layer_count);
- enumerator->AddInt64("numMissingTiles", impl_stats.missing_tile_count);
- enumerator->AddInt64("totalDeferredImageDecodeCount",
- impl_stats.deferred_image_decode_count);
- enumerator->AddInt64("totalTilesAnalyzed", impl_stats.tile_analysis_count);
- enumerator->AddInt64("solidColorTilesAnalyzed",
- impl_stats.solid_color_tile_analysis_count);
- enumerator->AddInt64("totalDeferredImageCacheHitCount",
- impl_stats.deferred_image_cache_hit_count);
- enumerator->AddDouble("totalDeferredImageDecodeTimeInSeconds",
- impl_stats.deferred_image_decode_time.InSecondsF());
- enumerator->AddDouble("totalTileAnalysisTimeInSeconds",
- impl_stats.tile_analysis_time.InSecondsF());
-}
-
-void MainThreadRenderingStats::IssueTraceEvent() const {
- TRACE_EVENT_INSTANT1("benchmark",
- "MainThreadRenderingStats::IssueTraceEvent",
- TRACE_EVENT_SCOPE_THREAD,
- "data", AsTraceableData());
-}
-
-scoped_ptr<base::debug::ConvertableToTraceFormat>
+scoped_refptr<base::debug::ConvertableToTraceFormat>
MainThreadRenderingStats::AsTraceableData() const {
scoped_ptr<base::DictionaryValue> record_data(new base::DictionaryValue());
- record_data->SetInteger("animation_frame_count",
- animation_frame_count);
- record_data->SetInteger("screen_frame_count",
- screen_frame_count);
- record_data->SetDouble("paint_time",
- paint_time.InSecondsF());
- record_data->SetDouble("record_time",
- record_time.InSecondsF());
- record_data->SetDouble("commit_time",
- commit_time.InSecondsF());
- record_data->SetInteger("commit_count",
- commit_count);
- record_data->SetInteger("painted_pixel_count",
- painted_pixel_count);
- record_data->SetInteger("recorded_pixel_count",
- recorded_pixel_count);
- record_data->SetInteger("image_gathering_count",
- image_gathering_count);
- record_data->SetDouble("image_gathering_time",
- image_gathering_time.InSecondsF());
+ record_data->SetInteger("frame_count", frame_count);
+ record_data->SetDouble("paint_time", paint_time.InSecondsF());
+ record_data->SetInteger("painted_pixel_count", painted_pixel_count);
+ record_data->SetDouble("record_time", record_time.InSecondsF());
+ record_data->SetInteger("recorded_pixel_count", recorded_pixel_count);
return TracedValue::FromValue(record_data.release());
}
-void ImplThreadRenderingStats::IssueTraceEvent() const {
- TRACE_EVENT_INSTANT1("benchmark",
- "ImplThreadRenderingStats::IssueTraceEvent",
- TRACE_EVENT_SCOPE_THREAD,
- "data", AsTraceableData());
+void MainThreadRenderingStats::Add(const MainThreadRenderingStats& other) {
+ frame_count += other.frame_count;
+ paint_time += other.paint_time;
+ painted_pixel_count += other.painted_pixel_count;
+ record_time += other.record_time;
+ recorded_pixel_count += other.recorded_pixel_count;
}
-scoped_ptr<base::debug::ConvertableToTraceFormat>
+ImplThreadRenderingStats::ImplThreadRenderingStats()
+ : frame_count(0),
+ rasterized_pixel_count(0) {}
+
+scoped_refptr<base::debug::ConvertableToTraceFormat>
ImplThreadRenderingStats::AsTraceableData() const {
scoped_ptr<base::DictionaryValue> record_data(new base::DictionaryValue());
- record_data->SetInteger("screen_frame_count",
- screen_frame_count);
- record_data->SetInteger("dropped_frame_count",
- dropped_frame_count);
- record_data->SetDouble("rasterize_time",
- rasterize_time.InSecondsF());
- record_data->SetDouble(
- "rasterize_time_for_now_bins_on_pending_tree",
- rasterize_time_for_now_bins_on_pending_tree.InSecondsF());
- record_data->SetDouble("best_rasterize_time",
- best_rasterize_time.InSecondsF());
- record_data->SetInteger("rasterized_pixel_count",
- rasterized_pixel_count);
- record_data->SetInteger("impl_thread_scroll_count",
- impl_thread_scroll_count);
- record_data->SetInteger("main_thread_scroll_count",
- main_thread_scroll_count);
- record_data->SetInteger("drawn_layer_count",
- drawn_layer_count);
- record_data->SetInteger("missing_tile_count",
- missing_tile_count);
- record_data->SetInteger("deferred_image_decode_count",
- deferred_image_decode_count);
- record_data->SetInteger("deferred_image_cache_hit_count",
- deferred_image_cache_hit_count);
- record_data->SetInteger("tile_analysis_count",
- tile_analysis_count);
- record_data->SetInteger("solid_color_tile_analysis_count",
- solid_color_tile_analysis_count);
- record_data->SetDouble("deferred_image_decode_time",
- deferred_image_decode_time.InSecondsF());
- record_data->SetDouble("tile_analysis_time",
- tile_analysis_time.InSecondsF());
+ record_data->SetInteger("frame_count", frame_count);
+ record_data->SetDouble("rasterize_time", rasterize_time.InSecondsF());
+ record_data->SetInteger("rasterized_pixel_count", rasterized_pixel_count);
return TracedValue::FromValue(record_data.release());
}
-
-void MainThreadRenderingStats::Add(const MainThreadRenderingStats& other) {
- animation_frame_count += other.animation_frame_count;
- screen_frame_count += other.screen_frame_count;
- paint_time += other.paint_time;
- record_time += other.record_time;
- commit_time += other.commit_time;
- commit_count += other.commit_count;
- painted_pixel_count += other.painted_pixel_count;
- recorded_pixel_count += other.recorded_pixel_count;
- image_gathering_count += other.image_gathering_count;
- image_gathering_time += other.image_gathering_time;
-}
-
void ImplThreadRenderingStats::Add(const ImplThreadRenderingStats& other) {
- screen_frame_count += other.screen_frame_count;
- dropped_frame_count += other.dropped_frame_count;
+ frame_count += other.frame_count;
rasterize_time += other.rasterize_time;
- rasterize_time_for_now_bins_on_pending_tree +=
- other.rasterize_time_for_now_bins_on_pending_tree;
- best_rasterize_time += other.best_rasterize_time;
+ analysis_time += other.analysis_time;
rasterized_pixel_count += other.rasterized_pixel_count;
- impl_thread_scroll_count += other.impl_thread_scroll_count;
- main_thread_scroll_count += other.main_thread_scroll_count;
- drawn_layer_count += other.drawn_layer_count;
- missing_tile_count += other.missing_tile_count;
- deferred_image_decode_count += other.deferred_image_decode_count;
- deferred_image_cache_hit_count += other.deferred_image_cache_hit_count;
- deferred_image_decode_time += other.deferred_image_decode_time;
- tile_analysis_count += other.tile_analysis_count;
- solid_color_tile_analysis_count += other.solid_color_tile_analysis_count;
- tile_analysis_time += other.tile_analysis_time;
+}
+
+void RenderingStats::EnumerateFields(Enumerator* enumerator) const {
+ enumerator->AddInt64("frameCount",
+ main_stats.frame_count + impl_stats.frame_count);
+ enumerator->AddDouble("paintTime",
+ main_stats.paint_time.InSecondsF());
+ enumerator->AddInt64("paintedPixelCount",
+ main_stats.painted_pixel_count);
+ enumerator->AddDouble("recordTime",
+ main_stats.record_time.InSecondsF());
+ enumerator->AddInt64("recordedPixelCount",
+ main_stats.recorded_pixel_count);
+ // Combine rasterization and analysis time as a precursor to combining
+ // them in the same step internally.
+ enumerator->AddDouble("rasterizeTime",
+ impl_stats.rasterize_time.InSecondsF() +
+ impl_stats.analysis_time.InSecondsF());
+ enumerator->AddInt64("rasterizedPixelCount",
+ impl_stats.rasterized_pixel_count);
}
void RenderingStats::Add(const RenderingStats& other) {
diff --git a/chromium/cc/debug/rendering_stats.h b/chromium/cc/debug/rendering_stats.h
index ee13706034a..d28f1107157 100644
--- a/chromium/cc/debug/rendering_stats.h
+++ b/chromium/cc/debug/rendering_stats.h
@@ -32,20 +32,14 @@ struct CC_EXPORT MainThreadRenderingStats {
// Note: when adding new members, please remember to update EnumerateFields
// and Add in rendering_stats.cc.
- int64 animation_frame_count;
- int64 screen_frame_count;
+ int64 frame_count;
base::TimeDelta paint_time;
- base::TimeDelta record_time;
- base::TimeDelta commit_time;
- int64 commit_count;
int64 painted_pixel_count;
+ base::TimeDelta record_time;
int64 recorded_pixel_count;
- int64 image_gathering_count;
- base::TimeDelta image_gathering_time;
MainThreadRenderingStats();
- void IssueTraceEvent() const;
- scoped_ptr<base::debug::ConvertableToTraceFormat> AsTraceableData() const;
+ scoped_refptr<base::debug::ConvertableToTraceFormat> AsTraceableData() const;
void Add(const MainThreadRenderingStats& other);
};
@@ -53,26 +47,13 @@ struct CC_EXPORT ImplThreadRenderingStats {
// Note: when adding new members, please remember to update EnumerateFields
// and Add in rendering_stats.cc.
- int64 screen_frame_count;
- int64 dropped_frame_count;
+ int64 frame_count;
base::TimeDelta rasterize_time;
- base::TimeDelta rasterize_time_for_now_bins_on_pending_tree;
- base::TimeDelta best_rasterize_time;
+ base::TimeDelta analysis_time;
int64 rasterized_pixel_count;
- int64 impl_thread_scroll_count;
- int64 main_thread_scroll_count;
- int64 drawn_layer_count;
- int64 missing_tile_count;
- int64 deferred_image_decode_count;
- int64 deferred_image_cache_hit_count;
- int64 tile_analysis_count;
- int64 solid_color_tile_analysis_count;
- base::TimeDelta deferred_image_decode_time;
- base::TimeDelta tile_analysis_time;
ImplThreadRenderingStats();
- void IssueTraceEvent() const;
- scoped_ptr<base::debug::ConvertableToTraceFormat> AsTraceableData() const;
+ scoped_refptr<base::debug::ConvertableToTraceFormat> AsTraceableData() const;
void Add(const ImplThreadRenderingStats& other);
};
diff --git a/chromium/cc/debug/rendering_stats_instrumentation.cc b/chromium/cc/debug/rendering_stats_instrumentation.cc
index 3c2c96b8b00..63840a35f74 100644
--- a/chromium/cc/debug/rendering_stats_instrumentation.cc
+++ b/chromium/cc/debug/rendering_stats_instrumentation.cc
@@ -57,41 +57,16 @@ base::TimeDelta RenderingStatsInstrumentation::EndRecording(
return base::TimeDelta();
}
-void RenderingStatsInstrumentation::IncrementAnimationFrameCount() {
- if (!record_rendering_stats_)
- return;
-
- base::AutoLock scoped_lock(lock_);
- main_stats_.animation_frame_count++;
-}
-
-void RenderingStatsInstrumentation::IncrementScreenFrameCount(
- int64 count, bool main_thread) {
+void RenderingStatsInstrumentation::IncrementFrameCount(int64 count,
+ bool main_thread) {
if (!record_rendering_stats_)
return;
base::AutoLock scoped_lock(lock_);
if (main_thread)
- main_stats_.screen_frame_count += count;
+ main_stats_.frame_count += count;
else
- impl_stats_.screen_frame_count += count;
-}
-
-void RenderingStatsInstrumentation::IncrementDroppedFrameCount(int64 count) {
- if (!record_rendering_stats_)
- return;
-
- base::AutoLock scoped_lock(lock_);
- impl_stats_.dropped_frame_count += count;
-}
-
-void RenderingStatsInstrumentation::AddCommit(base::TimeDelta duration) {
- if (!record_rendering_stats_)
- return;
-
- base::AutoLock scoped_lock(lock_);
- main_stats_.commit_time += duration;
- main_stats_.commit_count++;
+ impl_stats_.frame_count += count;
}
void RenderingStatsInstrumentation::AddPaint(base::TimeDelta duration,
@@ -114,95 +89,23 @@ void RenderingStatsInstrumentation::AddRecord(base::TimeDelta duration,
main_stats_.recorded_pixel_count += pixels;
}
-void RenderingStatsInstrumentation::AddRaster(base::TimeDelta total_duration,
- base::TimeDelta best_duration,
- int64 pixels,
- bool is_in_pending_tree_now_bin) {
+void RenderingStatsInstrumentation::AddRaster(base::TimeDelta duration,
+ int64 pixels) {
if (!record_rendering_stats_)
return;
base::AutoLock scoped_lock(lock_);
- impl_stats_.rasterize_time += total_duration;
- impl_stats_.best_rasterize_time += best_duration;
+ impl_stats_.rasterize_time += duration;
impl_stats_.rasterized_pixel_count += pixels;
-
- if (is_in_pending_tree_now_bin) {
- impl_stats_.rasterize_time_for_now_bins_on_pending_tree +=
- total_duration;
- }
-}
-
-void RenderingStatsInstrumentation::IncrementImplThreadScrolls() {
- if (!record_rendering_stats_)
- return;
-
- base::AutoLock scoped_lock(lock_);
- impl_stats_.impl_thread_scroll_count++;
-}
-
-void RenderingStatsInstrumentation::IncrementMainThreadScrolls() {
- if (!record_rendering_stats_)
- return;
-
- base::AutoLock scoped_lock(lock_);
- impl_stats_.main_thread_scroll_count++;
-}
-
-void RenderingStatsInstrumentation::AddLayersDrawn(int64 amount) {
- if (!record_rendering_stats_)
- return;
-
- base::AutoLock scoped_lock(lock_);
- impl_stats_.drawn_layer_count += amount;
-}
-
-void RenderingStatsInstrumentation::AddMissingTiles(int64 amount) {
- if (!record_rendering_stats_)
- return;
-
- base::AutoLock scoped_lock(lock_);
- impl_stats_.missing_tile_count += amount;
-}
-
-void RenderingStatsInstrumentation::AddDeferredImageDecode(
- base::TimeDelta duration) {
- if (!record_rendering_stats_)
- return;
-
- base::AutoLock scoped_lock(lock_);
- impl_stats_.deferred_image_decode_time += duration;
- impl_stats_.deferred_image_decode_count++;
-}
-
-void RenderingStatsInstrumentation::AddImageGathering(
- base::TimeDelta duration) {
- if (!record_rendering_stats_)
- return;
-
- base::AutoLock scoped_lock(lock_);
- main_stats_.image_gathering_time += duration;
- main_stats_.image_gathering_count++;
-}
-
-void RenderingStatsInstrumentation::IncrementDeferredImageCacheHitCount() {
- if (!record_rendering_stats_)
- return;
-
- base::AutoLock scoped_lock(lock_);
- impl_stats_.deferred_image_cache_hit_count++;
}
-void RenderingStatsInstrumentation::AddAnalysisResult(
- base::TimeDelta duration,
- bool is_solid_color) {
+void RenderingStatsInstrumentation::AddAnalysis(base::TimeDelta duration,
+ int64 pixels) {
if (!record_rendering_stats_)
return;
base::AutoLock scoped_lock(lock_);
- impl_stats_.tile_analysis_count++;
- impl_stats_.tile_analysis_time += duration;
- if (is_solid_color)
- impl_stats_.solid_color_tile_analysis_count++;
+ impl_stats_.analysis_time += duration;
}
} // namespace cc
diff --git a/chromium/cc/debug/rendering_stats_instrumentation.h b/chromium/cc/debug/rendering_stats_instrumentation.h
index 5f74f9e6132..68117557e7d 100644
--- a/chromium/cc/debug/rendering_stats_instrumentation.h
+++ b/chromium/cc/debug/rendering_stats_instrumentation.h
@@ -19,11 +19,11 @@ class CC_EXPORT RenderingStatsInstrumentation {
virtual ~RenderingStatsInstrumentation();
// Return current main thread rendering stats.
- MainThreadRenderingStats GetMainThreadRenderingStats() {
+ const MainThreadRenderingStats& main_thread_rendering_stats() {
return main_stats_;
}
// Return current impl thread rendering stats.
- ImplThreadRenderingStats GetImplThreadRenderingStats() {
+ const ImplThreadRenderingStats& impl_thread_rendering_stats() {
return impl_stats_;
}
// Return the accumulated, combined rendering stats.
@@ -36,15 +36,6 @@ class CC_EXPORT RenderingStatsInstrumentation {
// clear current stats.
void AccumulateAndClearImplThreadStats();
- // Issue trace event for current main thread rendering stats.
- void IssueTraceEventForMainThreadStats() {
- main_stats_.IssueTraceEvent();
- }
- // Issue trace event for current impl thread rendering stats.
- void IssueTraceEventForImplThreadStats() {
- impl_stats_.IssueTraceEvent();
- }
-
// Read and write access to the record_rendering_stats_ flag is not locked to
// improve performance. The flag is commonly turned off and hardly changes
// it's value during runtime.
@@ -57,35 +48,17 @@ class CC_EXPORT RenderingStatsInstrumentation {
base::TimeTicks StartRecording() const;
base::TimeDelta EndRecording(base::TimeTicks start_time) const;
- void IncrementAnimationFrameCount();
- void IncrementScreenFrameCount(int64 count, bool main_thread);
- void IncrementDroppedFrameCount(int64 count);
-
- void AddCommit(base::TimeDelta duration);
+ void IncrementFrameCount(int64 count, bool main_thread);
void AddPaint(base::TimeDelta duration, int64 pixels);
void AddRecord(base::TimeDelta duration, int64 pixels);
- void AddRaster(base::TimeDelta total_duraction,
- base::TimeDelta best_duration,
- int64 pixels,
- bool is_in_pending_tree_now_bin);
-
- void IncrementImplThreadScrolls();
- void IncrementMainThreadScrolls();
-
- void AddLayersDrawn(int64 amount);
- void AddMissingTiles(int64 amount);
-
- void AddDeferredImageDecode(base::TimeDelta duration);
- void AddImageGathering(base::TimeDelta duration);
-
- void IncrementDeferredImageCacheHitCount();
-
- void AddAnalysisResult(base::TimeDelta duration, bool is_solid_color);
+ void AddRaster(base::TimeDelta duration, int64 pixels);
+ void AddAnalysis(base::TimeDelta duration, int64 pixels);
protected:
RenderingStatsInstrumentation();
private:
+ // TODO(ernstm): rename to *_thread_rendering_stats_*
MainThreadRenderingStats main_stats_;
MainThreadRenderingStats main_stats_accu_;
ImplThreadRenderingStats impl_stats_;
diff --git a/chromium/cc/debug/test_context_provider.cc b/chromium/cc/debug/test_context_provider.cc
deleted file mode 100644
index d09ecd86ed9..00000000000
--- a/chromium/cc/debug/test_context_provider.cc
+++ /dev/null
@@ -1,240 +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/test_context_provider.h"
-
-#include <set>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/callback_helpers.h"
-#include "base/logging.h"
-#include "base/strings/string_split.h"
-#include "cc/debug/test_web_graphics_context_3d.h"
-
-namespace cc {
-
-class TestContextProvider::LostContextCallbackProxy
- : public WebKit::WebGraphicsContext3D::WebGraphicsContextLostCallback {
- public:
- explicit LostContextCallbackProxy(TestContextProvider* provider)
- : provider_(provider) {
- provider_->context3d_->setContextLostCallback(this);
- }
-
- virtual ~LostContextCallbackProxy() {
- provider_->context3d_->setContextLostCallback(NULL);
- }
-
- virtual void onContextLost() {
- provider_->OnLostContext();
- }
-
- private:
- TestContextProvider* provider_;
-};
-
-class TestContextProvider::SwapBuffersCompleteCallbackProxy
- : public WebKit::WebGraphicsContext3D::
- WebGraphicsSwapBuffersCompleteCallbackCHROMIUM {
- public:
- explicit SwapBuffersCompleteCallbackProxy(TestContextProvider* provider)
- : provider_(provider) {
- provider_->context3d_->setSwapBuffersCompleteCallbackCHROMIUM(this);
- }
-
- virtual ~SwapBuffersCompleteCallbackProxy() {
- provider_->context3d_->setSwapBuffersCompleteCallbackCHROMIUM(NULL);
- }
-
- virtual void onSwapBuffersComplete() {
- provider_->OnSwapBuffersComplete();
- }
-
- private:
- TestContextProvider* provider_;
-};
-
-// static
-scoped_refptr<TestContextProvider> TestContextProvider::Create() {
- return Create(TestWebGraphicsContext3D::Create().Pass());
-}
-
-// static
-scoped_refptr<TestContextProvider> TestContextProvider::Create(
- const CreateCallback& create_callback) {
- scoped_refptr<TestContextProvider> provider = new TestContextProvider;
- if (!provider->InitializeOnMainThread(create_callback))
- return NULL;
- return provider;
-}
-
-scoped_ptr<TestWebGraphicsContext3D> ReturnScopedContext(
- scoped_ptr<TestWebGraphicsContext3D> context) {
- return context.Pass();
-}
-
-// static
-scoped_refptr<TestContextProvider> TestContextProvider::Create(
- scoped_ptr<TestWebGraphicsContext3D> context) {
- return Create(base::Bind(&ReturnScopedContext, base::Passed(&context)));
-}
-
-TestContextProvider::TestContextProvider()
- : bound_(false),
- destroyed_(false) {
- DCHECK(main_thread_checker_.CalledOnValidThread());
- context_thread_checker_.DetachFromThread();
-}
-
-TestContextProvider::~TestContextProvider() {
- DCHECK(main_thread_checker_.CalledOnValidThread() ||
- context_thread_checker_.CalledOnValidThread());
-}
-
-bool TestContextProvider::InitializeOnMainThread(
- const CreateCallback& create_callback) {
- DCHECK(main_thread_checker_.CalledOnValidThread());
-
- DCHECK(!context3d_);
- DCHECK(!create_callback.is_null());
- context3d_ = create_callback.Run();
- return context3d_;
-}
-
-bool TestContextProvider::BindToCurrentThread() {
- DCHECK(context3d_);
-
- // This is called on the thread the context will be used.
- DCHECK(context_thread_checker_.CalledOnValidThread());
-
- if (bound_)
- return true;
-
- bound_ = true;
- if (!context3d_->makeContextCurrent()) {
- base::AutoLock lock(destroyed_lock_);
- destroyed_ = true;
- return false;
- }
-
- lost_context_callback_proxy_.reset(new LostContextCallbackProxy(this));
- swap_buffers_complete_callback_proxy_.reset(
- new SwapBuffersCompleteCallbackProxy(this));
-
- return true;
-}
-
-ContextProvider::Capabilities TestContextProvider::ContextCapabilities() {
- DCHECK(context3d_);
- DCHECK(bound_);
- DCHECK(context_thread_checker_.CalledOnValidThread());
-
- return context3d_->test_capabilities();
-}
-
-WebKit::WebGraphicsContext3D* TestContextProvider::Context3d() {
- DCHECK(context3d_);
- DCHECK(bound_);
- DCHECK(context_thread_checker_.CalledOnValidThread());
-
- return context3d_.get();
-}
-
-class GrContext* TestContextProvider::GrContext() {
- DCHECK(context3d_);
- DCHECK(bound_);
- DCHECK(context_thread_checker_.CalledOnValidThread());
-
- // TODO(danakj): Make a test GrContext that works with a test Context3d.
- return NULL;
-}
-
-void TestContextProvider::VerifyContexts() {
- DCHECK(context3d_);
- DCHECK(bound_);
- DCHECK(context_thread_checker_.CalledOnValidThread());
-
- if (context3d_->isContextLost()) {
- base::AutoLock lock(destroyed_lock_);
- destroyed_ = true;
- }
-}
-
-bool TestContextProvider::DestroyedOnMainThread() {
- DCHECK(main_thread_checker_.CalledOnValidThread());
-
- base::AutoLock lock(destroyed_lock_);
- return destroyed_;
-}
-
-void TestContextProvider::OnLostContext() {
- DCHECK(context_thread_checker_.CalledOnValidThread());
- {
- base::AutoLock lock(destroyed_lock_);
- if (destroyed_)
- return;
- destroyed_ = true;
- }
- if (!lost_context_callback_.is_null())
- base::ResetAndReturn(&lost_context_callback_).Run();
-}
-
-void TestContextProvider::OnSwapBuffersComplete() {
- DCHECK(context_thread_checker_.CalledOnValidThread());
- if (!swap_buffers_complete_callback_.is_null())
- swap_buffers_complete_callback_.Run();
-}
-
-TestWebGraphicsContext3D* TestContextProvider::TestContext3d() {
- DCHECK(context3d_);
- DCHECK(bound_);
- DCHECK(context_thread_checker_.CalledOnValidThread());
-
- return context3d_.get();
-}
-
-TestWebGraphicsContext3D* TestContextProvider::UnboundTestContext3d() {
- DCHECK(context3d_);
- DCHECK(context_thread_checker_.CalledOnValidThread());
-
- return context3d_.get();
-}
-
-void TestContextProvider::SetMemoryAllocation(
- const ManagedMemoryPolicy& policy,
- bool discard_backbuffer_when_not_visible) {
- if (memory_policy_changed_callback_.is_null())
- return;
- memory_policy_changed_callback_.Run(
- policy, discard_backbuffer_when_not_visible);
-}
-
-void TestContextProvider::SetLostContextCallback(
- const LostContextCallback& cb) {
- DCHECK(context_thread_checker_.CalledOnValidThread());
- DCHECK(lost_context_callback_.is_null() || cb.is_null());
- lost_context_callback_ = cb;
-}
-
-void TestContextProvider::SetSwapBuffersCompleteCallback(
- const SwapBuffersCompleteCallback& cb) {
- DCHECK(context_thread_checker_.CalledOnValidThread());
- DCHECK(swap_buffers_complete_callback_.is_null() || cb.is_null());
- swap_buffers_complete_callback_ = cb;
-}
-
-void TestContextProvider::SetMemoryPolicyChangedCallback(
- const MemoryPolicyChangedCallback& cb) {
- DCHECK(context_thread_checker_.CalledOnValidThread());
- DCHECK(memory_policy_changed_callback_.is_null() || cb.is_null());
- memory_policy_changed_callback_ = cb;
-}
-
-void TestContextProvider::SetMaxTransferBufferUsageBytes(
- size_t max_transfer_buffer_usage_bytes) {
- context3d_->SetMaxTransferBufferUsageBytes(max_transfer_buffer_usage_bytes);
-}
-
-} // namespace cc
diff --git a/chromium/cc/debug/test_context_provider.h b/chromium/cc/debug/test_context_provider.h
deleted file mode 100644
index 0401fcf1ba8..00000000000
--- a/chromium/cc/debug/test_context_provider.h
+++ /dev/null
@@ -1,90 +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_TEST_CONTEXT_PROVIDER_H_
-#define CC_DEBUG_TEST_CONTEXT_PROVIDER_H_
-
-#include "base/callback.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/synchronization/lock.h"
-#include "base/threading/thread_checker.h"
-#include "cc/base/cc_export.h"
-#include "cc/output/context_provider.h"
-
-namespace WebKit { class WebGraphicsContext3D; }
-
-namespace cc {
-class TestWebGraphicsContext3D;
-
-class CC_EXPORT TestContextProvider
- : public NON_EXPORTED_BASE(cc::ContextProvider) {
- public:
- typedef base::Callback<scoped_ptr<TestWebGraphicsContext3D>(void)>
- CreateCallback;
-
- static scoped_refptr<TestContextProvider> Create();
- static scoped_refptr<TestContextProvider> Create(
- const CreateCallback& create_callback);
- static scoped_refptr<TestContextProvider> Create(
- scoped_ptr<TestWebGraphicsContext3D> context);
-
- virtual bool BindToCurrentThread() OVERRIDE;
- virtual Capabilities ContextCapabilities() OVERRIDE;
- virtual WebKit::WebGraphicsContext3D* Context3d() OVERRIDE;
- virtual class GrContext* GrContext() OVERRIDE;
- virtual void VerifyContexts() OVERRIDE;
- virtual bool DestroyedOnMainThread() OVERRIDE;
- virtual void SetLostContextCallback(const LostContextCallback& cb) OVERRIDE;
- virtual void SetSwapBuffersCompleteCallback(
- const SwapBuffersCompleteCallback& cb) OVERRIDE;
- virtual void SetMemoryPolicyChangedCallback(
- const MemoryPolicyChangedCallback& cb) OVERRIDE;
-
- TestWebGraphicsContext3D* TestContext3d();
-
- // This returns the TestWebGraphicsContext3D but is valid to call
- // before the context is bound to a thread. This is needed to set up
- // state on the test context before binding. Don't call
- // makeContextCurrent on the context returned from this method.
- TestWebGraphicsContext3D* UnboundTestContext3d();
-
- void SetMemoryAllocation(const ManagedMemoryPolicy& policy,
- bool discard_backbuffer_when_not_visible);
-
- void SetMaxTransferBufferUsageBytes(size_t max_transfer_buffer_usage_bytes);
-
- protected:
- TestContextProvider();
- virtual ~TestContextProvider();
-
- bool InitializeOnMainThread(const CreateCallback& create_callback);
-
- void OnLostContext();
- void OnSwapBuffersComplete();
-
- scoped_ptr<TestWebGraphicsContext3D> context3d_;
- bool bound_;
-
- base::ThreadChecker main_thread_checker_;
- base::ThreadChecker context_thread_checker_;
-
- base::Lock destroyed_lock_;
- bool destroyed_;
-
- LostContextCallback lost_context_callback_;
- SwapBuffersCompleteCallback swap_buffers_complete_callback_;
- MemoryPolicyChangedCallback memory_policy_changed_callback_;
-
- class LostContextCallbackProxy;
- scoped_ptr<LostContextCallbackProxy> lost_context_callback_proxy_;
-
- class SwapBuffersCompleteCallbackProxy;
- scoped_ptr<SwapBuffersCompleteCallbackProxy>
- swap_buffers_complete_callback_proxy_;
-};
-
-} // namespace cc
-
-#endif // CC_DEBUG_TEST_CONTEXT_PROVIDER_H_
-
diff --git a/chromium/cc/debug/test_web_graphics_context_3d.cc b/chromium/cc/debug/test_web_graphics_context_3d.cc
deleted file mode 100644
index 634778fc4e6..00000000000
--- a/chromium/cc/debug/test_web_graphics_context_3d.cc
+++ /dev/null
@@ -1,632 +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/test_web_graphics_context_3d.h"
-
-#include <algorithm>
-#include <string>
-
-#include "base/bind.h"
-#include "base/lazy_instance.h"
-#include "base/logging.h"
-#include "base/message_loop/message_loop.h"
-#include "gpu/GLES2/gl2extchromium.h"
-#include "third_party/khronos/GLES2/gl2ext.h"
-
-using WebKit::WGC3Dboolean;
-using WebKit::WGC3Dchar;
-using WebKit::WGC3Denum;
-using WebKit::WGC3Dint;
-using WebKit::WGC3Dsizei;
-using WebKit::WGC3Dsizeiptr;
-using WebKit::WGC3Duint;
-using WebKit::WebGLId;
-using WebKit::WebGraphicsContext3D;
-
-namespace cc {
-
-static const WebGLId kFramebufferId = 1;
-static const WebGLId kProgramId = 2;
-static const WebGLId kRenderbufferId = 3;
-static const WebGLId kShaderId = 4;
-
-static unsigned s_context_id = 1;
-
-const WebGLId TestWebGraphicsContext3D::kExternalTextureId = 1337;
-
-static base::LazyInstance<base::Lock>::Leaky
- g_shared_namespace_lock = LAZY_INSTANCE_INITIALIZER;
-
-TestWebGraphicsContext3D::Namespace*
- TestWebGraphicsContext3D::shared_namespace_ = NULL;
-
-TestWebGraphicsContext3D::Namespace::Namespace()
- : next_buffer_id(1),
- next_image_id(1),
- next_texture_id(1) {
-}
-
-TestWebGraphicsContext3D::Namespace::~Namespace() {
- g_shared_namespace_lock.Get().AssertAcquired();
- if (shared_namespace_ == this)
- shared_namespace_ = NULL;
-}
-
-// static
-scoped_ptr<TestWebGraphicsContext3D> TestWebGraphicsContext3D::Create() {
- return make_scoped_ptr(new TestWebGraphicsContext3D());
-}
-
-TestWebGraphicsContext3D::TestWebGraphicsContext3D()
- : FakeWebGraphicsContext3D(),
- context_id_(s_context_id++),
- times_make_current_succeeds_(-1),
- times_bind_texture_succeeds_(-1),
- times_end_query_succeeds_(-1),
- times_gen_mailbox_succeeds_(-1),
- context_lost_(false),
- times_map_image_chromium_succeeds_(-1),
- times_map_buffer_chromium_succeeds_(-1),
- context_lost_callback_(NULL),
- swap_buffers_callback_(NULL),
- max_texture_size_(2048),
- width_(0),
- height_(0),
- bound_buffer_(0),
- weak_ptr_factory_(this) {
- CreateNamespace();
- test_capabilities_.swapbuffers_complete_callback = true;
-}
-
-TestWebGraphicsContext3D::TestWebGraphicsContext3D(
- const WebGraphicsContext3D::Attributes& attributes)
- : FakeWebGraphicsContext3D(),
- context_id_(s_context_id++),
- attributes_(attributes),
- times_make_current_succeeds_(-1),
- times_bind_texture_succeeds_(-1),
- times_end_query_succeeds_(-1),
- times_gen_mailbox_succeeds_(-1),
- context_lost_(false),
- times_map_image_chromium_succeeds_(-1),
- times_map_buffer_chromium_succeeds_(-1),
- context_lost_callback_(NULL),
- swap_buffers_callback_(NULL),
- max_texture_size_(2048),
- width_(0),
- height_(0),
- bound_buffer_(0),
- weak_ptr_factory_(this) {
- CreateNamespace();
- test_capabilities_.swapbuffers_complete_callback = true;
-}
-
-void TestWebGraphicsContext3D::CreateNamespace() {
- if (attributes_.shareResources) {
- base::AutoLock lock(g_shared_namespace_lock.Get());
- if (shared_namespace_) {
- namespace_ = shared_namespace_;
- } else {
- namespace_ = new Namespace;
- shared_namespace_ = namespace_.get();
- }
- } else {
- namespace_ = new Namespace;
- }
-}
-
-TestWebGraphicsContext3D::~TestWebGraphicsContext3D() {
- for (size_t i = 0; i < sync_point_callbacks_.size(); ++i) {
- if (sync_point_callbacks_[i] != NULL)
- delete sync_point_callbacks_[i];
- }
- base::AutoLock lock(g_shared_namespace_lock.Get());
- namespace_ = NULL;
-}
-
-bool TestWebGraphicsContext3D::makeContextCurrent() {
- if (times_make_current_succeeds_ >= 0) {
- if (!times_make_current_succeeds_) {
- loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
- GL_INNOCENT_CONTEXT_RESET_ARB);
- }
- --times_make_current_succeeds_;
- }
- return !context_lost_;
-}
-
-int TestWebGraphicsContext3D::width() {
- return width_;
-}
-
-int TestWebGraphicsContext3D::height() {
- return height_;
-}
-
-void TestWebGraphicsContext3D::reshapeWithScaleFactor(
- int width, int height, float scale_factor) {
- width_ = width;
- height_ = height;
-}
-
-bool TestWebGraphicsContext3D::isContextLost() {
- return context_lost_;
-}
-
-WGC3Denum TestWebGraphicsContext3D::getGraphicsResetStatusARB() {
- return context_lost_ ? GL_UNKNOWN_CONTEXT_RESET_ARB : GL_NO_ERROR;
-}
-
-WGC3Denum TestWebGraphicsContext3D::checkFramebufferStatus(
- WGC3Denum target) {
- if (context_lost_)
- return GL_FRAMEBUFFER_UNDEFINED_OES;
- return GL_FRAMEBUFFER_COMPLETE;
-}
-
-WebGraphicsContext3D::Attributes
- TestWebGraphicsContext3D::getContextAttributes() {
- return attributes_;
-}
-
-WebKit::WebString TestWebGraphicsContext3D::getString(WGC3Denum name) {
- return WebKit::WebString();
-}
-
-WGC3Dint TestWebGraphicsContext3D::getUniformLocation(
- WebGLId program,
- const WGC3Dchar* name) {
- return 0;
-}
-
-WGC3Dsizeiptr TestWebGraphicsContext3D::getVertexAttribOffset(
- WGC3Duint index,
- WGC3Denum pname) {
- return 0;
-}
-
-WGC3Dboolean TestWebGraphicsContext3D::isBuffer(
- WebGLId buffer) {
- return false;
-}
-
-WGC3Dboolean TestWebGraphicsContext3D::isEnabled(
- WGC3Denum cap) {
- return false;
-}
-
-WGC3Dboolean TestWebGraphicsContext3D::isFramebuffer(
- WebGLId framebuffer) {
- return false;
-}
-
-WGC3Dboolean TestWebGraphicsContext3D::isProgram(
- WebGLId program) {
- return false;
-}
-
-WGC3Dboolean TestWebGraphicsContext3D::isRenderbuffer(
- WebGLId renderbuffer) {
- return false;
-}
-
-WGC3Dboolean TestWebGraphicsContext3D::isShader(
- WebGLId shader) {
- return false;
-}
-
-WGC3Dboolean TestWebGraphicsContext3D::isTexture(
- WebGLId texture) {
- return false;
-}
-
-WebGLId TestWebGraphicsContext3D::createBuffer() {
- return NextBufferId();
-}
-
-void TestWebGraphicsContext3D::deleteBuffer(WebGLId id) {
- base::AutoLock lock(namespace_->lock);
- unsigned context_id = id >> 17;
- unsigned buffer_id = id & 0x1ffff;
- DCHECK(buffer_id && buffer_id < namespace_->next_buffer_id);
- DCHECK_EQ(context_id, context_id_);
-}
-
-WebGLId TestWebGraphicsContext3D::createFramebuffer() {
- return kFramebufferId | context_id_ << 16;
-}
-
-void TestWebGraphicsContext3D::deleteFramebuffer(WebGLId id) {
- DCHECK_EQ(kFramebufferId | context_id_ << 16, id);
-}
-
-WebGLId TestWebGraphicsContext3D::createProgram() {
- return kProgramId | context_id_ << 16;
-}
-
-void TestWebGraphicsContext3D::deleteProgram(WebGLId id) {
- DCHECK_EQ(kProgramId | context_id_ << 16, id);
-}
-
-WebGLId TestWebGraphicsContext3D::createRenderbuffer() {
- return kRenderbufferId | context_id_ << 16;
-}
-
-void TestWebGraphicsContext3D::deleteRenderbuffer(WebGLId id) {
- DCHECK_EQ(kRenderbufferId | context_id_ << 16, id);
-}
-
-WebGLId TestWebGraphicsContext3D::createShader(WGC3Denum) {
- return kShaderId | context_id_ << 16;
-}
-
-void TestWebGraphicsContext3D::deleteShader(WebGLId id) {
- DCHECK_EQ(kShaderId | context_id_ << 16, id);
-}
-
-WebGLId TestWebGraphicsContext3D::createTexture() {
- WebGLId texture_id = NextTextureId();
- DCHECK_NE(texture_id, kExternalTextureId);
- base::AutoLock lock(namespace_->lock);
- namespace_->textures.push_back(texture_id);
- return texture_id;
-}
-
-void TestWebGraphicsContext3D::deleteTexture(WebGLId texture_id) {
- base::AutoLock lock(namespace_->lock);
- std::vector<WebKit::WebGLId>& textures = namespace_->textures;
- DCHECK(std::find(textures.begin(), textures.end(), texture_id) !=
- textures.end());
- textures.erase(std::find(textures.begin(), textures.end(), texture_id));
-}
-
-void TestWebGraphicsContext3D::attachShader(WebGLId program, WebGLId shader) {
- DCHECK_EQ(kProgramId | context_id_ << 16, program);
- DCHECK_EQ(kShaderId | context_id_ << 16, shader);
-}
-
-void TestWebGraphicsContext3D::useProgram(WebGLId program) {
- if (!program)
- return;
- DCHECK_EQ(kProgramId | context_id_ << 16, program);
-}
-
-void TestWebGraphicsContext3D::bindFramebuffer(
- WGC3Denum target, WebGLId framebuffer) {
- if (!framebuffer)
- return;
- DCHECK_EQ(kFramebufferId | context_id_ << 16, framebuffer);
-}
-
-void TestWebGraphicsContext3D::bindRenderbuffer(
- WGC3Denum target, WebGLId renderbuffer) {
- if (!renderbuffer)
- return;
- DCHECK_EQ(kRenderbufferId | context_id_ << 16, renderbuffer);
-}
-
-void TestWebGraphicsContext3D::bindTexture(
- WGC3Denum target, WebGLId texture_id) {
- if (times_bind_texture_succeeds_ >= 0) {
- if (!times_bind_texture_succeeds_) {
- loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
- GL_INNOCENT_CONTEXT_RESET_ARB);
- }
- --times_bind_texture_succeeds_;
- }
-
- if (!texture_id)
- return;
- if (texture_id == kExternalTextureId)
- return;
- base::AutoLock lock(namespace_->lock);
- std::vector<WebKit::WebGLId>& textures = namespace_->textures;
- DCHECK(std::find(textures.begin(), textures.end(), texture_id) !=
- textures.end());
- used_textures_.insert(texture_id);
-}
-
-void TestWebGraphicsContext3D::endQueryEXT(WGC3Denum target) {
- if (times_end_query_succeeds_ >= 0) {
- if (!times_end_query_succeeds_) {
- loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
- GL_INNOCENT_CONTEXT_RESET_ARB);
- }
- --times_end_query_succeeds_;
- }
-}
-
-void TestWebGraphicsContext3D::getQueryObjectuivEXT(
- WebGLId query,
- WGC3Denum pname,
- WGC3Duint* params) {
- // If the context is lost, behave as if result is available.
- if (pname == GL_QUERY_RESULT_AVAILABLE_EXT)
- *params = 1;
-}
-
-void TestWebGraphicsContext3D::getIntegerv(
- WGC3Denum pname,
- WebKit::WGC3Dint* value) {
- if (pname == GL_MAX_TEXTURE_SIZE)
- *value = max_texture_size_;
- else if (pname == GL_ACTIVE_TEXTURE)
- *value = GL_TEXTURE0;
-}
-
-void TestWebGraphicsContext3D::genMailboxCHROMIUM(WebKit::WGC3Dbyte* mailbox) {
- if (times_gen_mailbox_succeeds_ >= 0) {
- if (!times_gen_mailbox_succeeds_) {
- loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
- GL_INNOCENT_CONTEXT_RESET_ARB);
- }
- --times_gen_mailbox_succeeds_;
- }
- if (context_lost_) {
- memset(mailbox, 0, 64);
- return;
- }
-
- static char mailbox_name1 = '1';
- static char mailbox_name2 = '1';
- mailbox[0] = mailbox_name1;
- mailbox[1] = mailbox_name2;
- mailbox[2] = '\0';
- if (++mailbox_name1 == 0) {
- mailbox_name1 = '1';
- ++mailbox_name2;
- }
-}
-
-void TestWebGraphicsContext3D::setContextLostCallback(
- WebGraphicsContextLostCallback* callback) {
- context_lost_callback_ = callback;
-}
-
-void TestWebGraphicsContext3D::loseContextCHROMIUM(WGC3Denum current,
- WGC3Denum other) {
- if (context_lost_)
- return;
- context_lost_ = true;
- if (context_lost_callback_)
- context_lost_callback_->onContextLost();
-
- for (size_t i = 0; i < shared_contexts_.size(); ++i)
- shared_contexts_[i]->loseContextCHROMIUM(current, other);
- shared_contexts_.clear();
-}
-
-void TestWebGraphicsContext3D::signalSyncPoint(
- unsigned sync_point,
- WebGraphicsSyncPointCallback* callback) {
- sync_point_callbacks_.push_back(callback);
-}
-
-void TestWebGraphicsContext3D::signalQuery(
- WebKit::WebGLId query,
- WebGraphicsSyncPointCallback* callback) {
- sync_point_callbacks_.push_back(callback);
-}
-
-void TestWebGraphicsContext3D::setSwapBuffersCompleteCallbackCHROMIUM(
- WebGraphicsSwapBuffersCompleteCallbackCHROMIUM* callback) {
- if (test_capabilities_.swapbuffers_complete_callback)
- swap_buffers_callback_ = callback;
-}
-
-void TestWebGraphicsContext3D::prepareTexture() {
- if (swap_buffers_callback_) {
- base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(&TestWebGraphicsContext3D::SwapBuffersComplete,
- weak_ptr_factory_.GetWeakPtr()));
- }
- CallAllSyncPointCallbacks();
-}
-
-void TestWebGraphicsContext3D::finish() {
- CallAllSyncPointCallbacks();
-}
-
-void TestWebGraphicsContext3D::flush() {
- CallAllSyncPointCallbacks();
-}
-
-static void CallAndDestroy(
- WebKit::WebGraphicsContext3D::WebGraphicsSyncPointCallback* callback) {
- if (!callback)
- return;
- callback->onSyncPointReached();
- delete callback;
-}
-
-void TestWebGraphicsContext3D::CallAllSyncPointCallbacks() {
- for (size_t i = 0; i < sync_point_callbacks_.size(); ++i) {
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&CallAndDestroy,
- sync_point_callbacks_[i]));
- }
- sync_point_callbacks_.clear();
-}
-
-void TestWebGraphicsContext3D::SwapBuffersComplete() {
- if (swap_buffers_callback_)
- swap_buffers_callback_->onSwapBuffersComplete();
-}
-
-void TestWebGraphicsContext3D::bindBuffer(WebKit::WGC3Denum target,
- WebKit::WebGLId buffer) {
- bound_buffer_ = buffer;
- if (!bound_buffer_)
- return;
- unsigned context_id = buffer >> 17;
- unsigned buffer_id = buffer & 0x1ffff;
- base::AutoLock lock(namespace_->lock);
- DCHECK(buffer_id && buffer_id < namespace_->next_buffer_id);
- DCHECK_EQ(context_id, context_id_);
-
- base::ScopedPtrHashMap<unsigned, Buffer>& buffers = namespace_->buffers;
- if (buffers.count(bound_buffer_) == 0)
- buffers.set(bound_buffer_, make_scoped_ptr(new Buffer).Pass());
-
- buffers.get(bound_buffer_)->target = target;
-}
-
-void TestWebGraphicsContext3D::bufferData(WebKit::WGC3Denum target,
- WebKit::WGC3Dsizeiptr size,
- const void* data,
- WebKit::WGC3Denum usage) {
- base::AutoLock lock(namespace_->lock);
- base::ScopedPtrHashMap<unsigned, Buffer>& buffers = namespace_->buffers;
- DCHECK_GT(buffers.count(bound_buffer_), 0u);
- DCHECK_EQ(target, buffers.get(bound_buffer_)->target);
- Buffer* buffer = buffers.get(bound_buffer_);
- if (context_lost_) {
- buffer->pixels.reset();
- return;
- }
-
- buffer->pixels.reset(new uint8[size]);
- buffer->size = size;
- if (data != NULL)
- memcpy(buffer->pixels.get(), data, size);
-}
-
-void* TestWebGraphicsContext3D::mapBufferCHROMIUM(WebKit::WGC3Denum target,
- WebKit::WGC3Denum access) {
- base::AutoLock lock(namespace_->lock);
- base::ScopedPtrHashMap<unsigned, Buffer>& buffers = namespace_->buffers;
- DCHECK_GT(buffers.count(bound_buffer_), 0u);
- DCHECK_EQ(target, buffers.get(bound_buffer_)->target);
- if (times_map_buffer_chromium_succeeds_ >= 0) {
- if (!times_map_buffer_chromium_succeeds_) {
- return NULL;
- }
- --times_map_buffer_chromium_succeeds_;
- }
- return buffers.get(bound_buffer_)->pixels.get();
-}
-
-WebKit::WGC3Dboolean TestWebGraphicsContext3D::unmapBufferCHROMIUM(
- WebKit::WGC3Denum target) {
- base::AutoLock lock(namespace_->lock);
- base::ScopedPtrHashMap<unsigned, Buffer>& buffers = namespace_->buffers;
- DCHECK_GT(buffers.count(bound_buffer_), 0u);
- DCHECK_EQ(target, buffers.get(bound_buffer_)->target);
- buffers.get(bound_buffer_)->pixels.reset();
- return true;
-}
-
-WebKit::WGC3Duint TestWebGraphicsContext3D::createImageCHROMIUM(
- WebKit::WGC3Dsizei width, WebKit::WGC3Dsizei height,
- WebKit::WGC3Denum internalformat) {
- DCHECK_EQ(GL_RGBA8_OES, static_cast<int>(internalformat));
- WebKit::WGC3Duint image_id = NextImageId();
- base::AutoLock lock(namespace_->lock);
- base::ScopedPtrHashMap<unsigned, Image>& images = namespace_->images;
- images.set(image_id, make_scoped_ptr(new Image).Pass());
- images.get(image_id)->pixels.reset(new uint8[width * height * 4]);
- return image_id;
-}
-
-void TestWebGraphicsContext3D::destroyImageCHROMIUM(
- WebKit::WGC3Duint id) {
- base::AutoLock lock(namespace_->lock);
- unsigned context_id = id >> 17;
- unsigned image_id = id & 0x1ffff;
- DCHECK(image_id && image_id < namespace_->next_image_id);
- DCHECK_EQ(context_id, context_id_);
-}
-
-void TestWebGraphicsContext3D::getImageParameterivCHROMIUM(
- WebKit::WGC3Duint image_id,
- WebKit::WGC3Denum pname,
- WebKit::WGC3Dint* params) {
- base::AutoLock lock(namespace_->lock);
- DCHECK_GT(namespace_->images.count(image_id), 0u);
- DCHECK_EQ(GL_IMAGE_ROWBYTES_CHROMIUM, static_cast<int>(pname));
- *params = 0;
-}
-
-void* TestWebGraphicsContext3D::mapImageCHROMIUM(WebKit::WGC3Duint image_id,
- WebKit::WGC3Denum access) {
- base::AutoLock lock(namespace_->lock);
- base::ScopedPtrHashMap<unsigned, Image>& images = namespace_->images;
- DCHECK_GT(images.count(image_id), 0u);
- if (times_map_image_chromium_succeeds_ >= 0) {
- if (!times_map_image_chromium_succeeds_) {
- return NULL;
- }
- --times_map_image_chromium_succeeds_;
- }
- return images.get(image_id)->pixels.get();
-}
-
-void TestWebGraphicsContext3D::unmapImageCHROMIUM(
- WebKit::WGC3Duint image_id) {
- base::AutoLock lock(namespace_->lock);
- DCHECK_GT(namespace_->images.count(image_id), 0u);
-}
-
-size_t TestWebGraphicsContext3D::NumTextures() const {
- base::AutoLock lock(namespace_->lock);
- return namespace_->textures.size();
-}
-
-WebKit::WebGLId TestWebGraphicsContext3D::TextureAt(int i) const {
- base::AutoLock lock(namespace_->lock);
- return namespace_->textures[i];
-}
-
-WebGLId TestWebGraphicsContext3D::NextTextureId() {
- base::AutoLock lock(namespace_->lock);
- WebGLId texture_id = namespace_->next_texture_id++;
- DCHECK(texture_id < (1 << 16));
- texture_id |= context_id_ << 16;
- return texture_id;
-}
-
-WebGLId TestWebGraphicsContext3D::NextBufferId() {
- base::AutoLock lock(namespace_->lock);
- WebGLId buffer_id = namespace_->next_buffer_id++;
- DCHECK(buffer_id < (1 << 17));
- buffer_id |= context_id_ << 17;
- return buffer_id;
-}
-
-WebKit::WGC3Duint TestWebGraphicsContext3D::NextImageId() {
- base::AutoLock lock(namespace_->lock);
- WGC3Duint image_id = namespace_->next_image_id++;
- DCHECK(image_id < (1 << 17));
- image_id |= context_id_ << 17;
- return image_id;
-}
-
-size_t TestWebGraphicsContext3D::GetTransferBufferMemoryUsedBytes() const {
- size_t total_bytes = 0;
- base::ScopedPtrHashMap<unsigned, Buffer>& buffers = namespace_->buffers;
- base::ScopedPtrHashMap<unsigned, Buffer>::iterator it = buffers.begin();
- for (; it != buffers.end(); ++it) {
- Buffer* buffer = it->second;
- if (buffer->target == GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM)
- total_bytes += buffer->size;
- }
- return total_bytes;
-}
-
-void TestWebGraphicsContext3D::SetMaxTransferBufferUsageBytes(
- size_t max_transfer_buffer_usage_bytes) {
- test_capabilities_.max_transfer_buffer_usage_bytes =
- max_transfer_buffer_usage_bytes;
-}
-
-TestWebGraphicsContext3D::Buffer::Buffer() : target(0), size(0) {}
-
-TestWebGraphicsContext3D::Buffer::~Buffer() {}
-
-TestWebGraphicsContext3D::Image::Image() {}
-
-TestWebGraphicsContext3D::Image::~Image() {}
-
-} // namespace cc
diff --git a/chromium/cc/debug/test_web_graphics_context_3d.h b/chromium/cc/debug/test_web_graphics_context_3d.h
deleted file mode 100644
index 4db270c4dd6..00000000000
--- a/chromium/cc/debug/test_web_graphics_context_3d.h
+++ /dev/null
@@ -1,292 +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_TEST_WEB_GRAPHICS_CONTEXT_3D_H_
-#define CC_DEBUG_TEST_WEB_GRAPHICS_CONTEXT_3D_H_
-
-#include <vector>
-
-#include "base/compiler_specific.h"
-#include "base/containers/hash_tables.h"
-#include "base/containers/scoped_ptr_hash_map.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "base/stl_util.h"
-#include "base/synchronization/lock.h"
-#include "cc/base/cc_export.h"
-#include "cc/debug/fake_web_graphics_context_3d.h"
-#include "cc/output/context_provider.h"
-#include "third_party/khronos/GLES2/gl2.h"
-
-namespace cc {
-
-class CC_EXPORT TestWebGraphicsContext3D : public FakeWebGraphicsContext3D {
- public:
- static scoped_ptr<TestWebGraphicsContext3D> Create();
-
- virtual ~TestWebGraphicsContext3D();
-
- virtual bool makeContextCurrent();
-
- virtual int width();
- virtual int height();
-
- virtual void reshapeWithScaleFactor(
- int width, int height, float scale_factor);
-
- virtual bool isContextLost();
- virtual WebKit::WGC3Denum getGraphicsResetStatusARB();
-
- virtual void attachShader(WebKit::WebGLId program, WebKit::WebGLId shader);
- virtual void bindFramebuffer(
- WebKit::WGC3Denum target, WebKit::WebGLId framebuffer);
- virtual void bindRenderbuffer(
- WebKit::WGC3Denum target, WebKit::WebGLId renderbuffer);
- virtual void bindTexture(
- WebKit::WGC3Denum target,
- WebKit::WebGLId texture_id);
-
- virtual WebKit::WGC3Denum checkFramebufferStatus(WebKit::WGC3Denum target);
-
- virtual Attributes getContextAttributes();
-
- virtual WebKit::WebString getString(WebKit::WGC3Denum name);
- virtual WebKit::WGC3Dint getUniformLocation(
- WebKit::WebGLId program,
- const WebKit::WGC3Dchar* name);
- virtual WebKit::WGC3Dsizeiptr getVertexAttribOffset(
- WebKit::WGC3Duint index,
- WebKit::WGC3Denum pname);
-
- virtual WebKit::WGC3Dboolean isBuffer(WebKit::WebGLId buffer);
- virtual WebKit::WGC3Dboolean isEnabled(WebKit::WGC3Denum cap);
- virtual WebKit::WGC3Dboolean isFramebuffer(WebKit::WebGLId framebuffer);
- virtual WebKit::WGC3Dboolean isProgram(WebKit::WebGLId program);
- virtual WebKit::WGC3Dboolean isRenderbuffer(WebKit::WebGLId renderbuffer);
- virtual WebKit::WGC3Dboolean isShader(WebKit::WebGLId shader);
- virtual WebKit::WGC3Dboolean isTexture(WebKit::WebGLId texture);
-
- virtual void useProgram(WebKit::WebGLId program);
-
- virtual WebKit::WebGLId createBuffer();
- virtual WebKit::WebGLId createFramebuffer();
- virtual WebKit::WebGLId createProgram();
- virtual WebKit::WebGLId createRenderbuffer();
- virtual WebKit::WebGLId createShader(WebKit::WGC3Denum);
- virtual WebKit::WebGLId createTexture();
-
- virtual void deleteBuffer(WebKit::WebGLId id);
- virtual void deleteFramebuffer(WebKit::WebGLId id);
- virtual void deleteProgram(WebKit::WebGLId id);
- virtual void deleteRenderbuffer(WebKit::WebGLId id);
- virtual void deleteShader(WebKit::WebGLId id);
- virtual void deleteTexture(WebKit::WebGLId texture_id);
-
- virtual void endQueryEXT(WebKit::WGC3Denum target);
- virtual void getQueryObjectuivEXT(
- WebKit::WebGLId query,
- WebKit::WGC3Denum pname,
- WebKit::WGC3Duint* params);
-
- virtual void getIntegerv(
- WebKit::WGC3Denum pname,
- WebKit::WGC3Dint* value);
-
- virtual void genMailboxCHROMIUM(WebKit::WGC3Dbyte* mailbox);
- virtual void produceTextureCHROMIUM(WebKit::WGC3Denum target,
- const WebKit::WGC3Dbyte* mailbox) { }
- virtual void consumeTextureCHROMIUM(WebKit::WGC3Denum target,
- const WebKit::WGC3Dbyte* mailbox) { }
-
- virtual void setContextLostCallback(
- WebGraphicsContextLostCallback* callback);
-
- virtual void loseContextCHROMIUM(WebKit::WGC3Denum current,
- WebKit::WGC3Denum other);
-
- // Takes ownership of the |callback|.
- virtual void signalSyncPoint(unsigned sync_point,
- WebGraphicsSyncPointCallback* callback);
- virtual void signalQuery(WebKit::WebGLId query,
- WebGraphicsSyncPointCallback* callback);
-
- virtual void setSwapBuffersCompleteCallbackCHROMIUM(
- WebGraphicsSwapBuffersCompleteCallbackCHROMIUM* callback);
-
- virtual void prepareTexture();
- virtual void finish();
- virtual void flush();
-
- virtual void bindBuffer(WebKit::WGC3Denum target, WebKit::WebGLId buffer);
- virtual void bufferData(WebKit::WGC3Denum target,
- WebKit::WGC3Dsizeiptr size,
- const void* data,
- WebKit::WGC3Denum usage);
- virtual void* mapBufferCHROMIUM(WebKit::WGC3Denum target,
- WebKit::WGC3Denum access);
- virtual WebKit::WGC3Dboolean unmapBufferCHROMIUM(WebKit::WGC3Denum target);
-
- virtual WebKit::WGC3Duint createImageCHROMIUM(
- WebKit::WGC3Dsizei width,
- WebKit::WGC3Dsizei height,
- WebKit::WGC3Denum internalformat);
- virtual void destroyImageCHROMIUM(WebKit::WGC3Duint image_id);
- virtual void getImageParameterivCHROMIUM(
- WebKit::WGC3Duint image_id,
- WebKit::WGC3Denum pname,
- WebKit::WGC3Dint* params);
- virtual void* mapImageCHROMIUM(
- WebKit::WGC3Duint image_id,
- WebKit::WGC3Denum access);
- virtual void unmapImageCHROMIUM(WebKit::WGC3Duint image_id);
-
- const ContextProvider::Capabilities& test_capabilities() const {
- return test_capabilities_;
- }
-
- // When set, MakeCurrent() will fail after this many times.
- void set_times_make_current_succeeds(int times) {
- times_make_current_succeeds_ = times;
- }
- void set_times_bind_texture_succeeds(int times) {
- times_bind_texture_succeeds_ = times;
- }
- void set_times_end_query_succeeds(int times) {
- times_end_query_succeeds_ = times;
- }
- void set_times_gen_mailbox_succeeds(int times) {
- times_gen_mailbox_succeeds_ = times;
- }
-
- // When set, mapImageCHROMIUM and mapBufferCHROMIUM will return NULL after
- // this many times.
- void set_times_map_image_chromium_succeeds(int times) {
- times_map_image_chromium_succeeds_ = times;
- }
- void set_times_map_buffer_chromium_succeeds(int times) {
- times_map_buffer_chromium_succeeds_ = times;
- }
-
- size_t NumTextures() const;
- WebKit::WebGLId TextureAt(int i) const;
-
- size_t NumUsedTextures() const { return used_textures_.size(); }
- bool UsedTexture(int texture) const {
- return ContainsKey(used_textures_, texture);
- }
- void ResetUsedTextures() { used_textures_.clear(); }
-
- void set_support_swapbuffers_complete_callback(bool support) {
- test_capabilities_.swapbuffers_complete_callback = support;
- }
- void set_have_extension_io_surface(bool have) {
- test_capabilities_.iosurface = have;
- }
- void set_have_extension_egl_image(bool have) {
- test_capabilities_.egl_image_external = have;
- }
- void set_have_post_sub_buffer(bool have) {
- test_capabilities_.post_sub_buffer = have;
- }
- void set_have_discard_framebuffer(bool have) {
- test_capabilities_.discard_framebuffer = have;
- }
-
- // When this context is lost, all contexts in its share group are also lost.
- void add_share_group_context(WebKit::WebGraphicsContext3D* context3d) {
- shared_contexts_.push_back(context3d);
- }
-
- void set_max_texture_size(int size) { max_texture_size_ = size; }
-
- static const WebKit::WebGLId kExternalTextureId;
- virtual WebKit::WebGLId NextTextureId();
-
- virtual WebKit::WebGLId NextBufferId();
-
- virtual WebKit::WebGLId NextImageId();
-
- size_t GetTransferBufferMemoryUsedBytes() const;
- void SetMaxTransferBufferUsageBytes(size_t max_transfer_buffer_usage_bytes);
-
- protected:
- struct Buffer {
- Buffer();
- ~Buffer();
-
- WebKit::WGC3Denum target;
- scoped_ptr<uint8[]> pixels;
- size_t size;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Buffer);
- };
-
- struct Image {
- Image();
- ~Image();
-
- scoped_ptr<uint8[]> pixels;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Image);
- };
-
- struct Namespace : public base::RefCountedThreadSafe<Namespace> {
- Namespace();
-
- // Protects all fields.
- base::Lock lock;
- unsigned next_buffer_id;
- unsigned next_image_id;
- unsigned next_texture_id;
- std::vector<WebKit::WebGLId> textures;
- base::ScopedPtrHashMap<unsigned, Buffer> buffers;
- base::ScopedPtrHashMap<unsigned, Image> images;
-
- private:
- friend class base::RefCountedThreadSafe<Namespace>;
- ~Namespace();
- DISALLOW_COPY_AND_ASSIGN(Namespace);
- };
-
- TestWebGraphicsContext3D();
- TestWebGraphicsContext3D(
- const WebKit::WebGraphicsContext3D::Attributes& attributes);
-
- void CallAllSyncPointCallbacks();
- void SwapBuffersComplete();
- void CreateNamespace();
-
- unsigned context_id_;
- Attributes attributes_;
- ContextProvider::Capabilities test_capabilities_;
- int times_make_current_succeeds_;
- int times_bind_texture_succeeds_;
- int times_end_query_succeeds_;
- int times_gen_mailbox_succeeds_;
- bool context_lost_;
- int times_map_image_chromium_succeeds_;
- int times_map_buffer_chromium_succeeds_;
- WebGraphicsContextLostCallback* context_lost_callback_;
- WebGraphicsSwapBuffersCompleteCallbackCHROMIUM* swap_buffers_callback_;
- std::vector<WebGraphicsSyncPointCallback*> sync_point_callbacks_;
- base::hash_set<WebKit::WebGLId> used_textures_;
- std::vector<WebKit::WebGraphicsContext3D*> shared_contexts_;
- int max_texture_size_;
- int width_;
- int height_;
-
- unsigned bound_buffer_;
-
- scoped_refptr<Namespace> namespace_;
- static Namespace* shared_namespace_;
-
- base::WeakPtrFactory<TestWebGraphicsContext3D> weak_ptr_factory_;
-};
-
-} // namespace cc
-
-#endif // CC_DEBUG_TEST_WEB_GRAPHICS_CONTEXT_3D_H_
diff --git a/chromium/cc/debug/traced_picture.cc b/chromium/cc/debug/traced_picture.cc
index 0cc2148f5f0..143f0b87adb 100644
--- a/chromium/cc/debug/traced_picture.cc
+++ b/chromium/cc/debug/traced_picture.cc
@@ -19,19 +19,17 @@ TracedPicture::TracedPicture(scoped_refptr<Picture> picture)
TracedPicture::~TracedPicture() {
}
-scoped_ptr<base::debug::ConvertableToTraceFormat>
+scoped_refptr<base::debug::ConvertableToTraceFormat>
TracedPicture::AsTraceablePicture(Picture* picture) {
- TracedPicture* ptr = new TracedPicture(picture);
- scoped_ptr<TracedPicture> result(ptr);
- return result.PassAs<base::debug::ConvertableToTraceFormat>();
+ return scoped_refptr<base::debug::ConvertableToTraceFormat>(
+ new TracedPicture(picture));
}
-scoped_ptr<base::debug::ConvertableToTraceFormat>
+scoped_refptr<base::debug::ConvertableToTraceFormat>
TracedPicture::AsTraceablePictureAlias(Picture* original) {
- TracedPicture* ptr = new TracedPicture(original);
+ scoped_refptr<TracedPicture> ptr = new TracedPicture(original);
ptr->is_alias_ = true;
- scoped_ptr<TracedPicture> result(ptr);
- return result.PassAs<base::debug::ConvertableToTraceFormat>();
+ return scoped_refptr<base::debug::ConvertableToTraceFormat>(ptr);
}
void TracedPicture::AppendAsTraceFormat(std::string* out) const {
diff --git a/chromium/cc/debug/traced_picture.h b/chromium/cc/debug/traced_picture.h
index 50511f2034a..cc212ceed82 100644
--- a/chromium/cc/debug/traced_picture.h
+++ b/chromium/cc/debug/traced_picture.h
@@ -17,17 +17,17 @@ class TracedPicture : public base::debug::ConvertableToTraceFormat {
public:
explicit TracedPicture(scoped_refptr<Picture>);
- virtual ~TracedPicture();
-
- static scoped_ptr<base::debug::ConvertableToTraceFormat>
+ static scoped_refptr<base::debug::ConvertableToTraceFormat>
AsTraceablePicture(Picture* picture);
- static scoped_ptr<base::debug::ConvertableToTraceFormat>
+ static scoped_refptr<base::debug::ConvertableToTraceFormat>
AsTraceablePictureAlias(Picture* original);
virtual void AppendAsTraceFormat(std::string* out) const OVERRIDE;
private:
+ virtual ~TracedPicture();
+
void AppendPicture(std::string* out) const;
void AppendPictureAlias(std::string* out) const;
diff --git a/chromium/cc/debug/traced_value.cc b/chromium/cc/debug/traced_value.cc
index fbca5c60c80..5a324148725 100644
--- a/chromium/cc/debug/traced_value.cc
+++ b/chromium/cc/debug/traced_value.cc
@@ -30,11 +30,10 @@ void TracedValue::MakeDictIntoImplicitSnapshotWithCategory(
MakeDictIntoImplicitSnapshot(dict, object_name, id);
}
-scoped_ptr<base::debug::ConvertableToTraceFormat> TracedValue::FromValue(
+scoped_refptr<base::debug::ConvertableToTraceFormat> TracedValue::FromValue(
base::Value* value) {
- TracedValue* ptr = new TracedValue(value);
- scoped_ptr<TracedValue> result(ptr);
- return result.PassAs<base::debug::ConvertableToTraceFormat>();
+ return scoped_refptr<base::debug::ConvertableToTraceFormat>(
+ new TracedValue(value));
}
TracedValue::TracedValue(base::Value* value)
diff --git a/chromium/cc/debug/traced_value.h b/chromium/cc/debug/traced_value.h
index 148aca8ebb6..fe17695a45c 100644
--- a/chromium/cc/debug/traced_value.h
+++ b/chromium/cc/debug/traced_value.h
@@ -26,15 +26,14 @@ class TracedValue : public base::debug::ConvertableToTraceFormat {
base::DictionaryValue* dict,
const char* object_name,
const void* id);
- static scoped_ptr<ConvertableToTraceFormat> FromValue(
+ static scoped_refptr<base::debug::ConvertableToTraceFormat> FromValue(
base::Value* value);
- virtual ~TracedValue();
-
virtual void AppendAsTraceFormat(std::string* out) const OVERRIDE;
private:
explicit TracedValue(base::Value* value);
+ virtual ~TracedValue();
scoped_ptr<base::Value> value_;
diff --git a/chromium/cc/debug/unittest_only_benchmark.cc b/chromium/cc/debug/unittest_only_benchmark.cc
new file mode 100644
index 00000000000..9c6b17699e3
--- /dev/null
+++ b/chromium/cc/debug/unittest_only_benchmark.cc
@@ -0,0 +1,55 @@
+// 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/unittest_only_benchmark.h"
+
+#include "base/bind.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/values.h"
+#include "cc/debug/unittest_only_benchmark_impl.h"
+
+namespace cc {
+
+UnittestOnlyBenchmark::UnittestOnlyBenchmark(scoped_ptr<base::Value> value,
+ const DoneCallback& callback)
+ : MicroBenchmark(callback),
+ create_impl_benchmark_(false),
+ weak_ptr_factory_(this) {
+ if (!value)
+ return;
+
+ base::DictionaryValue* settings = NULL;
+ value->GetAsDictionary(&settings);
+ if (!settings)
+ return;
+
+ if (settings->HasKey("run_benchmark_impl"))
+ settings->GetBoolean("run_benchmark_impl", &create_impl_benchmark_);
+}
+
+UnittestOnlyBenchmark::~UnittestOnlyBenchmark() {
+ weak_ptr_factory_.InvalidateWeakPtrs();
+}
+
+void UnittestOnlyBenchmark::DidUpdateLayers(LayerTreeHost* host) {
+ NotifyDone(scoped_ptr<base::Value>());
+}
+
+void UnittestOnlyBenchmark::RecordImplResults(scoped_ptr<base::Value> results) {
+ NotifyDone(results.Pass());
+}
+
+scoped_ptr<MicroBenchmarkImpl> UnittestOnlyBenchmark::CreateBenchmarkImpl(
+ scoped_refptr<base::MessageLoopProxy> origin_loop) {
+ if (!create_impl_benchmark_)
+ return make_scoped_ptr<MicroBenchmarkImpl>(NULL);
+
+ return scoped_ptr<MicroBenchmarkImpl>(new UnittestOnlyBenchmarkImpl(
+ origin_loop,
+ NULL,
+ base::Bind(&UnittestOnlyBenchmark::RecordImplResults,
+ weak_ptr_factory_.GetWeakPtr())));
+}
+
+} // namespace cc
diff --git a/chromium/cc/debug/unittest_only_benchmark.h b/chromium/cc/debug/unittest_only_benchmark.h
new file mode 100644
index 00000000000..83312859644
--- /dev/null
+++ b/chromium/cc/debug/unittest_only_benchmark.h
@@ -0,0 +1,35 @@
+// 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_UNITTEST_ONLY_BENCHMARK_H_
+#define CC_DEBUG_UNITTEST_ONLY_BENCHMARK_H_
+
+#include "base/memory/weak_ptr.h"
+#include "cc/debug/micro_benchmark.h"
+
+namespace cc {
+
+class CC_EXPORT UnittestOnlyBenchmark : public MicroBenchmark {
+ public:
+ UnittestOnlyBenchmark(scoped_ptr<base::Value> value,
+ const DoneCallback& callback);
+ virtual ~UnittestOnlyBenchmark();
+
+ virtual void DidUpdateLayers(LayerTreeHost* host) OVERRIDE;
+
+ protected:
+ virtual scoped_ptr<MicroBenchmarkImpl> CreateBenchmarkImpl(
+ scoped_refptr<base::MessageLoopProxy> origin_loop) OVERRIDE;
+
+ private:
+ void RecordImplResults(scoped_ptr<base::Value> results);
+
+ bool create_impl_benchmark_;
+ base::WeakPtrFactory<UnittestOnlyBenchmark> weak_ptr_factory_;
+};
+
+} // namespace cc
+
+#endif // CC_DEBUG_UNITTEST_ONLY_BENCHMARK_H_
+
diff --git a/chromium/cc/debug/unittest_only_benchmark_impl.cc b/chromium/cc/debug/unittest_only_benchmark_impl.cc
new file mode 100644
index 00000000000..b249ce34476
--- /dev/null
+++ b/chromium/cc/debug/unittest_only_benchmark_impl.cc
@@ -0,0 +1,24 @@
+// 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/unittest_only_benchmark_impl.h"
+
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/values.h"
+
+namespace cc {
+
+UnittestOnlyBenchmarkImpl::UnittestOnlyBenchmarkImpl(
+ scoped_refptr<base::MessageLoopProxy> origin_loop,
+ base::Value* settings,
+ const DoneCallback& callback)
+ : MicroBenchmarkImpl(callback, origin_loop) {}
+
+UnittestOnlyBenchmarkImpl::~UnittestOnlyBenchmarkImpl() {}
+
+void UnittestOnlyBenchmarkImpl::DidCompleteCommit(LayerTreeHostImpl* host) {
+ NotifyDone(scoped_ptr<base::Value>());
+}
+
+} // namespace cc
diff --git a/chromium/cc/debug/unittest_only_benchmark_impl.h b/chromium/cc/debug/unittest_only_benchmark_impl.h
new file mode 100644
index 00000000000..b9e9bc9e95b
--- /dev/null
+++ b/chromium/cc/debug/unittest_only_benchmark_impl.h
@@ -0,0 +1,31 @@
+// 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_UNITTEST_ONLY_BENCHMARK_IMPL_H_
+#define CC_DEBUG_UNITTEST_ONLY_BENCHMARK_IMPL_H_
+
+#include "base/memory/weak_ptr.h"
+#include "cc/debug/micro_benchmark_impl.h"
+
+namespace base {
+class Value;
+class MessageLoopProxy;
+}
+
+namespace cc {
+
+class LayerTreeHostImpl;
+class CC_EXPORT UnittestOnlyBenchmarkImpl : public MicroBenchmarkImpl {
+ public:
+ UnittestOnlyBenchmarkImpl(scoped_refptr<base::MessageLoopProxy> origin_loop,
+ base::Value* settings,
+ const DoneCallback& callback);
+ virtual ~UnittestOnlyBenchmarkImpl();
+
+ virtual void DidCompleteCommit(LayerTreeHostImpl* host) OVERRIDE;
+};
+
+} // namespace cc
+
+#endif // CC_DEBUG_UNITTEST_ONLY_BENCHMARK_IMPL_H_
diff --git a/chromium/cc/input/input_handler.h b/chromium/cc/input/input_handler.h
index d28935f0a39..fde89d265d6 100644
--- a/chromium/cc/input/input_handler.h
+++ b/chromium/cc/input/input_handler.h
@@ -8,6 +8,7 @@
#include "base/basictypes.h"
#include "base/time/time.h"
#include "cc/base/cc_export.h"
+#include "cc/base/swap_promise_monitor.h"
#include "cc/input/scrollbar.h"
namespace gfx {
@@ -96,6 +97,8 @@ class CC_EXPORT InputHandler {
virtual void NotifyCurrentFlingVelocity(gfx::Vector2dF velocity) = 0;
+ virtual void MouseMoveAt(gfx::Point mouse_position) = 0;
+
// Stop scrolling the selected layer. Should only be called if ScrollBegin()
// returned ScrollStarted.
virtual void ScrollEnd() = 0;
@@ -124,8 +127,13 @@ class CC_EXPORT InputHandler {
virtual bool HaveTouchEventHandlersAt(gfx::Point viewport_point) = 0;
- virtual void SetLatencyInfoForInputEvent(
- const ui::LatencyInfo& latency_info) = 0;
+ // Calling CreateLatencyInfoSwapPromiseMonitor() to get a scoped
+ // LatencyInfoSwapPromiseMonitor. During the life time of the
+ // LatencyInfoSwapPromiseMonitor, if SetNeedsRedraw() or SetNeedsRedrawRect()
+ // is called on LayerTreeHostImpl, the original latency info will be turned
+ // into a LatencyInfoSwapPromise.
+ virtual scoped_ptr<SwapPromiseMonitor> CreateLatencyInfoSwapPromiseMonitor(
+ ui::LatencyInfo* latency) = 0;
protected:
InputHandler() {}
diff --git a/chromium/cc/input/layer_scroll_offset_delegate.h b/chromium/cc/input/layer_scroll_offset_delegate.h
index 895d36d7490..54a11c9e2bd 100644
--- a/chromium/cc/input/layer_scroll_offset_delegate.h
+++ b/chromium/cc/input/layer_scroll_offset_delegate.h
@@ -6,6 +6,7 @@
#define CC_INPUT_LAYER_SCROLL_OFFSET_DELEGATE_H_
#include "base/basictypes.h"
+#include "ui/gfx/size_f.h"
#include "ui/gfx/vector2d_f.h"
namespace cc {
@@ -16,6 +17,10 @@ namespace cc {
// The LayerScrollOffsetDelegate is only used on the impl thread.
class LayerScrollOffsetDelegate {
public:
+ // This is called by the compositor to notify the delegate what is the upper
+ // total scroll offset bound.
+ virtual void SetMaxScrollOffset(gfx::Vector2dF max_scroll_offset) = 0;
+
// This is called by the compositor when the scroll offset of the layer would
// have otherwise changed.
virtual void SetTotalScrollOffset(gfx::Vector2dF new_value) = 0;
@@ -25,9 +30,22 @@ class LayerScrollOffsetDelegate {
// 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.
+ // 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::Vector2dF GetTotalScrollOffset() = 0;
+ // This is called by the compositor to check whether a delegate-managed fling
+ // is active or not.
+ virtual bool IsExternalFlingActive() const = 0;
+
+ // This is called by the compositor to notify the delegate what is the current
+ // page scale factor is.
+ virtual void SetTotalPageScaleFactor(float page_scale_factor) = 0;
+
+ // This is called by the compositor to notify the delegate what is the layer's
+ // scrollable size is.
+ virtual void SetScrollableSize(gfx::SizeF scrollable_size) = 0;
+
protected:
LayerScrollOffsetDelegate() {}
virtual ~LayerScrollOffsetDelegate() {}
diff --git a/chromium/cc/input/top_controls_manager.cc b/chromium/cc/input/top_controls_manager.cc
index 925830cf40e..871d9e6f69c 100644
--- a/chromium/cc/input/top_controls_manager.cc
+++ b/chromium/cc/input/top_controls_manager.cc
@@ -7,11 +7,12 @@
#include <algorithm>
#include "base/logging.h"
-#include "base/time/time.h"
#include "cc/animation/keyframed_animation_curve.h"
#include "cc/animation/timing_function.h"
#include "cc/input/top_controls_manager_client.h"
+#include "cc/output/begin_frame_args.h"
#include "cc/trees/layer_tree_impl.h"
+#include "ui/gfx/frame_time.h"
#include "ui/gfx/transform.h"
#include "ui/gfx/vector2d_f.h"
@@ -48,7 +49,8 @@ TopControlsManager::TopControlsManager(TopControlsManagerClient* client,
top_controls_show_height_(
top_controls_height * top_controls_hide_threshold),
top_controls_hide_height_(
- top_controls_height * (1.f - top_controls_show_threshold)) {
+ top_controls_height * (1.f - top_controls_show_threshold)),
+ pinch_gesture_active_(false) {
CHECK(client_);
}
@@ -89,6 +91,7 @@ void TopControlsManager::UpdateTopControlsState(TopControlsState constraints,
}
void TopControlsManager::ScrollBegin() {
+ DCHECK(!pinch_gesture_active_);
ResetAnimations();
current_scroll_delta_ = 0.f;
controls_scroll_begin_offset_ = controls_top_offset_;
@@ -96,6 +99,9 @@ void TopControlsManager::ScrollBegin() {
gfx::Vector2dF TopControlsManager::ScrollBy(
const gfx::Vector2dF pending_delta) {
+ if (pinch_gesture_active_)
+ return pending_delta;
+
if (permitted_state_ == SHOWN && pending_delta.y() > 0)
return pending_delta;
else if (permitted_state_ == HIDDEN && pending_delta.y() < 0)
@@ -120,9 +126,24 @@ gfx::Vector2dF TopControlsManager::ScrollBy(
}
void TopControlsManager::ScrollEnd() {
+ DCHECK(!pinch_gesture_active_);
StartAnimationIfNecessary();
}
+void TopControlsManager::PinchBegin() {
+ DCHECK(!pinch_gesture_active_);
+ pinch_gesture_active_ = true;
+ StartAnimationIfNecessary();
+}
+
+void TopControlsManager::PinchEnd() {
+ DCHECK(pinch_gesture_active_);
+ // Pinch{Begin,End} will always occur within the scope of Scroll{Begin,End},
+ // so return to a state expected by the remaining scroll sequence.
+ pinch_gesture_active_ = false;
+ ScrollBegin();
+}
+
void TopControlsManager::SetControlsTopOffset(float controls_top_offset) {
controls_top_offset = std::max(controls_top_offset, -top_controls_height_);
controls_top_offset = std::min(controls_top_offset, 0.f);
@@ -174,7 +195,7 @@ void TopControlsManager::SetupAnimation(AnimationDirection direction) {
top_controls_animation_ = KeyframedFloatAnimationCurve::Create();
double start_time =
- (base::TimeTicks::Now() - base::TimeTicks()).InMillisecondsF();
+ (gfx::FrameTime::Now() - base::TimeTicks()).InMillisecondsF();
top_controls_animation_->AddKeyframe(
FloatKeyframe::Create(start_time, controls_top_offset_,
scoped_ptr<TimingFunction>()));
diff --git a/chromium/cc/input/top_controls_manager.h b/chromium/cc/input/top_controls_manager.h
index 9bc3040d31a..246efba5b9a 100644
--- a/chromium/cc/input/top_controls_manager.h
+++ b/chromium/cc/input/top_controls_manager.h
@@ -56,6 +56,11 @@ class CC_EXPORT TopControlsManager
gfx::Vector2dF ScrollBy(const gfx::Vector2dF pending_delta);
void ScrollEnd();
+ // The caller should ensure that |Pinch{Begin,End}| are called within
+ // the scope of |Scroll{Begin,End}|.
+ void PinchBegin();
+ void PinchEnd();
+
gfx::Vector2dF Animate(base::TimeTicks monotonic_time);
protected:
@@ -91,6 +96,8 @@ class CC_EXPORT TopControlsManager
// the user stops the scroll.
float top_controls_hide_height_;
+ bool pinch_gesture_active_;
+
DISALLOW_COPY_AND_ASSIGN(TopControlsManager);
};
diff --git a/chromium/cc/input/top_controls_manager_unittest.cc b/chromium/cc/input/top_controls_manager_unittest.cc
index da7475f576c..74687adfac0 100644
--- a/chromium/cc/input/top_controls_manager_unittest.cc
+++ b/chromium/cc/input/top_controls_manager_unittest.cc
@@ -12,6 +12,7 @@
#include "cc/test/fake_layer_tree_host_impl.h"
#include "cc/trees/layer_tree_impl.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/frame_time.h"
#include "ui/gfx/vector2d_f.h"
namespace cc {
@@ -131,7 +132,7 @@ TEST(TopControlsManagerTest, PartialShownHideAnimation) {
EXPECT_TRUE(manager->animation());
- base::TimeTicks time = base::TimeTicks::Now();
+ base::TimeTicks time = gfx::FrameTime::Now();
float previous_offset = manager->controls_top_offset();
while (manager->animation()) {
time = base::TimeDelta::FromMicroseconds(100) + time;
@@ -161,7 +162,7 @@ TEST(TopControlsManagerTest, PartialShownShowAnimation) {
EXPECT_TRUE(manager->animation());
- base::TimeTicks time = base::TimeTicks::Now();
+ base::TimeTicks time = gfx::FrameTime::Now();
float previous_offset = manager->controls_top_offset();
while (manager->animation()) {
time = base::TimeDelta::FromMicroseconds(100) + time;
@@ -187,7 +188,7 @@ TEST(TopControlsManagerTest, PartialHiddenWithAmbiguousThresholdShows) {
manager->ScrollEnd();
EXPECT_TRUE(manager->animation());
- base::TimeTicks time = base::TimeTicks::Now();
+ base::TimeTicks time = gfx::FrameTime::Now();
float previous_offset = manager->controls_top_offset();
while (manager->animation()) {
time = base::TimeDelta::FromMicroseconds(100) + time;
@@ -213,7 +214,7 @@ TEST(TopControlsManagerTest, PartialHiddenWithAmbiguousThresholdHides) {
manager->ScrollEnd();
EXPECT_TRUE(manager->animation());
- base::TimeTicks time = base::TimeTicks::Now();
+ base::TimeTicks time = gfx::FrameTime::Now();
float previous_offset = manager->controls_top_offset();
while (manager->animation()) {
time = base::TimeDelta::FromMicroseconds(100) + time;
@@ -243,7 +244,7 @@ TEST(TopControlsManagerTest, PartialShownWithAmbiguousThresholdHides) {
manager->ScrollEnd();
EXPECT_TRUE(manager->animation());
- base::TimeTicks time = base::TimeTicks::Now();
+ base::TimeTicks time = gfx::FrameTime::Now();
float previous_offset = manager->controls_top_offset();
while (manager->animation()) {
time = base::TimeDelta::FromMicroseconds(100) + time;
@@ -273,7 +274,7 @@ TEST(TopControlsManagerTest, PartialShownWithAmbiguousThresholdShows) {
manager->ScrollEnd();
EXPECT_TRUE(manager->animation());
- base::TimeTicks time = base::TimeTicks::Now();
+ base::TimeTicks time = gfx::FrameTime::Now();
float previous_offset = manager->controls_top_offset();
while (manager->animation()) {
time = base::TimeDelta::FromMicroseconds(100) + time;
@@ -286,5 +287,88 @@ TEST(TopControlsManagerTest, PartialShownWithAmbiguousThresholdShows) {
EXPECT_EQ(100.f, manager->content_top_offset());
}
+TEST(TopControlsManagerTest, PinchIgnoresScroll) {
+ MockTopControlsManagerClient client(0.5f, 0.5f);
+ TopControlsManager* manager = client.manager();
+
+ // Hide the controls.
+ manager->ScrollBegin();
+ EXPECT_EQ(0.f, manager->controls_top_offset());
+
+ manager->ScrollBy(gfx::Vector2dF(0.f, 300.f));
+ EXPECT_EQ(-100.f, manager->controls_top_offset());
+
+ manager->PinchBegin();
+ EXPECT_EQ(-100.f, manager->controls_top_offset());
+
+ // Scrolls are ignored during pinch.
+ manager->ScrollBy(gfx::Vector2dF(0.f, -15.f));
+ EXPECT_EQ(-100.f, manager->controls_top_offset());
+ manager->PinchEnd();
+ EXPECT_EQ(-100.f, manager->controls_top_offset());
+
+ // Scrolls should no long be ignored.
+ manager->ScrollBy(gfx::Vector2dF(0.f, -15.f));
+ EXPECT_EQ(-85.f, manager->controls_top_offset());
+ EXPECT_EQ(15.f, manager->content_top_offset());
+ manager->ScrollEnd();
+
+ EXPECT_TRUE(manager->animation());
+}
+
+TEST(TopControlsManagerTest, PinchBeginStartsAnimationIfNecessary) {
+ MockTopControlsManagerClient client(0.5f, 0.5f);
+ TopControlsManager* manager = client.manager();
+
+ manager->ScrollBegin();
+ manager->ScrollBy(gfx::Vector2dF(0.f, 300.f));
+ EXPECT_EQ(-100.f, manager->controls_top_offset());
+
+ manager->PinchBegin();
+ EXPECT_FALSE(manager->animation());
+
+ manager->PinchEnd();
+ EXPECT_FALSE(manager->animation());
+
+ manager->ScrollBy(gfx::Vector2dF(0.f, -15.f));
+ EXPECT_EQ(-85.f, manager->controls_top_offset());
+ EXPECT_EQ(15.f, manager->content_top_offset());
+
+ manager->PinchBegin();
+ EXPECT_TRUE(manager->animation());
+
+ base::TimeTicks time = base::TimeTicks::Now();
+ float previous_offset = manager->controls_top_offset();
+ while (manager->animation()) {
+ time = base::TimeDelta::FromMicroseconds(100) + time;
+ manager->Animate(time);
+ EXPECT_LT(manager->controls_top_offset(), previous_offset);
+ previous_offset = manager->controls_top_offset();
+ }
+ EXPECT_FALSE(manager->animation());
+
+ manager->PinchEnd();
+ EXPECT_FALSE(manager->animation());
+
+ manager->ScrollBy(gfx::Vector2dF(0.f, -55.f));
+ EXPECT_EQ(-45.f, manager->controls_top_offset());
+ EXPECT_EQ(55.f, manager->content_top_offset());
+ EXPECT_FALSE(manager->animation());
+
+ manager->ScrollEnd();
+ EXPECT_TRUE(manager->animation());
+
+ time = base::TimeTicks::Now();
+ previous_offset = manager->controls_top_offset();
+ while (manager->animation()) {
+ time = base::TimeDelta::FromMicroseconds(100) + time;
+ manager->Animate(time);
+ EXPECT_GT(manager->controls_top_offset(), previous_offset);
+ previous_offset = manager->controls_top_offset();
+ }
+ EXPECT_FALSE(manager->animation());
+ EXPECT_EQ(0.f, manager->controls_top_offset());
+}
+
} // namespace
} // namespace cc
diff --git a/chromium/cc/layers/append_quads_data.h b/chromium/cc/layers/append_quads_data.h
index 1ec8184a17a..5e19731fd28 100644
--- a/chromium/cc/layers/append_quads_data.h
+++ b/chromium/cc/layers/append_quads_data.h
@@ -12,19 +12,15 @@ namespace cc {
struct AppendQuadsData {
AppendQuadsData()
- : had_occlusion_from_outside_target_surface(false),
- had_incomplete_tile(false),
+ : had_incomplete_tile(false),
num_missing_tiles(0),
render_pass_id(0, 0) {}
explicit AppendQuadsData(RenderPass::Id render_pass_id)
- : had_occlusion_from_outside_target_surface(false),
- had_incomplete_tile(false),
+ : had_incomplete_tile(false),
num_missing_tiles(0),
render_pass_id(render_pass_id) {}
- // Set by the QuadCuller.
- bool had_occlusion_from_outside_target_surface;
// Set by the layer appending quads.
bool had_incomplete_tile;
// Set by the layer appending quads.
diff --git a/chromium/cc/layers/compositing_reasons.h b/chromium/cc/layers/compositing_reasons.h
index 02354a03283..6331a906ada 100644
--- a/chromium/cc/layers/compositing_reasons.h
+++ b/chromium/cc/layers/compositing_reasons.h
@@ -53,6 +53,8 @@ const uint64 kCompositingReasonLayerForBackground = GG_UINT64_C(1) << 30;
const uint64 kCompositingReasonLayerForMask = GG_UINT64_C(1) << 31;
const uint64 kCompositingReasonOverflowScrollingParent = GG_UINT64_C(1) << 32;
const uint64 kCompositingReasonOutOfFlowClipping = GG_UINT64_C(1) << 33;
+const uint64 kCompositingReasonIsolateCompositedDescendants =
+ GG_UINT64_C(1) << 35;
typedef uint64 CompositingReasons;
diff --git a/chromium/cc/layers/content_layer.cc b/chromium/cc/layers/content_layer.cc
index 3d611eeef28..24cb8b36361 100644
--- a/chromium/cc/layers/content_layer.cc
+++ b/chromium/cc/layers/content_layer.cc
@@ -165,4 +165,10 @@ skia::RefPtr<SkPicture> ContentLayer::GetPicture() const {
return picture;
}
+void ContentLayer::OnOutputSurfaceCreated() {
+ SetTextureFormat(
+ layer_tree_host()->GetRendererCapabilities().best_texture_format);
+ TiledLayer::OnOutputSurfaceCreated();
+}
+
} // namespace cc
diff --git a/chromium/cc/layers/content_layer.h b/chromium/cc/layers/content_layer.h
index a076c31dcac..45de86cde71 100644
--- a/chromium/cc/layers/content_layer.h
+++ b/chromium/cc/layers/content_layer.h
@@ -54,13 +54,17 @@ class CC_EXPORT ContentLayer : public TiledLayer {
virtual skia::RefPtr<SkPicture> GetPicture() const OVERRIDE;
+ virtual void OnOutputSurfaceCreated() OVERRIDE;
+
protected:
explicit ContentLayer(ContentLayerClient* client);
virtual ~ContentLayer();
- private:
// TiledLayer implementation.
virtual LayerUpdater* Updater() const OVERRIDE;
+
+ private:
+ // TiledLayer implementation.
virtual void CreateUpdaterIfNeeded() OVERRIDE;
void UpdateCanUseLCDText();
diff --git a/chromium/cc/layers/delegated_frame_provider.cc b/chromium/cc/layers/delegated_frame_provider.cc
new file mode 100644
index 00000000000..c97f23171f5
--- /dev/null
+++ b/chromium/cc/layers/delegated_frame_provider.cc
@@ -0,0 +1,110 @@
+// 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/delegated_frame_provider.h"
+
+#include "cc/layers/delegated_frame_resource_collection.h"
+#include "cc/layers/delegated_renderer_layer.h"
+#include "cc/output/delegated_frame_data.h"
+#include "cc/quads/render_pass_draw_quad.h"
+
+namespace cc {
+
+DelegatedFrameProvider::DelegatedFrameProvider(
+ const scoped_refptr<DelegatedFrameResourceCollection>& resource_collection,
+ scoped_ptr<DelegatedFrameData> frame)
+ : resource_collection_(resource_collection) {
+ RenderPass* root_pass = frame->render_pass_list.back();
+ frame_size_ = root_pass->output_rect.size();
+ DCHECK(!frame_size_.IsEmpty());
+ SetFrameData(frame.Pass());
+}
+
+DelegatedFrameProvider::~DelegatedFrameProvider() {
+ ReturnedResourceArray returned;
+ TransferableResource::ReturnResources(frame_->resource_list, &returned);
+ resource_collection_->UnrefResources(returned);
+}
+
+void DelegatedFrameProvider::AddObserver(DelegatedRendererLayer* layer) {
+ if (DCHECK_IS_ON()) {
+ for (size_t i = 0; i < observers_.size(); ++i)
+ DCHECK(observers_[i].layer != layer);
+ }
+
+ observers_.push_back(Observer(layer, gfx::RectF(frame_size_)));
+
+ DCHECK(frame_) << "Must have a frame when given to a DelegatedRendererLayer.";
+}
+
+void DelegatedFrameProvider::RemoveObserver(DelegatedRendererLayer* layer) {
+ bool found_observer = false;
+ for (size_t i = 0; i < observers_.size(); ++i) {
+ if (observers_[i].layer != layer)
+ continue;
+ observers_.erase(observers_.begin() + i);
+ found_observer = true;
+ break;
+ }
+ DCHECK(found_observer);
+}
+
+void DelegatedFrameProvider::SetFrameData(
+ scoped_ptr<DelegatedFrameData> frame) {
+ DCHECK(frame);
+ DCHECK_NE(0u, frame->render_pass_list.size());
+
+ if (frame_) {
+ ReturnedResourceArray returned;
+ TransferableResource::ReturnResources(frame_->resource_list, &returned);
+ resource_collection_->UnrefResources(returned);
+ }
+
+ frame_ = frame.Pass();
+
+ resource_collection_->ReceivedResources(frame_->resource_list);
+ resource_collection_->RefResources(frame_->resource_list);
+
+ RenderPass* root_pass = frame_->render_pass_list.back();
+ DCHECK_EQ(frame_size_.ToString(), root_pass->output_rect.size().ToString())
+ << "All frames in a single DelegatedFrameProvider must have the same "
+ << "size. Use a new frame provider for frames of a different size.";
+
+ for (size_t i = 0; i < observers_.size(); ++i) {
+ observers_[i].damage =
+ gfx::UnionRects(observers_[i].damage, root_pass->damage_rect);
+ observers_[i].layer->ProviderHasNewFrame();
+ }
+}
+
+DelegatedFrameData* DelegatedFrameProvider::GetFrameDataAndRefResources(
+ DelegatedRendererLayer* observer,
+ gfx::RectF* 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();
+ found_observer = true;
+ }
+ DCHECK(found_observer);
+
+ resource_collection_->RefResources(frame_->resource_list);
+ return frame_.get();
+}
+
+ReturnCallback
+DelegatedFrameProvider::GetReturnResourcesCallbackForImplThread() {
+ return resource_collection_->GetReturnResourcesCallbackForImplThread();
+}
+
+void DelegatedFrameProvider::UnrefResourcesOnMainThread(
+ const ReturnedResourceArray& returned) {
+ resource_collection_->UnrefResources(returned);
+}
+
+} // namespace cc
diff --git a/chromium/cc/layers/delegated_frame_provider.h b/chromium/cc/layers/delegated_frame_provider.h
new file mode 100644
index 00000000000..b71c74881b2
--- /dev/null
+++ b/chromium/cc/layers/delegated_frame_provider.h
@@ -0,0 +1,75 @@
+// 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_LAYERS_DELEGATED_FRAME_PROVIDER_H_
+#define CC_LAYERS_DELEGATED_FRAME_PROVIDER_H_
+
+#include <vector>
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "cc/base/cc_export.h"
+#include "cc/resources/return_callback.h"
+#include "cc/resources/returned_resource.h"
+#include "ui/gfx/rect_f.h"
+#include "ui/gfx/size.h"
+
+namespace cc {
+class DelegatedFrameData;
+class DelegatedFrameResourceCollection;
+class DelegatedRendererLayer;
+
+// Only one observing layer has ownership of the DelegatedFrameProvider. Only
+// the active observer should call GetFrameDataAndRefResources(). All frames
+// provided by a single DelegatedFrameProvider must have the same size. A new
+// provider must be used for frames of a different size.
+class CC_EXPORT DelegatedFrameProvider
+ : public base::RefCounted<DelegatedFrameProvider> {
+ public:
+ explicit DelegatedFrameProvider(
+ const scoped_refptr<DelegatedFrameResourceCollection>&
+ resource_collection,
+ scoped_ptr<DelegatedFrameData> frame);
+
+ void AddObserver(DelegatedRendererLayer* layer);
+ void RemoveObserver(DelegatedRendererLayer* layer);
+
+ void SetFrameData(scoped_ptr<DelegatedFrameData> frame);
+
+ // The DelegatedFrameData returned here must be displayed in order to not
+ // lose track of damage.
+ DelegatedFrameData* GetFrameDataAndRefResources(
+ DelegatedRendererLayer* observer,
+ gfx::RectF* damage);
+
+ ReturnCallback GetReturnResourcesCallbackForImplThread();
+ void UnrefResourcesOnMainThread(const ReturnedResourceArray& unused);
+
+ gfx::Size frame_size() const { return frame_size_; }
+
+ private:
+ friend class base::RefCounted<DelegatedFrameProvider>;
+ ~DelegatedFrameProvider();
+
+ scoped_refptr<DelegatedFrameResourceCollection> resource_collection_;
+
+ scoped_ptr<DelegatedFrameData> frame_;
+
+ struct Observer {
+ DelegatedRendererLayer* layer;
+ gfx::RectF damage;
+
+ Observer(DelegatedRendererLayer* layer, const gfx::RectF& damage)
+ : layer(layer), damage(damage) {}
+ };
+ std::vector<Observer> observers_;
+
+ gfx::Size frame_size_;
+
+ DISALLOW_COPY_AND_ASSIGN(DelegatedFrameProvider);
+};
+
+} // namespace cc
+
+#endif // CC_LAYERS_DELEGATED_FRAME_PROVIDER_H_
diff --git a/chromium/cc/layers/delegated_frame_provider_unittest.cc b/chromium/cc/layers/delegated_frame_provider_unittest.cc
new file mode 100644
index 00000000000..20b355c6192
--- /dev/null
+++ b/chromium/cc/layers/delegated_frame_provider_unittest.cc
@@ -0,0 +1,395 @@
+// 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/delegated_frame_provider.h"
+#include "cc/layers/delegated_frame_resource_collection.h"
+#include "cc/layers/delegated_renderer_layer.h"
+#include "cc/output/delegated_frame_data.h"
+#include "cc/quads/texture_draw_quad.h"
+#include "cc/resources/returned_resource.h"
+#include "cc/resources/transferable_resource.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace cc {
+namespace {
+
+class DelegatedFrameProviderTest
+ : public testing::Test,
+ public DelegatedFrameResourceCollectionClient {
+ protected:
+ DelegatedFrameProviderTest() : resources_available_(false) {}
+
+ scoped_ptr<DelegatedFrameData> CreateFrameData(gfx::Rect root_output_rect,
+ gfx::Rect root_damage_rect) {
+ scoped_ptr<DelegatedFrameData> frame(new DelegatedFrameData);
+
+ scoped_ptr<RenderPass> root_pass(RenderPass::Create());
+ root_pass->SetNew(RenderPass::Id(1, 1),
+ root_output_rect,
+ root_damage_rect,
+ gfx::Transform());
+ frame->render_pass_list.push_back(root_pass.Pass());
+ return frame.Pass();
+ }
+
+ void AddTransferableResource(DelegatedFrameData* frame,
+ ResourceProvider::ResourceId resource_id) {
+ TransferableResource resource;
+ resource.id = resource_id;
+ resource.target = GL_TEXTURE_2D;
+ frame->resource_list.push_back(resource);
+ }
+
+ void AddTextureQuad(DelegatedFrameData* frame,
+ ResourceProvider::ResourceId resource_id) {
+ scoped_ptr<SharedQuadState> sqs = SharedQuadState::Create();
+ scoped_ptr<TextureDrawQuad> quad = TextureDrawQuad::Create();
+ float vertex_opacity[4] = {1.f, 1.f, 1.f, 1.f};
+ quad->SetNew(sqs.get(),
+ gfx::Rect(0, 0, 10, 10),
+ gfx::Rect(0, 0, 10, 10),
+ resource_id,
+ false,
+ gfx::PointF(0.f, 0.f),
+ gfx::PointF(1.f, 1.f),
+ SK_ColorTRANSPARENT,
+ vertex_opacity,
+ false);
+ frame->render_pass_list[0]->shared_quad_state_list.push_back(sqs.Pass());
+ frame->render_pass_list[0]->quad_list.push_back(quad.PassAs<DrawQuad>());
+ }
+
+ virtual void SetUp() OVERRIDE {
+ resource_collection_ = new DelegatedFrameResourceCollection;
+ resource_collection_->SetClient(this);
+ }
+
+ virtual void TearDown() OVERRIDE { resource_collection_->SetClient(NULL); }
+
+ virtual void UnusedResourcesAreAvailable() OVERRIDE {
+ resources_available_ = true;
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources_);
+ }
+
+ bool ReturnAndResetResourcesAvailable() {
+ bool r = resources_available_;
+ resources_available_ = false;
+ return r;
+ }
+
+ void SetFrameProvider(scoped_ptr<DelegatedFrameData> frame_data) {
+ frame_provider_ =
+ new DelegatedFrameProvider(resource_collection_, frame_data.Pass());
+ }
+
+ scoped_refptr<DelegatedFrameResourceCollection> resource_collection_;
+ scoped_refptr<DelegatedFrameProvider> frame_provider_;
+ bool resources_available_;
+ ReturnedResourceArray resources_;
+};
+
+TEST_F(DelegatedFrameProviderTest, SameResources) {
+ scoped_ptr<DelegatedFrameData> frame =
+ CreateFrameData(gfx::Rect(1, 1), gfx::Rect(1, 1));
+ AddTextureQuad(frame.get(), 444);
+ AddTransferableResource(frame.get(), 444);
+ SetFrameProvider(frame.Pass());
+
+ frame = CreateFrameData(gfx::Rect(1, 1), gfx::Rect(1, 1));
+ AddTextureQuad(frame.get(), 444);
+ AddTransferableResource(frame.get(), 444);
+ SetFrameProvider(frame.Pass());
+
+ EXPECT_FALSE(ReturnAndResetResourcesAvailable());
+ EXPECT_EQ(0u, resources_.size());
+
+ frame_provider_ = NULL;
+
+ EXPECT_TRUE(ReturnAndResetResourcesAvailable());
+ EXPECT_EQ(1u, resources_.size());
+ EXPECT_EQ(444u, resources_[0].id);
+}
+
+TEST_F(DelegatedFrameProviderTest, ReplaceResources) {
+ scoped_ptr<DelegatedFrameData> frame =
+ CreateFrameData(gfx::Rect(1, 1), gfx::Rect(1, 1));
+ AddTextureQuad(frame.get(), 444);
+ AddTransferableResource(frame.get(), 444);
+ SetFrameProvider(frame.Pass());
+
+ EXPECT_FALSE(ReturnAndResetResourcesAvailable());
+
+ frame = CreateFrameData(gfx::Rect(1, 1), gfx::Rect(1, 1));
+ AddTextureQuad(frame.get(), 555);
+ AddTransferableResource(frame.get(), 555);
+ SetFrameProvider(frame.Pass());
+
+ EXPECT_TRUE(ReturnAndResetResourcesAvailable());
+ EXPECT_EQ(1u, resources_.size());
+ EXPECT_EQ(444u, resources_[0].id);
+ resources_.clear();
+
+ frame_provider_ = NULL;
+
+ EXPECT_TRUE(ReturnAndResetResourcesAvailable());
+ EXPECT_EQ(1u, resources_.size());
+ EXPECT_EQ(555u, resources_[0].id);
+}
+
+TEST_F(DelegatedFrameProviderTest, RefResources) {
+ scoped_ptr<DelegatedFrameData> frame =
+ CreateFrameData(gfx::Rect(5, 5), gfx::Rect(2, 2));
+ AddTextureQuad(frame.get(), 444);
+ AddTransferableResource(frame.get(), 444);
+
+ TransferableResourceArray reffed = frame->resource_list;
+ ReturnedResourceArray returned;
+ TransferableResource::ReturnResources(reffed, &returned);
+
+ SetFrameProvider(frame.Pass());
+
+ scoped_refptr<DelegatedRendererLayer> observer1 =
+ DelegatedRendererLayer::Create(frame_provider_);
+ scoped_refptr<DelegatedRendererLayer> observer2 =
+ DelegatedRendererLayer::Create(frame_provider_);
+
+ gfx::RectF damage;
+
+ // Both observers get a full frame of damage on the first request.
+ frame_provider_->GetFrameDataAndRefResources(observer1, &damage);
+ EXPECT_EQ(gfx::RectF(5.f, 5.f).ToString(), damage.ToString());
+ frame_provider_->GetFrameDataAndRefResources(observer2, &damage);
+ EXPECT_EQ(gfx::RectF(5.f, 5.f).ToString(), damage.ToString());
+
+ // And both get no damage on the 2nd request. This adds a second ref to the
+ // resources.
+ frame_provider_->GetFrameDataAndRefResources(observer1, &damage);
+ EXPECT_EQ(gfx::RectF().ToString(), damage.ToString());
+ frame_provider_->GetFrameDataAndRefResources(observer2, &damage);
+ EXPECT_EQ(gfx::RectF().ToString(), damage.ToString());
+
+ EXPECT_FALSE(ReturnAndResetResourcesAvailable());
+
+ frame = CreateFrameData(gfx::Rect(5, 5), gfx::Rect(2, 2));
+ AddTextureQuad(frame.get(), 555);
+ AddTransferableResource(frame.get(), 555);
+ frame_provider_->SetFrameData(frame.Pass());
+
+ // The resources from the first frame are still reffed by the observers.
+ EXPECT_FALSE(ReturnAndResetResourcesAvailable());
+
+ // There are 4 refs taken.
+ frame_provider_->UnrefResourcesOnMainThread(returned);
+ EXPECT_FALSE(ReturnAndResetResourcesAvailable());
+ frame_provider_->UnrefResourcesOnMainThread(returned);
+ EXPECT_FALSE(ReturnAndResetResourcesAvailable());
+ frame_provider_->UnrefResourcesOnMainThread(returned);
+ EXPECT_FALSE(ReturnAndResetResourcesAvailable());
+
+ // The 4th unref will release them.
+ frame_provider_->UnrefResourcesOnMainThread(returned);
+
+ EXPECT_TRUE(ReturnAndResetResourcesAvailable());
+ EXPECT_EQ(1u, resources_.size());
+ EXPECT_EQ(444u, resources_[0].id);
+}
+
+TEST_F(DelegatedFrameProviderTest, RefResourcesInFrameProvider) {
+ scoped_ptr<DelegatedFrameData> frame =
+ CreateFrameData(gfx::Rect(5, 5), gfx::Rect(2, 2));
+ AddTextureQuad(frame.get(), 444);
+ AddTransferableResource(frame.get(), 444);
+
+ TransferableResourceArray reffed = frame->resource_list;
+ ReturnedResourceArray returned;
+ TransferableResource::ReturnResources(reffed, &returned);
+
+ SetFrameProvider(frame.Pass());
+
+ scoped_refptr<DelegatedRendererLayer> observer1 =
+ DelegatedRendererLayer::Create(frame_provider_);
+ scoped_refptr<DelegatedRendererLayer> observer2 =
+ DelegatedRendererLayer::Create(frame_provider_);
+
+ gfx::RectF damage;
+
+ // Take a ref on each observer.
+ frame_provider_->GetFrameDataAndRefResources(observer1, &damage);
+ frame_provider_->GetFrameDataAndRefResources(observer2, &damage);
+
+ EXPECT_FALSE(ReturnAndResetResourcesAvailable());
+
+ // Release both refs. But there's still a ref held in the frame
+ // provider itself.
+ frame_provider_->UnrefResourcesOnMainThread(returned);
+ frame_provider_->UnrefResourcesOnMainThread(returned);
+ EXPECT_FALSE(ReturnAndResetResourcesAvailable());
+
+ // Setting a new frame will release it.
+ frame = CreateFrameData(gfx::Rect(5, 5), gfx::Rect(2, 2));
+ AddTextureQuad(frame.get(), 555);
+ AddTransferableResource(frame.get(), 555);
+ frame_provider_->SetFrameData(frame.Pass());
+
+ EXPECT_TRUE(ReturnAndResetResourcesAvailable());
+ EXPECT_EQ(1u, resources_.size());
+ EXPECT_EQ(444u, resources_[0].id);
+}
+
+TEST_F(DelegatedFrameProviderTest, RefResourcesInFrameProviderUntilDestroy) {
+ scoped_ptr<DelegatedFrameData> frame =
+ CreateFrameData(gfx::Rect(5, 5), gfx::Rect(2, 2));
+ AddTextureQuad(frame.get(), 444);
+ AddTransferableResource(frame.get(), 444);
+
+ TransferableResourceArray reffed = frame->resource_list;
+ ReturnedResourceArray returned;
+ TransferableResource::ReturnResources(reffed, &returned);
+
+ SetFrameProvider(frame.Pass());
+
+ scoped_refptr<DelegatedRendererLayer> observer1 =
+ DelegatedRendererLayer::Create(frame_provider_);
+ scoped_refptr<DelegatedRendererLayer> observer2 =
+ DelegatedRendererLayer::Create(frame_provider_);
+
+ gfx::RectF damage;
+
+ // Take a ref on each observer.
+ frame_provider_->GetFrameDataAndRefResources(observer1, &damage);
+ frame_provider_->GetFrameDataAndRefResources(observer2, &damage);
+
+ EXPECT_FALSE(ReturnAndResetResourcesAvailable());
+
+ // Release both refs. But there's still a ref held in the frame
+ // provider itself.
+ frame_provider_->UnrefResourcesOnMainThread(returned);
+ frame_provider_->UnrefResourcesOnMainThread(returned);
+ EXPECT_FALSE(ReturnAndResetResourcesAvailable());
+
+ // Releasing all references to the frame provider will release
+ // the frame.
+ observer1 = NULL;
+ observer2 = NULL;
+ EXPECT_FALSE(ReturnAndResetResourcesAvailable());
+
+ frame_provider_ = NULL;
+
+ EXPECT_TRUE(ReturnAndResetResourcesAvailable());
+ EXPECT_EQ(1u, resources_.size());
+ EXPECT_EQ(444u, resources_[0].id);
+}
+
+TEST_F(DelegatedFrameProviderTest, Damage) {
+ scoped_ptr<DelegatedFrameData> frame =
+ CreateFrameData(gfx::Rect(5, 5), gfx::Rect(2, 2));
+ AddTextureQuad(frame.get(), 444);
+ AddTransferableResource(frame.get(), 444);
+
+ TransferableResourceArray reffed = frame->resource_list;
+ ReturnedResourceArray returned;
+ TransferableResource::ReturnResources(reffed, &returned);
+
+ SetFrameProvider(frame.Pass());
+
+ scoped_refptr<DelegatedRendererLayer> observer1 =
+ DelegatedRendererLayer::Create(frame_provider_);
+ scoped_refptr<DelegatedRendererLayer> observer2 =
+ DelegatedRendererLayer::Create(frame_provider_);
+
+ gfx::RectF damage;
+
+ // Both observers get a full frame of damage on the first request.
+ frame_provider_->GetFrameDataAndRefResources(observer1, &damage);
+ EXPECT_EQ(gfx::RectF(5.f, 5.f).ToString(), damage.ToString());
+ frame_provider_->GetFrameDataAndRefResources(observer2, &damage);
+ EXPECT_EQ(gfx::RectF(5.f, 5.f).ToString(), damage.ToString());
+
+ // And both get no damage on the 2nd request.
+ frame_provider_->GetFrameDataAndRefResources(observer1, &damage);
+ EXPECT_EQ(gfx::RectF().ToString(), damage.ToString());
+ frame_provider_->GetFrameDataAndRefResources(observer2, &damage);
+ EXPECT_EQ(gfx::RectF().ToString(), damage.ToString());
+
+ frame = CreateFrameData(gfx::Rect(5, 5), gfx::Rect(2, 2));
+ AddTextureQuad(frame.get(), 555);
+ AddTransferableResource(frame.get(), 555);
+ frame_provider_->SetFrameData(frame.Pass());
+
+ // Both observers get the damage for the new frame.
+ frame_provider_->GetFrameDataAndRefResources(observer1, &damage);
+ EXPECT_EQ(gfx::RectF(2.f, 2.f).ToString(), damage.ToString());
+ frame_provider_->GetFrameDataAndRefResources(observer2, &damage);
+ EXPECT_EQ(gfx::RectF(2.f, 2.f).ToString(), damage.ToString());
+
+ // And both get no damage on the 2nd request.
+ frame_provider_->GetFrameDataAndRefResources(observer1, &damage);
+ EXPECT_EQ(gfx::RectF().ToString(), damage.ToString());
+ frame_provider_->GetFrameDataAndRefResources(observer2, &damage);
+ EXPECT_EQ(gfx::RectF().ToString(), damage.ToString());
+}
+
+TEST_F(DelegatedFrameProviderTest, LostNothing) {
+ scoped_ptr<DelegatedFrameData> frame =
+ CreateFrameData(gfx::Rect(5, 5), gfx::Rect(5, 5));
+
+ TransferableResourceArray reffed = frame->resource_list;
+
+ SetFrameProvider(frame.Pass());
+
+ // There is nothing to lose.
+ EXPECT_FALSE(ReturnAndResetResourcesAvailable());
+ EXPECT_FALSE(resource_collection_->LoseAllResources());
+ EXPECT_FALSE(ReturnAndResetResourcesAvailable());
+ EXPECT_EQ(0u, resources_.size());
+}
+
+TEST_F(DelegatedFrameProviderTest, LostSomething) {
+ scoped_ptr<DelegatedFrameData> frame =
+ CreateFrameData(gfx::Rect(5, 5), gfx::Rect(5, 5));
+ AddTextureQuad(frame.get(), 444);
+ AddTransferableResource(frame.get(), 444);
+
+ SetFrameProvider(frame.Pass());
+
+ // Add a second reference on the resource.
+ frame = CreateFrameData(gfx::Rect(5, 5), gfx::Rect(5, 5));
+ AddTextureQuad(frame.get(), 444);
+ AddTransferableResource(frame.get(), 444);
+
+ SetFrameProvider(frame.Pass());
+
+ // There is something to lose.
+ EXPECT_FALSE(ReturnAndResetResourcesAvailable());
+ EXPECT_TRUE(resource_collection_->LoseAllResources());
+ EXPECT_TRUE(ReturnAndResetResourcesAvailable());
+
+ EXPECT_EQ(1u, resources_.size());
+ EXPECT_EQ(444u, resources_[0].id);
+ EXPECT_EQ(2, resources_[0].count);
+}
+
+TEST_F(DelegatedFrameProviderTest, NothingReturnedAfterLoss) {
+ scoped_ptr<DelegatedFrameData> frame =
+ CreateFrameData(gfx::Rect(1, 1), gfx::Rect(1, 1));
+ AddTextureQuad(frame.get(), 444);
+ AddTransferableResource(frame.get(), 444);
+ SetFrameProvider(frame.Pass());
+
+ EXPECT_FALSE(ReturnAndResetResourcesAvailable());
+
+ // Lose all the resources.
+ EXPECT_TRUE(resource_collection_->LoseAllResources());
+ EXPECT_TRUE(ReturnAndResetResourcesAvailable());
+ resources_.clear();
+
+ frame_provider_ = NULL;
+
+ // Nothing is returned twice.
+ EXPECT_FALSE(ReturnAndResetResourcesAvailable());
+ EXPECT_EQ(0u, resources_.size());
+}
+
+} // namespace
+} // namespace cc
diff --git a/chromium/cc/layers/delegated_frame_resource_collection.cc b/chromium/cc/layers/delegated_frame_resource_collection.cc
new file mode 100644
index 00000000000..5ca4eda57d7
--- /dev/null
+++ b/chromium/cc/layers/delegated_frame_resource_collection.cc
@@ -0,0 +1,133 @@
+// 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/delegated_frame_resource_collection.h"
+
+#include "base/bind.h"
+#include "cc/trees/blocking_task_runner.h"
+
+namespace cc {
+
+DelegatedFrameResourceCollection::DelegatedFrameResourceCollection()
+ : client_(NULL),
+ main_thread_runner_(BlockingTaskRunner::current()),
+ lost_all_resources_(false),
+ weak_ptr_factory_(this) {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
+}
+
+DelegatedFrameResourceCollection::~DelegatedFrameResourceCollection() {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
+}
+
+void DelegatedFrameResourceCollection::SetClient(
+ DelegatedFrameResourceCollectionClient* client) {
+ client_ = client;
+}
+
+void DelegatedFrameResourceCollection::TakeUnusedResourcesForChildCompositor(
+ ReturnedResourceArray* array) {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
+ DCHECK(array->empty());
+ array->swap(returned_resources_for_child_compositor_);
+}
+
+bool DelegatedFrameResourceCollection::LoseAllResources() {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
+ DCHECK(!lost_all_resources_);
+ lost_all_resources_ = true;
+
+ if (resource_id_ref_count_map_.empty())
+ return false;
+
+ ReturnedResourceArray to_return;
+
+ for (ResourceIdRefCountMap::iterator it = resource_id_ref_count_map_.begin();
+ it != resource_id_ref_count_map_.end();
+ ++it) {
+ DCHECK_GE(it->second.refs_to_wait_for, 1);
+
+ ReturnedResource returned;
+ returned.id = it->first;
+ returned.count = it->second.refs_to_return;
+ returned.lost = true;
+ to_return.push_back(returned);
+ }
+
+ returned_resources_for_child_compositor_.insert(
+ returned_resources_for_child_compositor_.end(),
+ to_return.begin(),
+ to_return.end());
+ if (client_)
+ client_->UnusedResourcesAreAvailable();
+ return true;
+}
+
+void DelegatedFrameResourceCollection::ReceivedResources(
+ const TransferableResourceArray& resources) {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
+ DCHECK(!lost_all_resources_);
+
+ for (size_t i = 0; i < resources.size(); ++i)
+ resource_id_ref_count_map_[resources[i].id].refs_to_return++;
+}
+
+void DelegatedFrameResourceCollection::UnrefResources(
+ const ReturnedResourceArray& returned) {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
+
+ if (lost_all_resources_)
+ return;
+
+ ReturnedResourceArray to_return;
+
+ for (size_t i = 0; i < returned.size(); ++i) {
+ ResourceIdRefCountMap::iterator it =
+ resource_id_ref_count_map_.find(returned[i].id);
+ DCHECK(it != resource_id_ref_count_map_.end());
+ DCHECK_GE(it->second.refs_to_wait_for, returned[i].count);
+ it->second.refs_to_wait_for -= returned[i].count;
+ if (it->second.refs_to_wait_for == 0) {
+ to_return.push_back(returned[i]);
+ to_return.back().count = it->second.refs_to_return;
+ resource_id_ref_count_map_.erase(it);
+ }
+ }
+
+ if (to_return.empty())
+ return;
+
+ returned_resources_for_child_compositor_.insert(
+ returned_resources_for_child_compositor_.end(),
+ to_return.begin(),
+ to_return.end());
+ if (client_)
+ client_->UnusedResourcesAreAvailable();
+}
+
+void DelegatedFrameResourceCollection::RefResources(
+ const TransferableResourceArray& resources) {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
+ for (size_t i = 0; i < resources.size(); ++i)
+ resource_id_ref_count_map_[resources[i].id].refs_to_wait_for++;
+}
+
+static void UnrefResourcesOnImplThread(
+ base::WeakPtr<DelegatedFrameResourceCollection> self,
+ scoped_refptr<BlockingTaskRunner> main_thread_runner,
+ const ReturnedResourceArray& returned) {
+ main_thread_runner->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &DelegatedFrameResourceCollection::UnrefResources, self, returned));
+}
+
+ReturnCallback
+DelegatedFrameResourceCollection::GetReturnResourcesCallbackForImplThread() {
+ return base::Bind(&UnrefResourcesOnImplThread,
+ weak_ptr_factory_.GetWeakPtr(),
+ main_thread_runner_);
+}
+
+} // namespace cc
diff --git a/chromium/cc/layers/delegated_frame_resource_collection.h b/chromium/cc/layers/delegated_frame_resource_collection.h
new file mode 100644
index 00000000000..9a5d336749b
--- /dev/null
+++ b/chromium/cc/layers/delegated_frame_resource_collection.h
@@ -0,0 +1,71 @@
+// 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_LAYERS_DELEGATED_FRAME_RESOURCE_COLLECTION_H_
+#define CC_LAYERS_DELEGATED_FRAME_RESOURCE_COLLECTION_H_
+
+#include "base/containers/hash_tables.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/threading/thread_checker.h"
+#include "cc/base/cc_export.h"
+#include "cc/resources/return_callback.h"
+#include "cc/resources/returned_resource.h"
+#include "cc/resources/transferable_resource.h"
+
+namespace cc {
+class BlockingTaskRunner;
+
+class CC_EXPORT DelegatedFrameResourceCollectionClient {
+ public:
+ // Called to inform the client that returned resources can be
+ // grabbed off the DelegatedFrameResourceCollection.
+ virtual void UnusedResourcesAreAvailable() = 0;
+};
+
+class CC_EXPORT DelegatedFrameResourceCollection
+ : public base::RefCounted<DelegatedFrameResourceCollection> {
+ public:
+ DelegatedFrameResourceCollection();
+
+ void SetClient(DelegatedFrameResourceCollectionClient* client);
+
+ void TakeUnusedResourcesForChildCompositor(ReturnedResourceArray* array);
+
+ // Considers all resources as lost, and returns true if it held any resource
+ // to lose.
+ bool LoseAllResources();
+
+ // Methods for DelegatedFrameProvider.
+ void RefResources(const TransferableResourceArray& resources);
+ void UnrefResources(const ReturnedResourceArray& returned);
+ void ReceivedResources(const TransferableResourceArray& resources);
+ ReturnCallback GetReturnResourcesCallbackForImplThread();
+
+ private:
+ friend class base::RefCounted<DelegatedFrameResourceCollection>;
+ ~DelegatedFrameResourceCollection();
+
+ DelegatedFrameResourceCollectionClient* client_;
+ scoped_refptr<BlockingTaskRunner> main_thread_runner_;
+
+ ReturnedResourceArray returned_resources_for_child_compositor_;
+ bool lost_all_resources_;
+
+ struct RefCount {
+ int refs_to_return;
+ int refs_to_wait_for;
+ };
+ typedef base::hash_map<unsigned, RefCount> ResourceIdRefCountMap;
+ ResourceIdRefCountMap resource_id_ref_count_map_;
+
+ base::ThreadChecker main_thread_checker_;
+ base::WeakPtrFactory<DelegatedFrameResourceCollection> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(DelegatedFrameResourceCollection);
+};
+
+} // namespace cc
+
+#endif // CC_LAYERS_DELEGATED_FRAME_RESOURCE_COLLECTION_H_
diff --git a/chromium/cc/layers/delegated_frame_resource_collection_unittest.cc b/chromium/cc/layers/delegated_frame_resource_collection_unittest.cc
new file mode 100644
index 00000000000..29f0eb54a5a
--- /dev/null
+++ b/chromium/cc/layers/delegated_frame_resource_collection_unittest.cc
@@ -0,0 +1,160 @@
+// 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/bind.h"
+#include "base/run_loop.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/thread.h"
+#include "cc/layers/delegated_frame_resource_collection.h"
+#include "cc/resources/returned_resource.h"
+#include "cc/resources/transferable_resource.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace cc {
+namespace {
+
+class DelegatedFrameResourceCollectionTest
+ : public testing::Test,
+ public DelegatedFrameResourceCollectionClient {
+ protected:
+ DelegatedFrameResourceCollectionTest() : resources_available_(false) {}
+
+ virtual void SetUp() OVERRIDE { CreateResourceCollection(); }
+
+ virtual void TearDown() OVERRIDE { DestroyResourceCollection(); }
+
+ void CreateResourceCollection() {
+ DCHECK(!resource_collection_);
+ resource_collection_ = new DelegatedFrameResourceCollection;
+ resource_collection_->SetClient(this);
+ }
+
+ void DestroyResourceCollection() {
+ if (resource_collection_) {
+ resource_collection_->SetClient(NULL);
+ resource_collection_ = NULL;
+ }
+ }
+
+ TransferableResourceArray CreateResourceArray() {
+ TransferableResourceArray resources;
+ TransferableResource resource;
+ resource.id = 444;
+ resources.push_back(resource);
+ return resources;
+ }
+
+ virtual void UnusedResourcesAreAvailable() OVERRIDE {
+ resources_available_ = true;
+ resource_collection_->TakeUnusedResourcesForChildCompositor(
+ &returned_resources_);
+ if (!resources_available_closure_.is_null())
+ resources_available_closure_.Run();
+ }
+
+ bool ReturnAndResetResourcesAvailable() {
+ bool r = resources_available_;
+ resources_available_ = false;
+ return r;
+ }
+
+ scoped_refptr<DelegatedFrameResourceCollection> resource_collection_;
+ bool resources_available_;
+ ReturnedResourceArray returned_resources_;
+ base::Closure resources_available_closure_;
+};
+
+// This checks that taking the return callback doesn't take extra refcounts,
+// since it's sent to other threads.
+TEST_F(DelegatedFrameResourceCollectionTest, NoRef) {
+ // Start with one ref.
+ EXPECT_TRUE(resource_collection_->HasOneRef());
+
+ ReturnCallback return_callback =
+ resource_collection_->GetReturnResourcesCallbackForImplThread();
+
+ // Callback shouldn't take a ref since it's sent to other threads.
+ EXPECT_TRUE(resource_collection_->HasOneRef());
+}
+
+void ReturnResourcesOnThread(ReturnCallback callback,
+ const ReturnedResourceArray& resources,
+ base::WaitableEvent* event) {
+ callback.Run(resources);
+ if (event)
+ event->Wait();
+}
+
+// Tests that the ReturnCallback can run safely on threads even after the
+// last references to the collection were dropped.
+// Flaky: crbug.com/313441
+TEST_F(DelegatedFrameResourceCollectionTest, Thread) {
+ base::Thread thread("test thread");
+ thread.Start();
+
+ TransferableResourceArray resources = CreateResourceArray();
+ resource_collection_->ReceivedResources(resources);
+ resource_collection_->RefResources(resources);
+
+ ReturnedResourceArray returned_resources;
+ TransferableResource::ReturnResources(resources, &returned_resources);
+
+ base::WaitableEvent event(false, false);
+
+ {
+ base::RunLoop run_loop;
+ resources_available_closure_ = run_loop.QuitClosure();
+
+ thread.message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &ReturnResourcesOnThread,
+ resource_collection_->GetReturnResourcesCallbackForImplThread(),
+ returned_resources,
+ &event));
+
+ run_loop.Run();
+ }
+ EXPECT_TRUE(ReturnAndResetResourcesAvailable());
+ EXPECT_EQ(1u, returned_resources_.size());
+ EXPECT_EQ(444u, returned_resources_[0].id);
+ EXPECT_EQ(1, returned_resources_[0].count);
+ returned_resources_.clear();
+
+ // The event prevents the return resources callback from being deleted.
+ // Destroy the last reference from this thread to the collection before
+ // signaling the event, to ensure any reference taken by the callback, if any,
+ // would be the last one.
+ DestroyResourceCollection();
+ event.Signal();
+
+ CreateResourceCollection();
+ resource_collection_->ReceivedResources(resources);
+ resource_collection_->RefResources(resources);
+
+ // Destroy the collection before we have a chance to run the return callback.
+ ReturnCallback return_callback =
+ resource_collection_->GetReturnResourcesCallbackForImplThread();
+ resource_collection_->LoseAllResources();
+ DestroyResourceCollection();
+
+ EXPECT_TRUE(ReturnAndResetResourcesAvailable());
+ EXPECT_EQ(1u, returned_resources_.size());
+ EXPECT_EQ(444u, returned_resources_[0].id);
+ EXPECT_EQ(1, returned_resources_[0].count);
+ EXPECT_TRUE(returned_resources_[0].lost);
+ returned_resources_.clear();
+
+ base::WaitableEvent* null_event = NULL;
+ thread.message_loop()->PostTask(FROM_HERE,
+ base::Bind(&ReturnResourcesOnThread,
+ return_callback,
+ returned_resources,
+ null_event));
+
+ thread.Stop();
+}
+
+} // namespace
+} // namespace cc
diff --git a/chromium/cc/layers/delegated_renderer_layer.cc b/chromium/cc/layers/delegated_renderer_layer.cc
index cc49c753e25..6616b9b345a 100644
--- a/chromium/cc/layers/delegated_renderer_layer.cc
+++ b/chromium/cc/layers/delegated_renderer_layer.cc
@@ -4,7 +4,6 @@
#include "cc/layers/delegated_renderer_layer.h"
-#include "cc/layers/delegated_renderer_layer_client.h"
#include "cc/layers/delegated_renderer_layer_impl.h"
#include "cc/output/delegated_frame_data.h"
#include "cc/quads/render_pass_draw_quad.h"
@@ -14,20 +13,25 @@
namespace cc {
scoped_refptr<DelegatedRendererLayer> DelegatedRendererLayer::Create(
- DelegatedRendererLayerClient* client) {
+ const scoped_refptr<DelegatedFrameProvider>& frame_provider) {
return scoped_refptr<DelegatedRendererLayer>(
- new DelegatedRendererLayer(client));
+ new DelegatedRendererLayer(frame_provider));
}
DelegatedRendererLayer::DelegatedRendererLayer(
- DelegatedRendererLayerClient* client)
+ const scoped_refptr<DelegatedFrameProvider>& frame_provider)
: Layer(),
- client_(client),
- needs_filter_context_(false),
+ frame_provider_(frame_provider),
+ should_collect_new_frame_(true),
+ frame_data_(NULL),
main_thread_runner_(BlockingTaskRunner::current()),
- weak_ptrs_(this) {}
+ weak_ptrs_(this) {
+ frame_provider_->AddObserver(this);
+}
-DelegatedRendererLayer::~DelegatedRendererLayer() {}
+DelegatedRendererLayer::~DelegatedRendererLayer() {
+ frame_provider_->RemoveObserver(this);
+}
scoped_ptr<LayerImpl> DelegatedRendererLayer::CreateLayerImpl(
LayerTreeImpl* tree_impl) {
@@ -48,17 +52,15 @@ void DelegatedRendererLayer::SetLayerTreeHost(LayerTreeHost* host) {
// or we never commited a frame with resources.
SetNextCommitWaitsForActivation();
} else {
- if (needs_filter_context_)
- host->set_needs_filter_context();
+ // There is no active frame in the new layer tree host to wait for so no
+ // need to call SetNextCommitWaitsForActivation().
+ should_collect_new_frame_ = true;
+ SetNeedsUpdate();
}
Layer::SetLayerTreeHost(host);
}
-bool DelegatedRendererLayer::DrawsContent() const {
- return Layer::DrawsContent() && !frame_size_.IsEmpty();
-}
-
void DelegatedRendererLayer::PushPropertiesTo(LayerImpl* impl) {
Layer::PushPropertiesTo(impl);
@@ -68,24 +70,20 @@ void DelegatedRendererLayer::PushPropertiesTo(LayerImpl* impl) {
delegated_impl->SetDisplaySize(display_size_);
delegated_impl->CreateChildIdIfNeeded(
- base::Bind(&DelegatedRendererLayer::ReceiveUnusedResourcesOnImplThread,
- main_thread_runner_,
- weak_ptrs_.GetWeakPtr()));
+ frame_provider_->GetReturnResourcesCallbackForImplThread());
if (frame_data_)
- delegated_impl->SetFrameData(frame_data_.Pass(), damage_in_frame_);
- frame_data_.reset();
- damage_in_frame_ = gfx::RectF();
-
- // The ResourceProvider will have the new frame as soon as we push it to the
- // pending tree. So unused resources will be returned as well.
- if (client_)
- client_->DidCommitFrameData();
-
- // TODO(danakj): The DidCommitFrameData() notification requires a push
- // properties to happen in order to notify about unused resources returned
- // from the parent compositor. crbug.com/259090
- needs_push_properties_ = true;
+ delegated_impl->SetFrameData(frame_data_, frame_damage_);
+ frame_data_ = NULL;
+ frame_damage_ = gfx::RectF();
+}
+
+void DelegatedRendererLayer::ProviderHasNewFrame() {
+ should_collect_new_frame_ = true;
+ SetNeedsUpdate();
+ // The active frame needs to be replaced and resources returned before the
+ // commit is called complete.
+ SetNextCommitWaitsForActivation();
}
void DelegatedRendererLayer::SetDisplaySize(gfx::Size size) {
@@ -95,76 +93,42 @@ void DelegatedRendererLayer::SetDisplaySize(gfx::Size size) {
SetNeedsCommit();
}
-void DelegatedRendererLayer::SetFrameData(
- scoped_ptr<DelegatedFrameData> new_frame_data) {
- DCHECK(new_frame_data);
-
- if (frame_data_) {
- // Copy the resources from the last provided frame into the unused resources
- // list, as the new frame will provide its own resources.
- TransferableResource::ReturnResources(
- frame_data_->resource_list,
- &unused_resources_for_child_compositor_);
- }
- frame_data_ = new_frame_data.Pass();
- if (!frame_data_->render_pass_list.empty()) {
- RenderPass* root_pass = frame_data_->render_pass_list.back();
- damage_in_frame_.Union(root_pass->damage_rect);
- frame_size_ = root_pass->output_rect.size();
- } else {
- frame_size_ = gfx::Size();
- }
-
- // If any RenderPassDrawQuad has a filter operation, then we need a filter
- // context to draw this layer's content.
- for (size_t i = 0;
- !needs_filter_context_ && i < frame_data_->render_pass_list.size();
- ++i) {
- const QuadList& quad_list = frame_data_->render_pass_list[i]->quad_list;
- for (size_t j = 0; !needs_filter_context_ && j < quad_list.size(); ++j) {
+static bool FrameDataRequiresFilterContext(const DelegatedFrameData* frame) {
+ for (size_t i = 0; i < frame->render_pass_list.size(); ++i) {
+ const QuadList& quad_list = frame->render_pass_list[i]->quad_list;
+ for (size_t j = 0; j < quad_list.size(); ++j) {
+ if (quad_list[j]->shared_quad_state->blend_mode !=
+ SkXfermode::kSrcOver_Mode)
+ return true;
if (quad_list[j]->material != DrawQuad::RENDER_PASS)
continue;
const RenderPassDrawQuad* render_pass_quad =
RenderPassDrawQuad::MaterialCast(quad_list[j]);
if (!render_pass_quad->filters.IsEmpty() ||
!render_pass_quad->background_filters.IsEmpty())
- needs_filter_context_ = true;
+ return true;
}
}
- if (needs_filter_context_ && layer_tree_host())
- layer_tree_host()->set_needs_filter_context();
-
- SetNeedsCommit();
- // The active frame needs to be replaced and resources returned before the
- // commit is called complete.
- SetNextCommitWaitsForActivation();
+ return false;
}
-void DelegatedRendererLayer::TakeUnusedResourcesForChildCompositor(
- ReturnedResourceArray* array) {
- DCHECK(array->empty());
- array->clear();
+bool DelegatedRendererLayer::Update(ResourceUpdateQueue* queue,
+ const OcclusionTracker* occlusion) {
+ bool updated = Layer::Update(queue, occlusion);
+ if (!should_collect_new_frame_)
+ return updated;
- array->swap(unused_resources_for_child_compositor_);
-}
+ frame_data_ =
+ frame_provider_->GetFrameDataAndRefResources(this, &frame_damage_);
+ should_collect_new_frame_ = false;
-void DelegatedRendererLayer::ReceiveUnusedResources(
- const ReturnedResourceArray& unused) {
- unused_resources_for_child_compositor_.insert(
- unused_resources_for_child_compositor_.end(),
- unused.begin(),
- unused.end());
-}
+ // If any quad has a filter operation or a blend mode other than normal,
+ // then we need an offscreen context to draw this layer's content.
+ if (FrameDataRequiresFilterContext(frame_data_))
+ layer_tree_host()->set_needs_filter_context();
-// static
-void DelegatedRendererLayer::ReceiveUnusedResourcesOnImplThread(
- scoped_refptr<BlockingTaskRunner> task_runner,
- base::WeakPtr<DelegatedRendererLayer> self,
- const ReturnedResourceArray& unused) {
- task_runner->PostTask(
- FROM_HERE,
- base::Bind(
- &DelegatedRendererLayer::ReceiveUnusedResources, self, unused));
+ SetNeedsPushProperties();
+ return true;
}
} // namespace cc
diff --git a/chromium/cc/layers/delegated_renderer_layer.h b/chromium/cc/layers/delegated_renderer_layer.h
index 60e9c3c05d9..dc9dfee4705 100644
--- a/chromium/cc/layers/delegated_renderer_layer.h
+++ b/chromium/cc/layers/delegated_renderer_layer.h
@@ -5,28 +5,29 @@
#ifndef CC_LAYERS_DELEGATED_RENDERER_LAYER_H_
#define CC_LAYERS_DELEGATED_RENDERER_LAYER_H_
+#include "base/containers/hash_tables.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/synchronization/lock.h"
#include "cc/base/cc_export.h"
+#include "cc/layers/delegated_frame_provider.h"
#include "cc/layers/layer.h"
#include "cc/resources/returned_resource.h"
namespace cc {
class BlockingTaskRunner;
-class DelegatedFrameData;
-class DelegatedRendererLayerClient;
class CC_EXPORT DelegatedRendererLayer : public Layer {
public:
static scoped_refptr<DelegatedRendererLayer> Create(
- DelegatedRendererLayerClient* client);
+ const scoped_refptr<DelegatedFrameProvider>& frame_provider);
virtual scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl)
OVERRIDE;
virtual void SetLayerTreeHost(LayerTreeHost* host) OVERRIDE;
+ virtual bool Update(ResourceUpdateQueue* queue,
+ const OcclusionTracker* occlusion) OVERRIDE;
virtual void PushPropertiesTo(LayerImpl* impl) OVERRIDE;
- virtual bool DrawsContent() const OVERRIDE;
// Set the size at which the frame should be displayed, with the origin at the
// layer's origin. This must always contain at least the layer's bounds. A
@@ -34,32 +35,25 @@ class CC_EXPORT DelegatedRendererLayer : public Layer {
// in the layer's bounds.
void SetDisplaySize(gfx::Size size);
- void SetFrameData(scoped_ptr<DelegatedFrameData> frame_data);
-
- // Passes ownership of any unused resources that had been given by the child
- // compositor to the given array, so they can be given back to the child.
- void TakeUnusedResourcesForChildCompositor(ReturnedResourceArray* array);
+ // Called by the DelegatedFrameProvider when a new frame is available to be
+ // picked up.
+ void ProviderHasNewFrame();
protected:
- explicit DelegatedRendererLayer(DelegatedRendererLayerClient* client);
+ DelegatedRendererLayer(
+ const scoped_refptr<DelegatedFrameProvider>& frame_provider);
virtual ~DelegatedRendererLayer();
private:
- void ReceiveUnusedResources(const ReturnedResourceArray& unused);
- static void ReceiveUnusedResourcesOnImplThread(
- scoped_refptr<BlockingTaskRunner> task_runner,
- base::WeakPtr<DelegatedRendererLayer> self,
- const ReturnedResourceArray& unused);
-
- scoped_ptr<DelegatedFrameData> frame_data_;
- gfx::RectF damage_in_frame_;
- gfx::Size frame_size_;
- gfx::Size display_size_;
+ scoped_refptr<DelegatedFrameProvider> frame_provider_;
+
+ bool should_collect_new_frame_;
- DelegatedRendererLayerClient* client_;
- bool needs_filter_context_;
+ DelegatedFrameData* frame_data_;
+ gfx::RectF frame_damage_;
+
+ gfx::Size display_size_;
- ReturnedResourceArray unused_resources_for_child_compositor_;
scoped_refptr<BlockingTaskRunner> main_thread_runner_;
base::WeakPtrFactory<DelegatedRendererLayer> weak_ptrs_;
diff --git a/chromium/cc/layers/delegated_renderer_layer_client.h b/chromium/cc/layers/delegated_renderer_layer_client.h
deleted file mode 100644
index eb599358074..00000000000
--- a/chromium/cc/layers/delegated_renderer_layer_client.h
+++ /dev/null
@@ -1,23 +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_LAYERS_DELEGATED_RENDERER_LAYER_CLIENT_H_
-#define CC_LAYERS_DELEGATED_RENDERER_LAYER_CLIENT_H_
-
-#include "cc/base/cc_export.h"
-
-namespace cc {
-
-class CC_EXPORT DelegatedRendererLayerClient {
- public:
- // Called after the object passed in SetFrameData was handed over
- // to the DelegatedRendererLayerImpl.
- virtual void DidCommitFrameData() = 0;
-
- protected:
- virtual ~DelegatedRendererLayerClient() {}
-};
-
-} // namespace cc
-#endif // CC_LAYERS_DELEGATED_RENDERER_LAYER_CLIENT_H_
diff --git a/chromium/cc/layers/delegated_renderer_layer_impl.cc b/chromium/cc/layers/delegated_renderer_layer_impl.cc
index 34a1cd86755..07734585724 100644
--- a/chromium/cc/layers/delegated_renderer_layer_impl.cc
+++ b/chromium/cc/layers/delegated_renderer_layer_impl.cc
@@ -33,9 +33,7 @@ DelegatedRendererLayerImpl::~DelegatedRendererLayerImpl() {
ClearChildId();
}
-bool DelegatedRendererLayerImpl::HasDelegatedContent() const {
- return !render_passes_in_draw_order_.empty();
-}
+bool DelegatedRendererLayerImpl::HasDelegatedContent() const { return true; }
bool DelegatedRendererLayerImpl::HasContributingDelegatedRenderPasses() const {
// The root RenderPass for the layer is merged with its target
@@ -101,14 +99,13 @@ void DelegatedRendererLayerImpl::CreateChildIdIfNeeded(
}
void DelegatedRendererLayerImpl::SetFrameData(
- scoped_ptr<DelegatedFrameData> frame_data,
+ const DelegatedFrameData* frame_data,
gfx::RectF damage_in_frame) {
- DCHECK(frame_data);
DCHECK(child_id_) << "CreateChildIdIfNeeded must be called first.";
-
+ DCHECK(frame_data);
+ DCHECK(!frame_data->render_pass_list.empty());
// A frame with an empty root render pass is invalid.
- DCHECK(frame_data->render_pass_list.empty() ||
- !frame_data->render_pass_list.back()->output_rect.IsEmpty());
+ DCHECK(!frame_data->render_pass_list.back()->output_rect.IsEmpty());
ResourceProvider* resource_provider = layer_tree_impl()->resource_provider();
const ResourceProvider::ResourceIdMap& resource_map =
@@ -116,6 +113,9 @@ void DelegatedRendererLayerImpl::SetFrameData(
resource_provider->ReceiveFromChild(child_id_, frame_data->resource_list);
+ ScopedPtrVector<RenderPass> render_pass_list;
+ RenderPass::CopyAll(frame_data->render_pass_list, &render_pass_list);
+
bool invalid_frame = false;
ResourceProvider::ResourceIdArray resources_in_frame;
DrawQuad::ResourceIteratorCallback remap_resources_to_parent_callback =
@@ -123,8 +123,8 @@ void DelegatedRendererLayerImpl::SetFrameData(
&invalid_frame,
resource_map,
&resources_in_frame);
- for (size_t i = 0; i < frame_data->render_pass_list.size(); ++i) {
- RenderPass* pass = frame_data->render_pass_list[i];
+ for (size_t i = 0; i < render_pass_list.size(); ++i) {
+ RenderPass* pass = render_pass_list[i];
for (size_t j = 0; j < pass->quad_list.size(); ++j) {
DrawQuad* quad = pass->quad_list[j];
quad->IterateResources(remap_resources_to_parent_callback);
@@ -142,19 +142,16 @@ void DelegatedRendererLayerImpl::SetFrameData(
resource_provider->DeclareUsedResourcesFromChild(child_id_, resources_);
// Display size is already set so we can compute what the damage rect
- // will be in layer space.
- if (!frame_data->render_pass_list.empty()) {
- RenderPass* new_root_pass = frame_data->render_pass_list.back();
- gfx::RectF damage_in_layer = MathUtil::MapClippedRect(
- DelegatedFrameToLayerSpaceTransform(
- new_root_pass->output_rect.size()),
- damage_in_frame);
- set_update_rect(gfx::UnionRects(update_rect(), damage_in_layer));
- }
-
- // Save the remapped quads on the layer. This steals the quads and render
- // passes from the frame_data.
- SetRenderPasses(&frame_data->render_pass_list);
+ // will be in layer space. The damage may exceed the visible portion of
+ // 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 = MathUtil::MapClippedRect(
+ DelegatedFrameToLayerSpaceTransform(frame_size), damage_in_frame);
+ set_update_rect(gfx::IntersectRects(
+ gfx::UnionRects(update_rect(), damage_in_layer), gfx::Rect(bounds())));
+
+ SetRenderPasses(&render_pass_list);
have_render_passes_to_push_ = true;
}
@@ -184,7 +181,6 @@ void DelegatedRendererLayerImpl::SetRenderPasses(
}
void DelegatedRendererLayerImpl::ClearRenderPasses() {
- // TODO(danakj): Release the resources back to the nested compositor.
render_passes_index_by_id_.clear();
render_passes_in_draw_order_.clear();
}
@@ -243,6 +239,13 @@ void DelegatedRendererLayerImpl::AppendContributingRenderPasses(
RenderPassSink* render_pass_sink) {
DCHECK(HasContributingDelegatedRenderPasses());
+ const RenderPass* root_delegated_render_pass =
+ render_passes_in_draw_order_.back();
+ gfx::Size frame_size = root_delegated_render_pass->output_rect.size();
+ gfx::Transform delegated_frame_to_root_transform =
+ screen_space_transform() *
+ DelegatedFrameToLayerSpaceTransform(frame_size);
+
for (size_t i = 0; i < render_passes_in_draw_order_.size() - 1; ++i) {
RenderPass::Id output_render_pass_id(-1, -1);
bool present =
@@ -254,8 +257,11 @@ void DelegatedRendererLayerImpl::AppendContributingRenderPasses(
<< render_passes_in_draw_order_[i]->id.index;
DCHECK_GT(output_render_pass_id.index, 0);
- render_pass_sink->AppendRenderPass(
- render_passes_in_draw_order_[i]->Copy(output_render_pass_id));
+ scoped_ptr<RenderPass> copy_pass =
+ render_passes_in_draw_order_[i]->Copy(output_render_pass_id);
+ copy_pass->transform_to_root_target.ConcatTransform(
+ delegated_frame_to_root_transform);
+ render_pass_sink->AppendRenderPass(copy_pass.Pass());
}
}
@@ -271,6 +277,7 @@ void DelegatedRendererLayerImpl::AppendQuads(
AppendQuadsData* append_quads_data) {
AppendRainbowDebugBorder(quad_sink, append_quads_data);
+ // This list will be empty after a lost context until a new frame arrives.
if (render_passes_in_draw_order_.empty())
return;
diff --git a/chromium/cc/layers/delegated_renderer_layer_impl.h b/chromium/cc/layers/delegated_renderer_layer_impl.h
index 7d774f1c357..358b7b9acf4 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 {
// inform when resources are no longer in use.
void CreateChildIdIfNeeded(const ReturnCallback& return_callback);
- void SetFrameData(scoped_ptr<DelegatedFrameData> frame_data,
+ void SetFrameData(const DelegatedFrameData* frame_data,
gfx::RectF damage_in_frame);
void SetDisplaySize(gfx::Size size);
diff --git a/chromium/cc/layers/delegated_renderer_layer_impl_unittest.cc b/chromium/cc/layers/delegated_renderer_layer_impl_unittest.cc
index a641e00eaf0..8cb0f3e376c 100644
--- a/chromium/cc/layers/delegated_renderer_layer_impl_unittest.cc
+++ b/chromium/cc/layers/delegated_renderer_layer_impl_unittest.cc
@@ -5,7 +5,6 @@
#include "cc/layers/delegated_renderer_layer_impl.h"
#include "cc/base/scoped_ptr_vector.h"
-#include "cc/debug/test_web_graphics_context_3d.h"
#include "cc/layers/append_quads_data.h"
#include "cc/layers/quad_sink.h"
#include "cc/layers/solid_color_layer_impl.h"
@@ -21,10 +20,12 @@
#include "cc/test/mock_quad_culler.h"
#include "cc/test/render_pass_test_common.h"
#include "cc/test/render_pass_test_utils.h"
+#include "cc/test/test_web_graphics_context_3d.h"
#include "cc/trees/layer_tree_host_impl.h"
#include "cc/trees/layer_tree_impl.h"
#include "cc/trees/single_thread_proxy.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/frame_time.h"
#include "ui/gfx/transform.h"
namespace cc {
@@ -88,24 +89,21 @@ class DelegatedRendererLayerImplTestSimple
delegated_renderer_layer->SetTransform(transform);
ScopedPtrVector<RenderPass> delegated_render_passes;
- TestRenderPass* pass1 = AddRenderPass(
- &delegated_render_passes,
- RenderPass::Id(9, 6),
- gfx::Rect(6, 6, 6, 6),
- gfx::Transform());
+ TestRenderPass* pass1 = AddRenderPass(&delegated_render_passes,
+ RenderPass::Id(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,
- RenderPass::Id(9, 7),
- gfx::Rect(7, 7, 7, 7),
- gfx::Transform());
+ TestRenderPass* pass2 = AddRenderPass(&delegated_render_passes,
+ RenderPass::Id(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,
- RenderPass::Id(9, 8),
- gfx::Rect(0, 0, 8, 8),
- gfx::Transform());
+ TestRenderPass* pass3 = AddRenderPass(&delegated_render_passes,
+ RenderPass::Id(9, 8),
+ gfx::Rect(0, 0, 8, 8),
+ gfx::Transform(1, 0, 0, 1, 9, 10));
AddRenderPassQuad(pass3, pass2);
delegated_renderer_layer->SetFrameDataForRenderPasses(
&delegated_render_passes);
@@ -165,7 +163,7 @@ TEST_F(DelegatedRendererLayerImplTestSimple, AddsContributingRenderPasses) {
EXPECT_EQ(gfx::Rect(7, 7, 7, 7).ToString(),
frame.render_passes[2]->output_rect.ToString());
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
@@ -201,7 +199,7 @@ TEST_F(DelegatedRendererLayerImplTestSimple,
EXPECT_EQ(gfx::Rect(0, 0, 6, 6).ToString(),
frame.render_passes[1]->quad_list[0]->rect.ToString());
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
@@ -228,7 +226,7 @@ TEST_F(DelegatedRendererLayerImplTestSimple, AddsQuadsToTargetRenderPass) {
EXPECT_EQ(gfx::Rect(0, 0, 15, 15).ToString(),
frame.render_passes[3]->quad_list[1]->rect.ToString());
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
@@ -262,6 +260,42 @@ TEST_F(DelegatedRendererLayerImplTestSimple,
EXPECT_TRANSFORMATION_MATRIX_EQ(
gfx::Transform(), frame.render_passes[1]->quad_list[0]->quadTransform());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
+ host_impl_->DidDrawAllLayers(frame);
+}
+
+TEST_F(DelegatedRendererLayerImplTestSimple, RenderPassTransformIsModified) {
+ LayerTreeHostImpl::FrameData frame;
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
+
+ // The delegated layer has a surface between it and the root.
+ EXPECT_TRUE(delegated_renderer_layer_->render_target()->parent());
+
+ // Each non-DelegatedRendererLayer added one RenderPass. The
+ // DelegatedRendererLayer added two contributing passes.
+ ASSERT_EQ(5u, frame.render_passes.size());
+
+ // The DelegatedRendererLayer is at position 9,9 compared to the root, so all
+ // render pass' transforms to the root should be shifted by this amount.
+ // The DelegatedRendererLayer has a size of 10x10, but the root delegated
+ // RenderPass has a size of 8x8, so any render passes should be scaled by
+ // 10/8.
+ gfx::Transform transform;
+ transform.Translate(9.0, 9.0);
+ transform.Scale(10.0 / 8.0, 10.0 / 8.0);
+
+ // The first contributing surface has a translation of 5, 6.
+ gfx::Transform five_six(1, 0, 0, 1, 5, 6);
+
+ // The second contributing surface has a translation of 7, 8.
+ gfx::Transform seven_eight(1, 0, 0, 1, 7, 8);
+
+ EXPECT_TRANSFORMATION_MATRIX_EQ(
+ transform * five_six, frame.render_passes[1]->transform_to_root_target);
+ EXPECT_TRANSFORMATION_MATRIX_EQ(
+ transform * seven_eight,
+ frame.render_passes[2]->transform_to_root_target);
+
host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
host_impl_->DidDrawAllLayers(frame);
}
@@ -274,7 +308,7 @@ TEST_F(DelegatedRendererLayerImplTestSimple, DoesNotOwnARenderSurface) {
// has no need to be a RenderSurface for the quads it carries.
EXPECT_FALSE(delegated_renderer_layer_->render_surface());
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
@@ -289,7 +323,7 @@ TEST_F(DelegatedRendererLayerImplTestSimple, DoesOwnARenderSurfaceForOpacity) {
// render surface.
EXPECT_TRUE(delegated_renderer_layer_->render_surface());
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
@@ -307,7 +341,7 @@ TEST_F(DelegatedRendererLayerImplTestSimple,
// render surface.
EXPECT_TRUE(delegated_renderer_layer_->render_surface());
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
@@ -354,7 +388,7 @@ TEST_F(DelegatedRendererLayerImplTestOwnSurface, AddsRenderPasses) {
EXPECT_EQ(gfx::Rect(7, 7, 7, 7).ToString(),
frame.render_passes[2]->output_rect.ToString());
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
@@ -391,7 +425,7 @@ TEST_F(DelegatedRendererLayerImplTestOwnSurface,
EXPECT_EQ(gfx::Rect(0, 0, 6, 6).ToString(),
frame.render_passes[1]->quad_list[0]->rect.ToString());
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
@@ -416,7 +450,7 @@ TEST_F(DelegatedRendererLayerImplTestOwnSurface, AddsQuadsToTargetRenderPass) {
EXPECT_EQ(gfx::Rect(7, 7, 7, 7).ToString(),
frame.render_passes[3]->quad_list[0]->rect.ToString());
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
@@ -448,7 +482,7 @@ TEST_F(DelegatedRendererLayerImplTestOwnSurface,
EXPECT_TRANSFORMATION_MATRIX_EQ(
gfx::Transform(), frame.render_passes[1]->quad_list[0]->quadTransform());
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
@@ -480,7 +514,7 @@ class DelegatedRendererLayerImplTestTransform
gfx::Size child_pass_content_bounds(7, 7);
gfx::Rect child_pass_rect(20, 20, 7, 7);
gfx::Transform child_pass_transform;
- child_pass_transform.Scale(0.8, 0.8);
+ child_pass_transform.Scale(0.8f, 0.8f);
child_pass_transform.Translate(9.0, 9.0);
gfx::Rect child_pass_clip_rect(21, 21, 3, 3);
bool child_pass_clipped = false;
@@ -495,13 +529,13 @@ class DelegatedRendererLayerImplTestTransform
AppendQuadsData data(pass->id);
SharedQuadState* shared_quad_state = quad_sink.UseSharedQuadState(
SharedQuadState::Create());
- shared_quad_state->SetAll(
- child_pass_transform,
- child_pass_content_bounds,
- child_pass_rect,
- child_pass_clip_rect,
- child_pass_clipped,
- 1.f);
+ shared_quad_state->SetAll(child_pass_transform,
+ child_pass_content_bounds,
+ child_pass_rect,
+ child_pass_clip_rect,
+ child_pass_clipped,
+ 1.f,
+ SkXfermode::kSrcOver_Mode);
scoped_ptr<SolidColorDrawQuad> color_quad;
color_quad = SolidColorDrawQuad::Create();
@@ -530,13 +564,13 @@ class DelegatedRendererLayerImplTestTransform
AppendQuadsData data(pass->id);
SharedQuadState* shared_quad_state =
quad_sink.UseSharedQuadState(SharedQuadState::Create());
- shared_quad_state->SetAll(
- root_pass_transform,
- root_pass_content_bounds,
- root_pass_rect,
- root_pass_clip_rect,
- root_pass_clipped,
- 1.f);
+ shared_quad_state->SetAll(root_pass_transform,
+ root_pass_content_bounds,
+ root_pass_rect,
+ root_pass_clip_rect,
+ root_pass_clipped,
+ 1.f,
+ SkXfermode::kSrcOver_Mode);
scoped_ptr<RenderPassDrawQuad> render_pass_quad =
RenderPassDrawQuad::Create();
@@ -549,7 +583,6 @@ class DelegatedRendererLayerImplTestTransform
child_pass_rect, // contents_changed_since_last_frame
gfx::RectF(), // mask_uv_rect
FilterOperations(), // filters
- skia::RefPtr<SkImageFilter>(), // filter
FilterOperations()); // background_filters
quad_sink.Append(render_pass_quad.PassAs<DrawQuad>(), &data);
@@ -677,13 +710,13 @@ TEST_F(DelegatedRendererLayerImplTestTransform, QuadsUnclipped_NoSurface) {
contrib_delegated_shared_quad_state->clip_rect.ToString());
EXPECT_FALSE(contrib_delegated_shared_quad_state->is_clipped);
expected.MakeIdentity();
- expected.Scale(0.8, 0.8);
+ expected.Scale(0.8f, 0.8f);
expected.Translate(9.0, 9.0);
EXPECT_TRANSFORMATION_MATRIX_EQ(
expected,
contrib_delegated_shared_quad_state->content_to_target_transform);
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
@@ -740,13 +773,13 @@ TEST_F(DelegatedRendererLayerImplTestTransform, QuadsClipped_NoSurface) {
contrib_delegated_shared_quad_state->clip_rect.ToString());
EXPECT_FALSE(contrib_delegated_shared_quad_state->is_clipped);
expected.MakeIdentity();
- expected.Scale(0.8, 0.8);
+ expected.Scale(0.8f, 0.8f);
expected.Translate(9.0, 9.0);
EXPECT_TRANSFORMATION_MATRIX_EQ(
expected,
contrib_delegated_shared_quad_state->content_to_target_transform);
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
@@ -796,13 +829,13 @@ TEST_F(DelegatedRendererLayerImplTestTransform, QuadsUnclipped_Surface) {
contrib_delegated_shared_quad_state->clip_rect.ToString());
EXPECT_FALSE(contrib_delegated_shared_quad_state->is_clipped);
expected.MakeIdentity();
- expected.Scale(0.8, 0.8);
+ expected.Scale(0.8f, 0.8f);
expected.Translate(9.0, 9.0);
EXPECT_TRANSFORMATION_MATRIX_EQ(
expected,
contrib_delegated_shared_quad_state->content_to_target_transform);
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
@@ -851,13 +884,13 @@ TEST_F(DelegatedRendererLayerImplTestTransform, QuadsClipped_Surface) {
contrib_delegated_shared_quad_state->clip_rect.ToString());
EXPECT_FALSE(contrib_delegated_shared_quad_state->is_clipped);
expected.MakeIdentity();
- expected.Scale(0.8, 0.8);
+ expected.Scale(0.8f, 0.8f);
expected.Translate(9.0, 9.0);
EXPECT_TRANSFORMATION_MATRIX_EQ(
expected,
contrib_delegated_shared_quad_state->content_to_target_transform);
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
@@ -900,13 +933,13 @@ class DelegatedRendererLayerImplTestClip
AppendQuadsData data(pass->id);
SharedQuadState* shared_quad_state =
quad_sink.UseSharedQuadState(SharedQuadState::Create());
- shared_quad_state->SetAll(
- child_pass_transform,
- child_pass_content_bounds,
- child_pass_rect,
- child_pass_clip_rect,
- child_pass_clipped,
- 1.f);
+ shared_quad_state->SetAll(child_pass_transform,
+ child_pass_content_bounds,
+ child_pass_rect,
+ child_pass_clip_rect,
+ child_pass_clipped,
+ 1.f,
+ SkXfermode::kSrcOver_Mode);
scoped_ptr<SolidColorDrawQuad> color_quad;
color_quad = SolidColorDrawQuad::Create();
@@ -938,7 +971,8 @@ class DelegatedRendererLayerImplTestClip
root_pass_rect,
root_pass_clip_rect,
root_pass_clipped,
- 1.f);
+ 1.f,
+ SkXfermode::kSrcOver_Mode);
scoped_ptr<RenderPassDrawQuad> render_pass_quad =
RenderPassDrawQuad::Create();
@@ -951,7 +985,6 @@ class DelegatedRendererLayerImplTestClip
child_pass_rect, // contents_changed_since_last_frame
gfx::RectF(), // mask_uv_rect
FilterOperations(), // filters
- skia::RefPtr<SkImageFilter>(), // filter
FilterOperations()); // background_filters
quad_sink.Append(render_pass_quad.PassAs<DrawQuad>(), &data);
@@ -1034,7 +1067,7 @@ TEST_F(DelegatedRendererLayerImplTestClip,
// Quads are clipped to the delegated renderer layer.
EXPECT_TRUE(root_delegated_shared_quad_state->is_clipped);
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
@@ -1063,7 +1096,7 @@ TEST_F(DelegatedRendererLayerImplTestClip,
// Quads came with a clip rect.
EXPECT_TRUE(root_delegated_shared_quad_state->is_clipped);
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
@@ -1093,7 +1126,7 @@ TEST_F(DelegatedRendererLayerImplTestClip,
// Quads are clipped to the delegated renderer layer.
EXPECT_TRUE(root_delegated_shared_quad_state->is_clipped);
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
@@ -1122,7 +1155,7 @@ TEST_F(DelegatedRendererLayerImplTestClip,
// Quads came with a clip rect.
EXPECT_TRUE(root_delegated_shared_quad_state->is_clipped);
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
@@ -1151,7 +1184,7 @@ TEST_F(DelegatedRendererLayerImplTestClip,
// clip rect is ignored, and they are not set as clipped.
EXPECT_FALSE(root_delegated_shared_quad_state->is_clipped);
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
@@ -1181,7 +1214,7 @@ TEST_F(DelegatedRendererLayerImplTestClip,
// Quads came with a clip rect.
EXPECT_TRUE(root_delegated_shared_quad_state->is_clipped);
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
@@ -1210,7 +1243,7 @@ TEST_F(DelegatedRendererLayerImplTestClip,
// clip rect is ignored, and they are not set as clipped.
EXPECT_FALSE(root_delegated_shared_quad_state->is_clipped);
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
@@ -1241,7 +1274,7 @@ TEST_F(DelegatedRendererLayerImplTestClip, QuadsClipped_LayerClipped_Surface) {
// Quads came with a clip rect.
EXPECT_TRUE(root_delegated_shared_quad_state->is_clipped);
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
@@ -1294,7 +1327,7 @@ TEST_F(DelegatedRendererLayerImplTest, InvalidRenderPassDrawQuad) {
EXPECT_EQ(DrawQuad::SOLID_COLOR,
frame.render_passes[0]->quad_list[0]->material);
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
diff --git a/chromium/cc/layers/draw_properties.h b/chromium/cc/layers/draw_properties.h
index 181d900f267..5fd42a49e94 100644
--- a/chromium/cc/layers/draw_properties.h
+++ b/chromium/cc/layers/draw_properties.h
@@ -13,7 +13,7 @@ namespace cc {
// Container for properties that layers need to compute before they can be
// drawn.
-template <typename LayerType, typename RenderSurfaceType>
+template <typename LayerType>
struct CC_EXPORT DrawProperties {
DrawProperties()
: opacity(0.f),
@@ -28,9 +28,13 @@ struct CC_EXPORT DrawProperties {
contents_scale_y(1.f),
num_descendants_that_draw_content(0),
num_unclipped_descendants(0),
- descendants_can_clip_selves(false),
- can_draw_directly_to_backbuffer(false),
- layer_or_descendant_has_copy_request(false) {}
+ layer_or_descendant_has_copy_request(false),
+ has_child_with_a_scroll_parent(false),
+ sorted_for_recursion(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) {}
// Transforms objects from content space to target surface space, where
// this layer would be drawn.
@@ -65,7 +69,7 @@ struct CC_EXPORT DrawProperties {
LayerType* render_target;
// The surface that this layer and its subtree would contribute to.
- scoped_ptr<RenderSurfaceType> render_surface;
+ scoped_ptr<typename LayerType::RenderSurfaceType> render_surface;
// This rect is in the layer's content space.
gfx::Rect visible_content_rect;
@@ -93,15 +97,27 @@ struct CC_EXPORT DrawProperties {
// does not include our clip children because they are clipped by us.
int num_unclipped_descendants;
- // If true, every descendant in the sub-tree can clip itself without the
- // need to use hardware sissoring or a new render target.
- bool descendants_can_clip_selves;
-
- bool can_draw_directly_to_backbuffer;
-
// If true, the layer or some layer in its sub-tree has a CopyOutputRequest
// present on it.
bool layer_or_descendant_has_copy_request;
+
+ // 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;
+
+ // This is true if the order (wrt to its siblings in the tree) in which the
+ // layer will be visited while computing draw properties has been determined.
+ bool sorted_for_recursion;
+
+ // 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;
};
} // namespace cc
diff --git a/chromium/cc/layers/heads_up_display_layer_impl.cc b/chromium/cc/layers/heads_up_display_layer_impl.cc
index c1fa9f37dbc..da4784074cf 100644
--- a/chromium/cc/layers/heads_up_display_layer_impl.cc
+++ b/chromium/cc/layers/heads_up_display_layer_impl.cc
@@ -12,6 +12,7 @@
#include "cc/debug/debug_rect_history.h"
#include "cc/debug/frame_rate_counter.h"
#include "cc/debug/paint_time_counter.h"
+#include "cc/debug/traced_value.h"
#include "cc/layers/quad_sink.h"
#include "cc/output/renderer.h"
#include "cc/quads/texture_draw_quad.h"
@@ -85,13 +86,15 @@ bool HeadsUpDisplayLayerImpl::WillDraw(DrawMode draw_mode,
return false;
if (!hud_resource_)
- hud_resource_ = ScopedResource::create(resource_provider);
+ hud_resource_ = ScopedResource::Create(resource_provider);
// TODO(danakj): The HUD could swap between two textures instead of creating a
// texture every frame in ubercompositor.
if (hud_resource_->size() != content_bounds() ||
- resource_provider->InUseByConsumer(hud_resource_->id()))
+ (hud_resource_->id() &&
+ resource_provider->InUseByConsumer(hud_resource_->id()))) {
hud_resource_->Free();
+ }
if (!hud_resource_->id()) {
hud_resource_->Allocate(content_bounds(),
@@ -132,8 +135,9 @@ void HeadsUpDisplayLayerImpl::AppendQuads(QuadSink* quad_sink,
}
void HeadsUpDisplayLayerImpl::UpdateHudTexture(
+ DrawMode draw_mode,
ResourceProvider* resource_provider) {
- if (!hud_resource_->id())
+ if (draw_mode == DRAW_MODE_RESOURCELESS_SOFTWARE || !hud_resource_->id())
return;
SkISize canvas_size;
@@ -144,6 +148,7 @@ void HeadsUpDisplayLayerImpl::UpdateHudTexture(
if (canvas_size.width() != content_bounds().width() ||
canvas_size.width() != content_bounds().height() || !hud_canvas_) {
+ TRACE_EVENT0("cc", "ResizeHudCanvas");
bool opaque = false;
hud_canvas_ = make_scoped_ptr(skia::CreateBitmapCanvas(
content_bounds().width(), content_bounds().height(), opaque));
@@ -151,14 +156,18 @@ void HeadsUpDisplayLayerImpl::UpdateHudTexture(
UpdateHudContents();
- hud_canvas_->clear(SkColorSetARGB(0, 0, 0, 0));
- hud_canvas_->save();
- hud_canvas_->scale(contents_scale_x(), contents_scale_y());
+ {
+ TRACE_EVENT0("cc", "DrawHudContents");
+ hud_canvas_->clear(SkColorSetARGB(0, 0, 0, 0));
+ hud_canvas_->save();
+ hud_canvas_->scale(contents_scale_x(), contents_scale_y());
- DrawHudContents(hud_canvas_.get());
+ DrawHudContents(hud_canvas_.get());
- hud_canvas_->restore();
+ hud_canvas_->restore();
+ }
+ TRACE_EVENT0("cc", "UploadHudTexture");
const SkBitmap* bitmap = &hud_canvas_->getDevice()->accessBitmap(false);
SkAutoLockPixels locker(*bitmap);
@@ -643,6 +652,12 @@ void HeadsUpDisplayLayerImpl::DrawDebugRects(
stroke_width = DebugColors::NonFastScrollableRectBorderWidth();
label_text = "repaints on scroll";
break;
+ case ANIMATION_BOUNDS_RECT_TYPE:
+ stroke_color = DebugColors::LayerAnimationBoundsBorderColor();
+ fill_color = DebugColors::LayerAnimationBoundsFillColor();
+ stroke_width = DebugColors::LayerAnimationBoundsBorderWidth();
+ label_text = "animation bounds";
+ break;
}
gfx::RectF debug_layer_rect = gfx::ScaleRect(debug_rects[i].rect,
diff --git a/chromium/cc/layers/heads_up_display_layer_impl.h b/chromium/cc/layers/heads_up_display_layer_impl.h
index 32bf77e143d..fa38f15eafe 100644
--- a/chromium/cc/layers/heads_up_display_layer_impl.h
+++ b/chromium/cc/layers/heads_up_display_layer_impl.h
@@ -40,7 +40,8 @@ class CC_EXPORT HeadsUpDisplayLayerImpl : public LayerImpl {
ResourceProvider* resource_provider) OVERRIDE;
virtual void AppendQuads(QuadSink* quad_sink,
AppendQuadsData* append_quads_data) OVERRIDE;
- void UpdateHudTexture(ResourceProvider* resource_provider);
+ void UpdateHudTexture(DrawMode draw_mode,
+ ResourceProvider* resource_provider);
virtual void DidLoseOutputSurface() OVERRIDE;
diff --git a/chromium/cc/layers/heads_up_display_layer_impl_unittest.cc b/chromium/cc/layers/heads_up_display_layer_impl_unittest.cc
new file mode 100644
index 00000000000..5afc01956d8
--- /dev/null
+++ b/chromium/cc/layers/heads_up_display_layer_impl_unittest.cc
@@ -0,0 +1,55 @@
+// 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/append_quads_data.h"
+#include "cc/layers/heads_up_display_layer_impl.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/mock_quad_culler.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace cc {
+namespace {
+
+void CheckDrawLayer(HeadsUpDisplayLayerImpl* layer,
+ ResourceProvider* resource_provider,
+ DrawMode draw_mode) {
+ MockQuadCuller quad_culler;
+ AppendQuadsData data;
+ bool will_draw = layer->WillDraw(draw_mode, resource_provider);
+ if (will_draw)
+ layer->AppendQuads(&quad_culler, &data);
+ layer->UpdateHudTexture(draw_mode, resource_provider);
+ if (will_draw)
+ layer->DidDraw(resource_provider);
+
+ size_t expected_quad_list_size = will_draw ? 1 : 0;
+ EXPECT_EQ(expected_quad_list_size, quad_culler.quad_list().size());
+}
+
+TEST(HeadsUpDisplayLayerImplTest, ResourcelessSoftwareDrawAfterResourceLoss) {
+ FakeImplProxy proxy;
+ FakeLayerTreeHostImpl host_impl(&proxy);
+ host_impl.CreatePendingTree();
+ host_impl.InitializeRenderer(CreateFakeOutputSurface());
+ scoped_ptr<HeadsUpDisplayLayerImpl> layer =
+ HeadsUpDisplayLayerImpl::Create(host_impl.pending_tree(), 1);
+ layer->SetContentBounds(gfx::Size(100, 100));
+
+ // Check regular hardware draw is ok.
+ CheckDrawLayer(
+ layer.get(), host_impl.resource_provider(), DRAW_MODE_HARDWARE);
+
+ // Simulate a resource loss on transitioning to resourceless software mode.
+ layer->DidLoseOutputSurface();
+
+ // Should skip resourceless software draw and not crash in UpdateHudTexture.
+ CheckDrawLayer(layer.get(),
+ host_impl.resource_provider(),
+ DRAW_MODE_RESOURCELESS_SOFTWARE);
+}
+
+} // namespace
+} // namespace cc
diff --git a/chromium/cc/layers/image_layer.cc b/chromium/cc/layers/image_layer.cc
index bbf1aa82e34..2f90bfc50a8 100644
--- a/chromium/cc/layers/image_layer.cc
+++ b/chromium/cc/layers/image_layer.cc
@@ -80,6 +80,12 @@ bool ImageLayer::DrawsContent() const {
return !bitmap_.isNull() && TiledLayer::DrawsContent();
}
+void ImageLayer::OnOutputSurfaceCreated() {
+ SetTextureFormat(
+ layer_tree_host()->GetRendererCapabilities().best_texture_format);
+ TiledLayer::OnOutputSurfaceCreated();
+}
+
float ImageLayer::ImageContentsScaleX() const {
if (bounds().IsEmpty() || bitmap_.width() == 0)
return 1;
diff --git a/chromium/cc/layers/image_layer.h b/chromium/cc/layers/image_layer.h
index ae8383a22c3..6cd82755bfc 100644
--- a/chromium/cc/layers/image_layer.h
+++ b/chromium/cc/layers/image_layer.h
@@ -31,6 +31,7 @@ class CC_EXPORT ImageLayer : public TiledLayer {
float* contents_scale_x,
float* contents_scale_y,
gfx::Size* content_bounds) OVERRIDE;
+ virtual void OnOutputSurfaceCreated() OVERRIDE;
void SetBitmap(const SkBitmap& image);
diff --git a/chromium/cc/layers/io_surface_layer_impl.cc b/chromium/cc/layers/io_surface_layer_impl.cc
index e8c627be08b..a70006a69c9 100644
--- a/chromium/cc/layers/io_surface_layer_impl.cc
+++ b/chromium/cc/layers/io_surface_layer_impl.cc
@@ -11,7 +11,7 @@
#include "cc/quads/io_surface_draw_quad.h"
#include "cc/trees/layer_tree_impl.h"
#include "gpu/GLES2/gl2extchromium.h"
-#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/khronos/GLES2/gl2ext.h"
@@ -21,7 +21,8 @@ IOSurfaceLayerImpl::IOSurfaceLayerImpl(LayerTreeImpl* tree_impl, int id)
: LayerImpl(tree_impl, id),
io_surface_id_(0),
io_surface_changed_(false),
- io_surface_texture_id_(0) {}
+ io_surface_texture_id_(0),
+ io_surface_resource_id_(0) {}
IOSurfaceLayerImpl::~IOSurfaceLayerImpl() {
if (!io_surface_texture_id_)
@@ -43,7 +44,7 @@ void IOSurfaceLayerImpl::DestroyTexture() {
layer_tree_impl()->output_surface()->context_provider().get();
// TODO(skaslev): Implement this path for software compositing.
if (context_provider)
- context_provider->Context3d()->deleteTexture(io_surface_texture_id_);
+ context_provider->ContextGL()->DeleteTextures(1, &io_surface_texture_id_);
io_surface_texture_id_ = 0;
}
}
@@ -74,25 +75,23 @@ bool IOSurfaceLayerImpl::WillDraw(DrawMode draw_mode,
return false;
}
- WebKit::WebGraphicsContext3D* context3d = context_provider->Context3d();
+ gpu::gles2::GLES2Interface* gl = context_provider->ContextGL();
// TODO(ernstm): Do this in a way that we can track memory usage.
if (!io_surface_texture_id_) {
- io_surface_texture_id_ = context3d->createTexture();
+ gl->GenTextures(1, &io_surface_texture_id_);
io_surface_resource_id_ =
resource_provider->CreateResourceFromExternalTexture(
GL_TEXTURE_RECTANGLE_ARB,
io_surface_texture_id_);
}
- GLC(context3d,
- context3d->bindTexture(GL_TEXTURE_RECTANGLE_ARB,
- io_surface_texture_id_));
- context3d->texImageIOSurface2DCHROMIUM(GL_TEXTURE_RECTANGLE_ARB,
- io_surface_size_.width(),
- io_surface_size_.height(),
- io_surface_id_,
- 0);
+ GLC(gl, gl->BindTexture(GL_TEXTURE_RECTANGLE_ARB, io_surface_texture_id_));
+ gl->TexImageIOSurface2DCHROMIUM(GL_TEXTURE_RECTANGLE_ARB,
+ io_surface_size_.width(),
+ io_surface_size_.height(),
+ io_surface_id_,
+ 0);
// Do not check for error conditions. texImageIOSurface2DCHROMIUM() is
// supposed to hold on to the last good IOSurface if the new one is already
// closed. This is only a possibility during live resizing of plugins.
diff --git a/chromium/cc/layers/layer.cc b/chromium/cc/layers/layer.cc
index 86887a6ad2c..f7682fd912f 100644
--- a/chromium/cc/layers/layer.cc
+++ b/chromium/cc/layers/layer.cc
@@ -12,6 +12,7 @@
#include "base/single_thread_task_runner.h"
#include "cc/animation/animation.h"
#include "cc/animation/animation_events.h"
+#include "cc/animation/keyframed_animation_curve.h"
#include "cc/animation/layer_animation_controller.h"
#include "cc/layers/layer_client.h"
#include "cc/layers/layer_impl.h"
@@ -41,11 +42,9 @@ Layer::Layer()
scrollable_(false),
should_scroll_on_main_thread_(false),
have_wheel_event_handlers_(false),
- anchor_point_(0.5f, 0.5f),
- background_color_(0),
- compositing_reasons_(kCompositingReasonUnknown),
- opacity_(1.f),
- anchor_point_z_(0.f),
+ user_scrollable_horizontal_(true),
+ user_scrollable_vertical_(true),
+ is_root_for_isolated_group_(false),
is_container_for_fixed_position_layers_(false),
is_drawable_(false),
hide_layer_and_subtree_(false),
@@ -56,6 +55,12 @@ Layer::Layer()
use_parent_backface_visibility_(false),
draw_checkerboard_for_missing_tiles_(false),
force_render_surface_(false),
+ anchor_point_(0.5f, 0.5f),
+ background_color_(0),
+ compositing_reasons_(kCompositingReasonUnknown),
+ opacity_(1.f),
+ blend_mode_(SkXfermode::kSrcOver_Mode),
+ anchor_point_z_(0.f),
scroll_parent_(NULL),
clip_parent_(NULL),
replica_layer_(NULL),
@@ -68,6 +73,7 @@ Layer::Layer()
layer_animation_controller_ = LayerAnimationController::Create(layer_id_);
layer_animation_controller_->AddValueObserver(this);
+ layer_animation_controller_->set_value_provider(this);
}
Layer::~Layer() {
@@ -79,6 +85,7 @@ Layer::~Layer() {
DCHECK(!layer_tree_host());
layer_animation_controller_->RemoveValueObserver(this);
+ layer_animation_controller_->remove_value_provider(this);
// Remove the parent reference from all children and dependents.
RemoveAllChildren();
@@ -123,9 +130,7 @@ void Layer::SetLayerTreeHost(LayerTreeHost* host) {
if (host && layer_animation_controller_->has_any_animation())
host->SetNeedsCommit();
- if (host &&
- (!filters_.IsEmpty() || !background_filters_.IsEmpty() || filter_))
- layer_tree_host_->set_needs_filter_context();
+ SetNeedsFilterContextIfNeeded();
}
void Layer::SetNeedsUpdate() {
@@ -159,6 +164,15 @@ void Layer::SetNextCommitWaitsForActivation() {
layer_tree_host_->SetNextCommitWaitsForActivation();
}
+void Layer::SetNeedsFilterContextIfNeeded() {
+ if (!layer_tree_host_)
+ return;
+
+ if (!filters_.IsEmpty() || !background_filters_.IsEmpty() ||
+ !uses_default_blend_mode())
+ layer_tree_host_->set_needs_filter_context();
+}
+
void Layer::SetNeedsPushProperties() {
if (needs_push_properties_)
return;
@@ -207,10 +221,6 @@ skia::RefPtr<SkPicture> Layer::GetPicture() const {
return skia::RefPtr<SkPicture>();
}
-bool Layer::CanClipSelf() const {
- return false;
-}
-
void Layer::SetParent(Layer* layer) {
DCHECK(!layer || !layer->HasAncestor(this));
@@ -472,22 +482,13 @@ void Layer::SetFilters(const FilterOperations& filters) {
DCHECK(IsPropertyChangeAllowed());
if (filters_ == filters)
return;
- DCHECK(!filter_);
filters_ = filters;
SetNeedsCommit();
- if (!filters.IsEmpty() && layer_tree_host_)
- layer_tree_host_->set_needs_filter_context();
+ SetNeedsFilterContextIfNeeded();
}
-void Layer::SetFilter(const skia::RefPtr<SkImageFilter>& filter) {
- DCHECK(IsPropertyChangeAllowed());
- if (filter_.get() == filter.get())
- return;
- DCHECK(filters_.IsEmpty());
- filter_ = filter;
- SetNeedsCommit();
- if (filter && layer_tree_host_)
- layer_tree_host_->set_needs_filter_context();
+bool Layer::FilterIsAnimating() const {
+ return layer_animation_controller_->IsAnimatingProperty(Animation::Filter);
}
void Layer::SetBackgroundFilters(const FilterOperations& filters) {
@@ -496,8 +497,7 @@ void Layer::SetBackgroundFilters(const FilterOperations& filters) {
return;
background_filters_ = filters;
SetNeedsCommit();
- if (!filters.IsEmpty() && layer_tree_host_)
- layer_tree_host_->set_needs_filter_context();
+ SetNeedsFilterContextIfNeeded();
}
void Layer::SetOpacity(float opacity) {
@@ -516,6 +516,64 @@ bool Layer::OpacityCanAnimateOnImplThread() const {
return false;
}
+void Layer::SetBlendMode(SkXfermode::Mode blend_mode) {
+ DCHECK(IsPropertyChangeAllowed());
+ if (blend_mode_ == blend_mode)
+ return;
+
+ // Allowing only blend modes that are defined in the CSS Compositing standard:
+ // http://dev.w3.org/fxtf/compositing-1/#blending
+ switch (blend_mode) {
+ case SkXfermode::kSrcOver_Mode:
+ case SkXfermode::kScreen_Mode:
+ case SkXfermode::kOverlay_Mode:
+ case SkXfermode::kDarken_Mode:
+ case SkXfermode::kLighten_Mode:
+ case SkXfermode::kColorDodge_Mode:
+ case SkXfermode::kColorBurn_Mode:
+ case SkXfermode::kHardLight_Mode:
+ case SkXfermode::kSoftLight_Mode:
+ case SkXfermode::kDifference_Mode:
+ case SkXfermode::kExclusion_Mode:
+ case SkXfermode::kMultiply_Mode:
+ case SkXfermode::kHue_Mode:
+ case SkXfermode::kSaturation_Mode:
+ case SkXfermode::kColor_Mode:
+ case SkXfermode::kLuminosity_Mode:
+ // supported blend modes
+ break;
+ case SkXfermode::kClear_Mode:
+ case SkXfermode::kSrc_Mode:
+ case SkXfermode::kDst_Mode:
+ case SkXfermode::kDstOver_Mode:
+ case SkXfermode::kSrcIn_Mode:
+ case SkXfermode::kDstIn_Mode:
+ case SkXfermode::kSrcOut_Mode:
+ case SkXfermode::kDstOut_Mode:
+ case SkXfermode::kSrcATop_Mode:
+ case SkXfermode::kDstATop_Mode:
+ case SkXfermode::kXor_Mode:
+ case SkXfermode::kPlus_Mode:
+ case SkXfermode::kModulate_Mode:
+ // Porter Duff Compositing Operators are not yet supported
+ // http://dev.w3.org/fxtf/compositing-1/#porterduffcompositingoperators
+ NOTREACHED();
+ return;
+ }
+
+ blend_mode_ = blend_mode;
+ SetNeedsCommit();
+ SetNeedsFilterContextIfNeeded();
+}
+
+void Layer::SetIsRootForIsolatedGroup(bool root) {
+ DCHECK(IsPropertyChangeAllowed());
+ if (is_root_for_isolated_group_ == root)
+ return;
+ is_root_for_isolated_group_ = root;
+ SetNeedsCommit();
+}
+
void Layer::SetContentsOpaque(bool opaque) {
DCHECK(IsPropertyChangeAllowed());
if (contents_opaque_ == opaque)
@@ -630,7 +688,7 @@ void Layer::SetScrollOffset(gfx::Vector2d scroll_offset) {
void Layer::SetScrollOffsetFromImplSide(gfx::Vector2d scroll_offset) {
DCHECK(IsPropertyChangeAllowed());
- // This function only gets called during a begin frame, so there
+ // This function only gets called during a BeginMainFrame, so there
// is no need to call SetNeedsUpdate here.
DCHECK(layer_tree_host_ && layer_tree_host_->CommitRequested());
if (scroll_offset_ == scroll_offset)
@@ -659,6 +717,16 @@ void Layer::SetScrollable(bool scrollable) {
SetNeedsCommit();
}
+void Layer::SetUserScrollable(bool horizontal, bool vertical) {
+ DCHECK(IsPropertyChangeAllowed());
+ if (user_scrollable_horizontal_ == horizontal &&
+ user_scrollable_vertical_ == vertical)
+ return;
+ user_scrollable_horizontal_ = horizontal;
+ user_scrollable_vertical_ = vertical;
+ SetNeedsCommit();
+}
+
void Layer::SetShouldScrollOnMainThread(bool should_scroll_on_main_thread) {
DCHECK(IsPropertyChangeAllowed());
if (should_scroll_on_main_thread_ == should_scroll_on_main_thread)
@@ -808,10 +876,12 @@ void Layer::PushPropertiesTo(LayerImpl* layer) {
bool is_tracing;
TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
&is_tracing);
- if (is_tracing)
- layer->SetDebugName(DebugName());
- else
- layer->SetDebugName(std::string());
+ if (is_tracing) {
+ layer->SetDebugName(DebugName());
+ layer->SetDebugInfo(TakeDebugInfo());
+ } else {
+ layer->SetDebugName(std::string());
+ }
layer->SetCompositingReasons(compositing_reasons_);
layer->SetDoubleSided(double_sided_);
@@ -820,8 +890,9 @@ void Layer::PushPropertiesTo(LayerImpl* layer) {
layer->SetForceRenderSurface(force_render_surface_);
layer->SetDrawsContent(DrawsContent());
layer->SetHideLayerAndSubtree(hide_layer_and_subtree_);
- layer->SetFilters(filters());
- layer->SetFilter(filter());
+ if (!layer->FilterIsAnimatingOnImplOnly() && !FilterIsAnimating())
+ layer->SetFilters(filters_);
+ DCHECK(!(FilterIsAnimating() && layer->FilterIsAnimatingOnImplOnly()));
layer->SetBackgroundFilters(background_filters());
layer->SetMasksToBounds(masks_to_bounds_);
layer->SetShouldScrollOnMainThread(should_scroll_on_main_thread_);
@@ -832,6 +903,8 @@ void Layer::PushPropertiesTo(LayerImpl* layer) {
if (!layer->OpacityIsAnimatingOnImplOnly() && !OpacityIsAnimating())
layer->SetOpacity(opacity_);
DCHECK(!(OpacityIsAnimating() && layer->OpacityIsAnimatingOnImplOnly()));
+ layer->SetBlendMode(blend_mode_);
+ layer->SetIsRootForIsolatedGroup(is_root_for_isolated_group_);
layer->SetPosition(position_);
layer->SetIsContainerForFixedPositionLayers(
IsContainerForFixedPositionLayers());
@@ -845,6 +918,8 @@ void Layer::PushPropertiesTo(LayerImpl* layer) {
DCHECK(!(TransformIsAnimating() && layer->TransformIsAnimatingOnImplOnly()));
layer->SetScrollable(scrollable_);
+ layer->set_user_scrollable_horizontal(user_scrollable_horizontal_);
+ layer->set_user_scrollable_vertical(user_scrollable_vertical_);
layer->SetMaxScrollOffset(max_scroll_offset_);
LayerImpl* scroll_parent = NULL;
@@ -879,8 +954,8 @@ void Layer::PushPropertiesTo(LayerImpl* layer) {
}
// Adjust the scroll delta to be just the scrolls that have happened since
- // the begin frame was sent. This happens for impl-side painting
- // in LayerImpl::ApplyScrollDeltasSinceBeginFrame in a separate tree walk.
+ // the BeginMainFrame was sent. This happens for impl-side painting
+ // in LayerImpl::ApplyScrollDeltasSinceBeginMainFrame in a separate tree walk.
if (layer->layer_tree_impl()->settings().impl_side_painting) {
layer->SetScrollOffset(scroll_offset_);
} else {
@@ -925,9 +1000,7 @@ void Layer::PushPropertiesTo(LayerImpl* layer) {
stacking_order_changed_ = false;
update_rect_ = gfx::RectF();
- // Animating layers require further push properties to clean up the animation.
- // crbug.com/259088
- needs_push_properties_ = layer_animation_controller_->has_any_animation();
+ needs_push_properties_ = false;
num_dependents_need_push_properties_ = 0;
}
@@ -966,6 +1039,14 @@ std::string Layer::DebugName() {
return client_ ? client_->DebugName() : std::string();
}
+scoped_refptr<base::debug::ConvertableToTraceFormat> Layer::TakeDebugInfo() {
+ if (client_)
+ return client_->TakeDebugInfo();
+ else
+ return NULL;
+}
+
+
void Layer::SetCompositingReasons(CompositingReasons reasons) {
compositing_reasons_ = reasons;
}
@@ -980,22 +1061,37 @@ void Layer::ClearRenderSurface() {
draw_properties_.render_surface.reset();
}
+gfx::Vector2dF Layer::ScrollOffsetForAnimation() const {
+ return TotalScrollOffset();
+}
+
+// On<Property>Animated is called due to an ongoing accelerated animation.
+// Since this animation is also being run on the compositor thread, there
+// is no need to request a commit to push this value over, so the value is
+// set directly rather than by calling Set<Property>.
+void Layer::OnFilterAnimated(const FilterOperations& filters) {
+ filters_ = filters;
+}
+
void Layer::OnOpacityAnimated(float opacity) {
- // This is called due to an ongoing accelerated animation. Since this
- // animation is also being run on the impl thread, there is no need to request
- // a commit to push this value over, so set the value directly rather than
- // calling SetOpacity.
opacity_ = opacity;
}
void Layer::OnTransformAnimated(const gfx::Transform& transform) {
- // This is called due to an ongoing accelerated animation. Since this
- // animation is also being run on the impl thread, there is no need to request
- // a commit to push this value over, so set this value directly rather than
- // calling SetTransform.
transform_ = transform;
}
+void Layer::OnScrollOffsetAnimated(gfx::Vector2dF scroll_offset) {
+ // Do nothing. Scroll deltas will be sent from the compositor thread back
+ // to the main thread in the same manner as during non-animated
+ // compositor-driven scrolling.
+}
+
+void Layer::OnAnimationWaitingForDeletion() {
+ // Animations are only deleted during PushProperties.
+ SetNeedsPushProperties();
+}
+
bool Layer::IsActive() const {
return true;
}
@@ -1021,21 +1117,10 @@ void Layer::RemoveAnimation(int animation_id) {
SetNeedsCommit();
}
-void Layer::SuspendAnimations(double monotonic_time) {
- layer_animation_controller_->SuspendAnimations(monotonic_time);
- SetNeedsCommit();
-}
-
-void Layer::ResumeAnimations(double monotonic_time) {
- layer_animation_controller_->ResumeAnimations(monotonic_time);
- SetNeedsCommit();
-}
-
void Layer::SetLayerAnimationControllerForTest(
scoped_refptr<LayerAnimationController> controller) {
layer_animation_controller_->RemoveValueObserver(this);
layer_animation_controller_ = controller;
- layer_animation_controller_->set_force_sync();
layer_animation_controller_->AddValueObserver(this);
SetNeedsCommit();
}
@@ -1098,4 +1183,8 @@ void Layer::RemoveFromClipTree() {
clip_parent_ = NULL;
}
+void Layer::RunMicroBenchmark(MicroBenchmark* benchmark) {
+ benchmark->RunOnLayer(this);
+}
+
} // namespace cc
diff --git a/chromium/cc/layers/layer.h b/chromium/cc/layers/layer.h
index 737e83df067..f0bca17f47c 100644
--- a/chromium/cc/layers/layer.h
+++ b/chromium/cc/layers/layer.h
@@ -13,9 +13,11 @@
#include "base/observer_list.h"
#include "cc/animation/layer_animation_controller.h"
#include "cc/animation/layer_animation_value_observer.h"
+#include "cc/animation/layer_animation_value_provider.h"
#include "cc/base/cc_export.h"
#include "cc/base/region.h"
#include "cc/base/scoped_ptr_vector.h"
+#include "cc/debug/micro_benchmark.h"
#include "cc/layers/compositing_reasons.h"
#include "cc/layers/draw_properties.h"
#include "cc/layers/layer_lists.h"
@@ -28,6 +30,7 @@
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkImageFilter.h"
#include "third_party/skia/include/core/SkPicture.h"
+#include "third_party/skia/include/core/SkXfermode.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/rect_f.h"
#include "ui/gfx/transform.h"
@@ -36,6 +39,12 @@ namespace gfx {
class BoxF;
}
+namespace base {
+namespace debug {
+class ConvertableToTraceFormat;
+}
+}
+
namespace cc {
class Animation;
@@ -57,8 +66,13 @@ struct AnimationEvent;
// Base class for composited layers. Special layer types are derived from
// this class.
class CC_EXPORT Layer : public base::RefCounted<Layer>,
- public LayerAnimationValueObserver {
+ public LayerAnimationValueObserver,
+ public LayerAnimationValueProvider {
public:
+ typedef RenderSurfaceLayerList RenderSurfaceListType;
+ typedef LayerList LayerListType;
+ typedef RenderSurface RenderSurfaceType;
+
enum LayerIdLabels {
INVALID_ID = -1,
};
@@ -121,11 +135,25 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>,
bool OpacityIsAnimating() const;
virtual bool OpacityCanAnimateOnImplThread() const;
+ void SetBlendMode(SkXfermode::Mode blend_mode);
+ SkXfermode::Mode blend_mode() const { return blend_mode_; }
+
+ bool uses_default_blend_mode() const {
+ return blend_mode_ == SkXfermode::kSrcOver_Mode;
+ }
+
+ // A layer is root for an isolated group when it and all its descendants are
+ // drawn over a black and fully transparent background, creating an isolated
+ // group. It should be used along with SetBlendMode(), in order to restrict
+ // layers within the group to blend with layers outside this group.
+ void SetIsRootForIsolatedGroup(bool root);
+ bool is_root_for_isolated_group() const {
+ return is_root_for_isolated_group_;
+ }
+
void SetFilters(const FilterOperations& filters);
const FilterOperations& filters() const { return filters_; }
-
- void SetFilter(const skia::RefPtr<SkImageFilter>& filter);
- skia::RefPtr<SkImageFilter> filter() const { return filter_; }
+ bool FilterIsAnimating() 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
@@ -186,10 +214,8 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>,
return clip_children_.get();
}
- DrawProperties<Layer, RenderSurface>& draw_properties() {
- return draw_properties_;
- }
- const DrawProperties<Layer, RenderSurface>& draw_properties() const {
+ DrawProperties<Layer>& draw_properties() { return draw_properties_; }
+ const DrawProperties<Layer>& draw_properties() const {
return draw_properties_;
}
@@ -250,6 +276,12 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>,
void SetScrollable(bool scrollable);
bool scrollable() const { return scrollable_; }
+ void SetUserScrollable(bool horizontal, bool vertical);
+ bool user_scrollable_horizontal() const {
+ return user_scrollable_horizontal_;
+ }
+ bool user_scrollable_vertical() const { return user_scrollable_vertical_; }
+
void SetShouldScrollOnMainThread(bool should_scroll_on_main_thread);
bool should_scroll_on_main_thread() const {
return should_scroll_on_main_thread_;
@@ -329,8 +361,10 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>,
virtual bool NeedMoreUpdates();
virtual void SetIsMask(bool is_mask) {}
virtual void ReduceMemoryUsage() {}
+ virtual void OnOutputSurfaceCreated() {}
virtual std::string DebugName();
+ virtual scoped_refptr<base::debug::ConvertableToTraceFormat> TakeDebugInfo();
void SetLayerClient(LayerClient* client) { client_ = client; }
@@ -367,9 +401,6 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>,
void PauseAnimation(int animation_id, double time_offset);
void RemoveAnimation(int animation_id);
- void SuspendAnimations(double monotonic_time);
- void ResumeAnimations(double monotonic_time);
-
bool AnimatedBoundsForBox(const gfx::BoxF& box, gfx::BoxF* bounds) {
return layer_animation_controller_->AnimatedBoundsForBox(box, bounds);
}
@@ -399,8 +430,6 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>,
virtual skia::RefPtr<SkPicture> GetPicture() const;
- virtual bool CanClipSelf() const;
-
// Constructs a LayerImpl of the correct runtime type for this Layer type.
virtual scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl);
@@ -428,6 +457,8 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>,
return num_dependents_need_push_properties_ > 0;
}
+ virtual void RunMicroBenchmark(MicroBenchmark* benchmark);
+
protected:
friend class LayerImpl;
friend class TreeSynchronizer;
@@ -454,6 +485,9 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>,
// unused resources on the impl thread are returned before commit completes.
void SetNextCommitWaitsForActivation();
+ // Called when the blend mode or filters have been changed.
+ void SetNeedsFilterContextIfNeeded();
+
void SetNeedsPushProperties();
void AddDependentNeedsPushProperties();
void RemoveDependentNeedsPushProperties();
@@ -513,9 +547,15 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>,
// This should only be called from RemoveFromParent().
void RemoveChildOrDependent(Layer* child);
+ // LayerAnimationValueProvider implementation.
+ virtual gfx::Vector2dF ScrollOffsetForAnimation() const OVERRIDE;
+
// LayerAnimationValueObserver implementation.
+ virtual void OnFilterAnimated(const FilterOperations& filters) OVERRIDE;
virtual void OnOpacityAnimated(float opacity) OVERRIDE;
virtual void OnTransformAnimated(const gfx::Transform& transform) OVERRIDE;
+ virtual void OnScrollOffsetAnimated(gfx::Vector2dF scroll_offset) OVERRIDE;
+ virtual void OnAnimationWaitingForDeletion() OVERRIDE;
virtual bool IsActive() const OVERRIDE;
LayerList children_;
@@ -533,9 +573,22 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>,
gfx::Vector2d scroll_offset_;
gfx::Vector2d max_scroll_offset_;
- bool scrollable_;
- bool should_scroll_on_main_thread_;
- bool have_wheel_event_handlers_;
+ bool scrollable_ : 1;
+ bool should_scroll_on_main_thread_ : 1;
+ bool have_wheel_event_handlers_ : 1;
+ bool user_scrollable_horizontal_ : 1;
+ bool user_scrollable_vertical_ : 1;
+ bool is_root_for_isolated_group_ : 1;
+ bool is_container_for_fixed_position_layers_ : 1;
+ bool is_drawable_ : 1;
+ bool hide_layer_and_subtree_ : 1;
+ bool masks_to_bounds_ : 1;
+ bool contents_opaque_ : 1;
+ bool double_sided_ : 1;
+ bool preserves_3d_ : 1;
+ bool use_parent_backface_visibility_ : 1;
+ bool draw_checkerboard_for_missing_tiles_ : 1;
+ bool force_render_surface_ : 1;
Region non_fast_scrollable_region_;
Region touch_event_handler_region_;
gfx::PointF position_;
@@ -543,21 +596,11 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>,
SkColor background_color_;
CompositingReasons compositing_reasons_;
float opacity_;
- skia::RefPtr<SkImageFilter> filter_;
+ SkXfermode::Mode blend_mode_;
FilterOperations filters_;
FilterOperations background_filters_;
float anchor_point_z_;
- bool is_container_for_fixed_position_layers_;
LayerPositionConstraint position_constraint_;
- bool is_drawable_;
- bool hide_layer_and_subtree_;
- bool masks_to_bounds_;
- bool contents_opaque_;
- bool double_sided_;
- bool preserves_3d_;
- bool use_parent_backface_visibility_;
- bool draw_checkerboard_for_missing_tiles_;
- bool force_render_surface_;
Layer* scroll_parent_;
scoped_ptr<std::set<Layer*> > scroll_children_;
@@ -579,7 +622,7 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>,
base::Closure did_scroll_callback_;
- DrawProperties<Layer, RenderSurface> draw_properties_;
+ DrawProperties<Layer> draw_properties_;
PaintProperties paint_properties_;
diff --git a/chromium/cc/layers/layer_client.h b/chromium/cc/layers/layer_client.h
index 73c0fd2514b..6ef6efe1c1b 100644
--- a/chromium/cc/layers/layer_client.h
+++ b/chromium/cc/layers/layer_client.h
@@ -7,14 +7,27 @@
#include <string>
+#include "base/memory/ref_counted.h"
#include "cc/base/cc_export.h"
+namespace base {
+namespace debug {
+class ConvertableToTraceFormat;
+}
+}
+
namespace cc {
class CC_EXPORT LayerClient {
public:
virtual std::string DebugName() = 0;
+ // Returns a pointer to a debug info object, if one has been computed.
+ // If not, returns NULL. If the returned pointer is non-NULL, the caller takes
+ // ownership of the pointer.
+ virtual scoped_refptr<base::debug::ConvertableToTraceFormat>
+ TakeDebugInfo() = 0;
+
protected:
virtual ~LayerClient() {}
};
diff --git a/chromium/cc/layers/layer_impl.cc b/chromium/cc/layers/layer_impl.cc
index b0c5399d32e..74b69b5572a 100644
--- a/chromium/cc/layers/layer_impl.cc
+++ b/chromium/cc/layers/layer_impl.cc
@@ -1,10 +1,11 @@
-// Copyright 2011 The Chromium Authors. All rights reserved.
+// 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/layers/layer_impl.h"
#include "base/debug/trace_event.h"
+#include "base/json/json_reader.h"
#include "base/strings/stringprintf.h"
#include "cc/animation/animation_registrar.h"
#include "cc/animation/scrollbar_animation_controller.h"
@@ -13,6 +14,7 @@
#include "cc/base/math_util.h"
#include "cc/debug/debug_colors.h"
#include "cc/debug/layer_tree_debug_state.h"
+#include "cc/debug/micro_benchmark_impl.h"
#include "cc/debug/traced_value.h"
#include "cc/input/layer_scroll_offset_delegate.h"
#include "cc/layers/painted_scrollbar_layer_impl.h"
@@ -22,12 +24,12 @@
#include "cc/trees/layer_tree_impl.h"
#include "cc/trees/layer_tree_settings.h"
#include "cc/trees/proxy.h"
+#include "ui/gfx/box_f.h"
#include "ui/gfx/point_conversions.h"
#include "ui/gfx/quad_f.h"
#include "ui/gfx/rect_conversions.h"
namespace cc {
-
LayerImpl::LayerImpl(LayerTreeImpl* tree_impl, int id)
: parent_(NULL),
scroll_parent_(NULL),
@@ -42,14 +44,14 @@ LayerImpl::LayerImpl(LayerTreeImpl* tree_impl, int id)
scrollable_(false),
should_scroll_on_main_thread_(false),
have_wheel_event_handlers_(false),
- background_color_(0),
+ user_scrollable_horizontal_(true),
+ user_scrollable_vertical_(true),
stacking_order_changed_(false),
double_sided_(true),
layer_property_changed_(false),
- layer_surface_property_changed_(false),
masks_to_bounds_(false),
contents_opaque_(false),
- opacity_(1.0),
+ is_root_for_isolated_group_(false),
preserves_3d_(false),
use_parent_backface_visibility_(false),
draw_checkerboard_for_missing_tiles_(false),
@@ -57,6 +59,9 @@ LayerImpl::LayerImpl(LayerTreeImpl* tree_impl, int id)
hide_layer_and_subtree_(false),
force_render_surface_(false),
is_container_for_fixed_position_layers_(false),
+ background_color_(0),
+ opacity_(1.0),
+ blend_mode_(SkXfermode::kSrcOver_Mode),
draw_depth_(0.f),
compositing_reasons_(kCompositingReasonUnknown),
current_draw_mode_(DRAW_MODE_NONE),
@@ -69,13 +74,19 @@ LayerImpl::LayerImpl(LayerTreeImpl* tree_impl, int id)
layer_animation_controller_ =
registrar->GetAnimationControllerForId(layer_id_);
layer_animation_controller_->AddValueObserver(this);
+ if (IsActive())
+ layer_animation_controller_->set_value_provider(this);
}
LayerImpl::~LayerImpl() {
DCHECK_EQ(DRAW_MODE_NONE, current_draw_mode_);
- layer_tree_impl_->UnregisterLayer(this);
layer_animation_controller_->RemoveValueObserver(this);
+ layer_animation_controller_->remove_value_provider(this);
+
+ if (!copy_requests_.empty() && layer_tree_impl_->IsActiveTree())
+ layer_tree_impl()->RemoveLayerWithCopyOutputRequest(this);
+ layer_tree_impl_->UnregisterLayer(this);
if (scroll_children_) {
for (std::set<LayerImpl*>::iterator it = scroll_children_->begin();
@@ -150,6 +161,11 @@ void LayerImpl::SetScrollParent(LayerImpl* parent) {
scroll_parent_ = parent;
}
+void LayerImpl::SetDebugInfo(
+ scoped_refptr<base::debug::ConvertableToTraceFormat> other) {
+ debug_info_ = other;
+}
+
void LayerImpl::SetScrollChildren(std::set<LayerImpl*>* children) {
if (scroll_children_.get() == children)
return;
@@ -243,7 +259,8 @@ scoped_ptr<SharedQuadState> LayerImpl::CreateSharedQuadState() const {
draw_properties_.visible_content_rect,
draw_properties_.clip_rect,
draw_properties_.is_clipped,
- draw_properties_.opacity);
+ draw_properties_.opacity,
+ blend_mode_);
return state.Pass();
}
@@ -342,14 +359,14 @@ void LayerImpl::SetSentScrollDelta(gfx::Vector2d sent_scroll_delta) {
gfx::Vector2dF LayerImpl::ScrollBy(gfx::Vector2dF scroll) {
DCHECK(scrollable());
-
gfx::Vector2dF min_delta = -scroll_offset_;
gfx::Vector2dF max_delta = max_scroll_offset_ - scroll_offset_;
// Clamp new_delta so that position + delta stays within scroll bounds.
gfx::Vector2dF new_delta = (ScrollDelta() + scroll);
new_delta.SetToMax(min_delta);
new_delta.SetToMin(max_delta);
- gfx::Vector2dF unscrolled = ScrollDelta() + scroll - new_delta;
+ gfx::Vector2dF unscrolled =
+ ScrollDelta() + scroll - new_delta;
SetScrollDelta(new_delta);
return unscrolled;
}
@@ -374,7 +391,7 @@ void LayerImpl::ApplySentScrollDeltasFromAbortedCommit() {
sent_scroll_delta_ = gfx::Vector2d();
}
-void LayerImpl::ApplyScrollDeltasSinceBeginFrame() {
+void LayerImpl::ApplyScrollDeltasSinceBeginMainFrame() {
// Only the pending tree can have missing scrolls.
DCHECK(layer_tree_impl()->IsPendingTree());
if (!scrollable())
@@ -472,10 +489,6 @@ skia::RefPtr<SkPicture> LayerImpl::GetPicture() {
return skia::RefPtr<SkPicture>();
}
-bool LayerImpl::CanClipSelf() const {
- return false;
-}
-
bool LayerImpl::AreVisibleResourcesReady() const {
return true;
}
@@ -500,7 +513,6 @@ void LayerImpl::PushPropertiesTo(LayerImpl* layer) {
layer->SetDrawsContent(DrawsContent());
layer->SetHideLayerAndSubtree(hide_layer_and_subtree_);
layer->SetFilters(filters());
- layer->SetFilter(filter());
layer->SetBackgroundFilters(background_filters());
layer->SetMasksToBounds(masks_to_bounds_);
layer->SetShouldScrollOnMainThread(should_scroll_on_main_thread_);
@@ -509,6 +521,8 @@ void LayerImpl::PushPropertiesTo(LayerImpl* layer) {
layer->SetTouchEventHandlerRegion(touch_event_handler_region_);
layer->SetContentsOpaque(contents_opaque_);
layer->SetOpacity(opacity_);
+ layer->SetBlendMode(blend_mode_);
+ layer->SetIsRootForIsolatedGroup(is_root_for_isolated_group_);
layer->SetPosition(position_);
layer->SetIsContainerForFixedPositionLayers(
is_container_for_fixed_position_layers_);
@@ -520,6 +534,8 @@ void LayerImpl::PushPropertiesTo(LayerImpl* layer) {
layer->SetTransform(transform_);
layer->SetScrollable(scrollable_);
+ layer->set_user_scrollable_horizontal(user_scrollable_horizontal_);
+ layer->set_user_scrollable_vertical(user_scrollable_vertical_);
layer->SetScrollOffsetAndDelta(
scroll_offset_, layer->ScrollDelta() - layer->sent_scroll_delta());
layer->SetSentScrollDelta(gfx::Vector2d());
@@ -568,6 +584,8 @@ void LayerImpl::PushPropertiesTo(LayerImpl* layer) {
// Reset any state that should be cleared for the next update.
stacking_order_changed_ = false;
update_rect_ = gfx::RectF();
+
+ layer->SetDebugInfo(debug_info_);
}
base::DictionaryValue* LayerImpl::LayerTreeAsJson() const {
@@ -599,6 +617,13 @@ base::DictionaryValue* LayerImpl::LayerTreeAsJson() const {
if (scrollable_)
result->SetBoolean("Scrollable", scrollable_);
+ if (have_wheel_event_handlers_)
+ result->SetBoolean("WheelHandler", have_wheel_event_handlers_);
+ if (!touch_event_handler_region_.IsEmpty()) {
+ scoped_ptr<base::Value> region = touch_event_handler_region_.AsValue();
+ result->Set("TouchRegion", region.release());
+ }
+
list = new base::ListValue;
for (size_t i = 0; i < children_.size(); ++i)
list->Append(children_[i]->LayerTreeAsJson());
@@ -614,30 +639,6 @@ void LayerImpl::SetStackingOrderChanged(bool stacking_order_changed) {
}
}
-bool LayerImpl::LayerSurfacePropertyChanged() const {
- if (layer_surface_property_changed_)
- return true;
-
- // If this layer's surface property hasn't changed, we want to see if
- // some layer above us has changed this property. This is done for the
- // case when such parent layer does not draw content, and therefore will
- // not be traversed by the damage tracker. We need to make sure that
- // property change on such layer will be caught by its descendants.
- LayerImpl* current = this->parent_;
- while (current && !current->draw_properties_.render_surface) {
- if (current->layer_surface_property_changed_)
- return true;
- current = current->parent_;
- }
-
- return false;
-}
-
-void LayerImpl::NoteLayerSurfacePropertyChanged() {
- layer_surface_property_changed_ = true;
- layer_tree_impl()->set_needs_update_draw_properties();
-}
-
void LayerImpl::NoteLayerPropertyChanged() {
layer_property_changed_ = true;
layer_tree_impl()->set_needs_update_draw_properties();
@@ -660,7 +661,6 @@ const char* LayerImpl::LayerTypeAsString() const {
void LayerImpl::ResetAllChangeTrackingForSubtree() {
layer_property_changed_ = false;
- layer_surface_property_changed_ = false;
update_rect_ = gfx::RectF();
@@ -683,6 +683,14 @@ bool LayerImpl::LayerIsAlwaysDamaged() const {
return false;
}
+gfx::Vector2dF LayerImpl::ScrollOffsetForAnimation() const {
+ return TotalScrollOffset();
+}
+
+void LayerImpl::OnFilterAnimated(const FilterOperations& filters) {
+ SetFilters(filters);
+}
+
void LayerImpl::OnOpacityAnimated(float opacity) {
SetOpacity(opacity);
}
@@ -691,6 +699,20 @@ void LayerImpl::OnTransformAnimated(const gfx::Transform& transform) {
SetTransform(transform);
}
+void LayerImpl::OnScrollOffsetAnimated(gfx::Vector2dF scroll_offset) {
+ // Only layers in the active tree should need to do anything here, since
+ // layers in the pending tree will find out about these changes as a
+ // result of the call to SetScrollDelta.
+ if (!IsActive())
+ return;
+
+ SetScrollDelta(scroll_offset - scroll_offset_);
+
+ layer_tree_impl_->DidAnimateScrollOffset();
+}
+
+void LayerImpl::OnAnimationWaitingForDeletion() {}
+
bool LayerImpl::IsActive() const {
return layer_tree_impl_->IsActiveTree();
}
@@ -818,11 +840,20 @@ void LayerImpl::SetFilters(const FilterOperations& filters) {
if (filters_ == filters)
return;
- DCHECK(!filter_);
filters_ = filters;
NoteLayerPropertyChangedForSubtree();
}
+bool LayerImpl::FilterIsAnimating() const {
+ return layer_animation_controller_->IsAnimatingProperty(Animation::Filter);
+}
+
+bool LayerImpl::FilterIsAnimatingOnImplOnly() const {
+ Animation* filter_animation =
+ layer_animation_controller_->GetAnimation(Animation::Filter);
+ return filter_animation && filter_animation->is_impl_only();
+}
+
void LayerImpl::SetBackgroundFilters(
const FilterOperations& filters) {
if (background_filters_ == filters)
@@ -832,15 +863,6 @@ void LayerImpl::SetBackgroundFilters(
NoteLayerPropertyChanged();
}
-void LayerImpl::SetFilter(const skia::RefPtr<SkImageFilter>& filter) {
- if (filter_.get() == filter.get())
- return;
-
- DCHECK(filters_.IsEmpty());
- filter_ = filter;
- NoteLayerPropertyChangedForSubtree();
-}
-
void LayerImpl::SetMasksToBounds(bool masks_to_bounds) {
if (masks_to_bounds_ == masks_to_bounds)
return;
@@ -862,7 +884,7 @@ void LayerImpl::SetOpacity(float opacity) {
return;
opacity_ = opacity;
- NoteLayerSurfacePropertyChanged();
+ NoteLayerPropertyChangedForSubtree();
}
bool LayerImpl::OpacityIsAnimating() const {
@@ -875,6 +897,21 @@ bool LayerImpl::OpacityIsAnimatingOnImplOnly() const {
return opacity_animation && opacity_animation->is_impl_only();
}
+void LayerImpl::SetBlendMode(SkXfermode::Mode blend_mode) {
+ if (blend_mode_ == blend_mode)
+ return;
+
+ blend_mode_ = blend_mode;
+ NoteLayerPropertyChangedForSubtree();
+}
+
+void LayerImpl::SetIsRootForIsolatedGroup(bool root) {
+ if (is_root_for_isolated_group_ == root)
+ return;
+
+ is_root_for_isolated_group_ = root;
+}
+
void LayerImpl::SetPosition(gfx::PointF position) {
if (position_ == position)
return;
@@ -906,7 +943,7 @@ void LayerImpl::SetTransform(const gfx::Transform& transform) {
return;
transform_ = transform;
- NoteLayerSurfacePropertyChanged();
+ NoteLayerPropertyChangedForSubtree();
}
bool LayerImpl::TransformIsAnimating() const {
@@ -1001,8 +1038,15 @@ void LayerImpl::SetScrollOffsetDelegate(
}
gfx::Vector2dF total_offset = TotalScrollOffset();
scroll_offset_delegate_ = scroll_offset_delegate;
- if (scroll_offset_delegate_)
+ if (scroll_offset_delegate_) {
+ scroll_offset_delegate_->SetMaxScrollOffset(max_scroll_offset_);
scroll_offset_delegate_->SetTotalScrollOffset(total_offset);
+ }
+}
+
+bool LayerImpl::IsExternalFlingActive() const {
+ return scroll_offset_delegate_ &&
+ scroll_offset_delegate_->IsExternalFlingActive();
}
void LayerImpl::SetScrollOffset(gfx::Vector2d scroll_offset) {
@@ -1088,6 +1132,9 @@ void LayerImpl::SetMaxScrollOffset(gfx::Vector2d max_scroll_offset) {
return;
max_scroll_offset_ = max_scroll_offset;
+ if (scroll_offset_delegate_)
+ scroll_offset_delegate_->SetMaxScrollOffset(max_scroll_offset_);
+
layer_tree_impl()->set_needs_update_draw_properties();
UpdateScrollbarPositions();
}
@@ -1266,6 +1313,9 @@ CompositingReasonsAsValue(CompositingReasons reasons) {
if (reasons & kCompositingReasonOutOfFlowClipping)
reason_list->AppendString("Has clipping ancestor");
+ if (reasons & kCompositingReasonIsolateCompositedDescendants)
+ reason_list->AppendString("Should isolate composited descendants");
+
return reason_list.PassAs<base::Value>();
}
@@ -1315,6 +1365,30 @@ void LayerImpl::AsValueInto(base::DictionaryValue* state) const {
if (clip_parent_)
state->SetInteger("clip_parent", clip_parent_->id());
+
+ state->SetBoolean("can_use_lcd_text", can_use_lcd_text());
+ state->SetBoolean("contents_opaque", contents_opaque());
+
+ if (layer_animation_controller_->IsAnimatingProperty(Animation::Transform) ||
+ layer_animation_controller_->IsAnimatingProperty(Animation::Filter)) {
+ gfx::BoxF box(bounds().width(), bounds().height(), 0.f);
+ gfx::BoxF inflated;
+ if (layer_animation_controller_->AnimatedBoundsForBox(box, &inflated))
+ state->Set("animated_bounds", MathUtil::AsValue(inflated).release());
+ }
+
+ if (debug_info_.get()) {
+ std::string str;
+ debug_info_->AppendAsTraceFormat(&str);
+ base::JSONReader json_reader;
+ // Parsing the JSON and re-encoding it is not very efficient,
+ // but it's the simplest way to achieve the desired effect, which
+ // is to output:
+ // {..., layout_rects: [{geometry_rect: ...}, ...], ...}
+ // rather than:
+ // {layout_rects: "[{geometry_rect: ...}, ...]", ...}
+ state->Set("layout_rects", json_reader.ReadToValue(str));
+ }
}
size_t LayerImpl::GPUMemoryUsageInBytes() const { return 0; }
@@ -1325,4 +1399,8 @@ scoped_ptr<base::Value> LayerImpl::AsValue() const {
return state.PassAs<base::Value>();
}
+void LayerImpl::RunMicroBenchmark(MicroBenchmarkImpl* benchmark) {
+ benchmark->RunOnLayer(this);
+}
+
} // namespace cc
diff --git a/chromium/cc/layers/layer_impl.h b/chromium/cc/layers/layer_impl.h
index ba0ff7b8216..cfbd353bf54 100644
--- a/chromium/cc/layers/layer_impl.h
+++ b/chromium/cc/layers/layer_impl.h
@@ -13,6 +13,7 @@
#include "base/values.h"
#include "cc/animation/layer_animation_controller.h"
#include "cc/animation/layer_animation_value_observer.h"
+#include "cc/animation/layer_animation_value_provider.h"
#include "cc/base/cc_export.h"
#include "cc/base/region.h"
#include "cc/base/scoped_ptr_vector.h"
@@ -35,6 +36,10 @@
#include "ui/gfx/transform.h"
namespace base {
+namespace debug {
+class ConvertableToTraceFormat;
+}
+
class DictionaryValue;
}
@@ -42,11 +47,11 @@ namespace cc {
class LayerTreeHostImpl;
class LayerTreeImpl;
+class MicroBenchmarkImpl;
class QuadSink;
class Renderer;
class ScrollbarAnimationController;
class ScrollbarLayerImplBase;
-class Layer;
struct AppendQuadsData;
@@ -57,8 +62,13 @@ enum DrawMode {
DRAW_MODE_RESOURCELESS_SOFTWARE
};
-class CC_EXPORT LayerImpl : LayerAnimationValueObserver {
+class CC_EXPORT LayerImpl : public LayerAnimationValueObserver,
+ public LayerAnimationValueProvider {
public:
+ typedef LayerImplList RenderSurfaceListType;
+ typedef LayerImplList LayerListType;
+ typedef RenderSurfaceImpl RenderSurfaceType;
+
static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
return make_scoped_ptr(new LayerImpl(tree_impl, id));
}
@@ -67,9 +77,15 @@ class CC_EXPORT LayerImpl : LayerAnimationValueObserver {
int id() const { return layer_id_; }
+ // LayerAnimationValueProvider implementation.
+ virtual gfx::Vector2dF ScrollOffsetForAnimation() const OVERRIDE;
+
// LayerAnimationValueObserver implementation.
+ virtual void OnFilterAnimated(const FilterOperations& filters) OVERRIDE;
virtual void OnOpacityAnimated(float opacity) OVERRIDE;
virtual void OnTransformAnimated(const gfx::Transform& transform) OVERRIDE;
+ virtual void OnScrollOffsetAnimated(gfx::Vector2dF scroll_offset) OVERRIDE;
+ virtual void OnAnimationWaitingForDeletion() OVERRIDE;
virtual bool IsActive() const OVERRIDE;
// Tree structure.
@@ -187,15 +203,14 @@ class CC_EXPORT LayerImpl : LayerAnimationValueObserver {
void SetFilters(const FilterOperations& filters);
const FilterOperations& filters() const { return filters_; }
+ bool FilterIsAnimating() const;
+ bool FilterIsAnimatingOnImplOnly() const;
void SetBackgroundFilters(const FilterOperations& filters);
const FilterOperations& background_filters() const {
return background_filters_;
}
- void SetFilter(const skia::RefPtr<SkImageFilter>& filter);
- skia::RefPtr<SkImageFilter> filter() const { return filter_; }
-
void SetMasksToBounds(bool masks_to_bounds);
bool masks_to_bounds() const { return masks_to_bounds_; }
@@ -207,6 +222,17 @@ class CC_EXPORT LayerImpl : LayerAnimationValueObserver {
bool OpacityIsAnimating() const;
bool OpacityIsAnimatingOnImplOnly() const;
+ void SetBlendMode(SkXfermode::Mode);
+ SkXfermode::Mode blend_mode() const { return blend_mode_; }
+ bool uses_default_blend_mode() const {
+ return blend_mode_ == SkXfermode::kSrcOver_Mode;
+ }
+
+ void SetIsRootForIsolatedGroup(bool root);
+ bool is_root_for_isolated_group() const {
+ return is_root_for_isolated_group_;
+ }
+
void SetPosition(gfx::PointF position);
gfx::PointF position() const { return position_; }
@@ -267,10 +293,10 @@ class CC_EXPORT LayerImpl : LayerAnimationValueObserver {
void CreateRenderSurface();
void ClearRenderSurface();
- DrawProperties<LayerImpl, RenderSurfaceImpl>& draw_properties() {
+ DrawProperties<LayerImpl>& draw_properties() {
return draw_properties_;
}
- const DrawProperties<LayerImpl, RenderSurfaceImpl>& draw_properties() const {
+ const DrawProperties<LayerImpl>& draw_properties() const {
return draw_properties_;
}
@@ -335,6 +361,12 @@ class CC_EXPORT LayerImpl : LayerAnimationValueObserver {
float contents_scale_y() const { return draw_properties_.contents_scale_y; }
void SetContentsScale(float contents_scale_x, float contents_scale_y);
+ // Computes a box in screen space that should entirely contain the layer's
+ // bounds through the entirety of the layer's current animation. Returns true
+ // and sets |out| to the inflation if there are animations that can inflate
+ // bounds in the path to the root layer. Returns false otherwise.
+ bool GetAnimationBounds(gfx::BoxF* out) const { return false; }
+
virtual void CalculateContentsScale(float ideal_contents_scale,
float device_scale_factor,
float page_scale_factor,
@@ -345,6 +377,8 @@ class CC_EXPORT LayerImpl : LayerAnimationValueObserver {
void SetScrollOffsetDelegate(
LayerScrollOffsetDelegate* scroll_offset_delegate);
+ bool IsExternalFlingActive() const;
+
void SetScrollOffset(gfx::Vector2d scroll_offset);
void SetScrollOffsetAndDelta(gfx::Vector2d scroll_offset,
gfx::Vector2dF scroll_delta);
@@ -368,8 +402,15 @@ class CC_EXPORT LayerImpl : LayerAnimationValueObserver {
void SetScrollable(bool scrollable) { scrollable_ = scrollable; }
bool scrollable() const { return scrollable_; }
+ void set_user_scrollable_horizontal(bool scrollable) {
+ user_scrollable_horizontal_ = scrollable;
+ }
+ void set_user_scrollable_vertical(bool scrollable) {
+ user_scrollable_vertical_ = scrollable;
+ }
+
void ApplySentScrollDeltasFromAbortedCommit();
- void ApplyScrollDeltasSinceBeginFrame();
+ void ApplyScrollDeltasSinceBeginMainFrame();
void SetShouldScrollOnMainThread(bool should_scroll_on_main_thread) {
should_scroll_on_main_thread_ = should_scroll_on_main_thread;
@@ -427,7 +468,6 @@ class CC_EXPORT LayerImpl : LayerAnimationValueObserver {
bool LayerPropertyChanged() const {
return layer_property_changed_ || LayerIsAlwaysDamaged();
}
- bool LayerSurfacePropertyChanged() const;
void ResetAllChangeTrackingForSubtree();
@@ -466,8 +506,6 @@ class CC_EXPORT LayerImpl : LayerAnimationValueObserver {
virtual skia::RefPtr<SkPicture> GetPicture();
- virtual bool CanClipSelf() const;
-
virtual bool AreVisibleResourcesReady() const;
virtual scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl);
@@ -480,6 +518,11 @@ class CC_EXPORT LayerImpl : LayerAnimationValueObserver {
bool needs_push_properties() const { return true; }
bool descendant_needs_push_properties() const { return true; }
+ virtual void RunMicroBenchmark(MicroBenchmarkImpl* benchmark);
+
+ virtual void SetDebugInfo(
+ scoped_refptr<base::debug::ConvertableToTraceFormat> other);
+
protected:
LayerImpl(LayerTreeImpl* layer_impl, int id);
@@ -497,7 +540,6 @@ class CC_EXPORT LayerImpl : LayerAnimationValueObserver {
virtual void AsValueInto(base::DictionaryValue* dict) const;
- void NoteLayerSurfacePropertyChanged();
void NoteLayerPropertyChanged();
void NoteLayerPropertyChangedForSubtree();
@@ -539,43 +581,40 @@ class CC_EXPORT LayerImpl : LayerAnimationValueObserver {
gfx::Size bounds_;
gfx::Vector2d scroll_offset_;
LayerScrollOffsetDelegate* scroll_offset_delegate_;
- bool scrollable_;
- bool should_scroll_on_main_thread_;
- bool have_wheel_event_handlers_;
- Region non_fast_scrollable_region_;
- Region touch_event_handler_region_;
- SkColor background_color_;
- bool stacking_order_changed_;
-
+ bool scrollable_ : 1;
+ bool should_scroll_on_main_thread_ : 1;
+ bool have_wheel_event_handlers_ : 1;
+ bool user_scrollable_horizontal_ : 1;
+ bool user_scrollable_vertical_ : 1;
+ bool stacking_order_changed_ : 1;
// Whether the "back" of this layer should draw.
- bool double_sided_;
+ bool double_sided_ : 1;
// Tracks if drawing-related properties have changed since last redraw.
- bool layer_property_changed_;
+ bool layer_property_changed_ : 1;
+
+ bool masks_to_bounds_ : 1;
+ bool contents_opaque_ : 1;
+ bool is_root_for_isolated_group_ : 1;
+ bool preserves_3d_ : 1;
+ bool use_parent_backface_visibility_ : 1;
+ bool draw_checkerboard_for_missing_tiles_ : 1;
+ bool draws_content_ : 1;
+ bool hide_layer_and_subtree_ : 1;
+ bool force_render_surface_ : 1;
- // Indicates that a property has changed on this layer that would not
- // affect the pixels on its target surface, but would require redrawing
- // the target_surface onto its ancestor target_surface.
- // For layers that do not own a surface this flag acts as
- // layer_property_changed_.
- bool layer_surface_property_changed_;
+ // Set for the layer that other layers are fixed to.
+ bool is_container_for_fixed_position_layers_ : 1;
+ Region non_fast_scrollable_region_;
+ Region touch_event_handler_region_;
+ SkColor background_color_;
- bool masks_to_bounds_;
- bool contents_opaque_;
float opacity_;
+ SkXfermode::Mode blend_mode_;
gfx::PointF position_;
- bool preserves_3d_;
- bool use_parent_backface_visibility_;
- bool draw_checkerboard_for_missing_tiles_;
gfx::Transform sublayer_transform_;
gfx::Transform transform_;
- bool draws_content_;
- bool hide_layer_and_subtree_;
- bool force_render_surface_;
-
- // Set for the layer that other layers are fixed to.
- bool is_container_for_fixed_position_layers_;
// This property is effective when
// is_container_for_fixed_position_layers_ == true,
gfx::Vector2dF fixed_container_size_delta_;
@@ -597,7 +636,6 @@ class CC_EXPORT LayerImpl : LayerAnimationValueObserver {
FilterOperations filters_;
FilterOperations background_filters_;
- skia::RefPtr<SkImageFilter> filter_;
protected:
DrawMode current_draw_mode_;
@@ -605,7 +643,7 @@ class CC_EXPORT LayerImpl : LayerAnimationValueObserver {
private:
// Rect indicating what was repainted/updated during update.
// Note that plugin layers bypass this and leave it empty.
- // Uses layer's content space.
+ // Uses layer (not content) space.
gfx::RectF update_rect_;
// Manages animations for this layer.
@@ -623,7 +661,9 @@ class CC_EXPORT LayerImpl : LayerAnimationValueObserver {
// Group of properties that need to be computed based on the layer tree
// hierarchy before layers can be drawn.
- DrawProperties<LayerImpl, RenderSurfaceImpl> draw_properties_;
+ DrawProperties<LayerImpl> draw_properties_;
+
+ scoped_refptr<base::debug::ConvertableToTraceFormat> debug_info_;
DISALLOW_COPY_AND_ASSIGN(LayerImpl);
};
diff --git a/chromium/cc/layers/layer_impl_unittest.cc b/chromium/cc/layers/layer_impl_unittest.cc
index 1ab7a71b2ca..9d90c04928e 100644
--- a/chromium/cc/layers/layer_impl_unittest.cc
+++ b/chromium/cc/layers/layer_impl_unittest.cc
@@ -24,32 +24,28 @@ namespace {
code_to_test; \
EXPECT_TRUE(root->LayerPropertyChanged()); \
EXPECT_TRUE(child->LayerPropertyChanged()); \
- EXPECT_TRUE(grand_child->LayerPropertyChanged()); \
- EXPECT_FALSE(root->LayerSurfacePropertyChanged())
+ EXPECT_TRUE(grand_child->LayerPropertyChanged());
#define EXECUTE_AND_VERIFY_SUBTREE_DID_NOT_CHANGE(code_to_test) \
root->ResetAllChangeTrackingForSubtree(); \
code_to_test; \
EXPECT_FALSE(root->LayerPropertyChanged()); \
EXPECT_FALSE(child->LayerPropertyChanged()); \
- EXPECT_FALSE(grand_child->LayerPropertyChanged()); \
- EXPECT_FALSE(root->LayerSurfacePropertyChanged())
+ EXPECT_FALSE(grand_child->LayerPropertyChanged());
#define EXECUTE_AND_VERIFY_ONLY_LAYER_CHANGED(code_to_test) \
root->ResetAllChangeTrackingForSubtree(); \
code_to_test; \
EXPECT_TRUE(root->LayerPropertyChanged()); \
EXPECT_FALSE(child->LayerPropertyChanged()); \
- EXPECT_FALSE(grand_child->LayerPropertyChanged()); \
- EXPECT_FALSE(root->LayerSurfacePropertyChanged())
+ EXPECT_FALSE(grand_child->LayerPropertyChanged());
-#define EXECUTE_AND_VERIFY_ONLY_SURFACE_CHANGED(code_to_test) \
+#define EXECUTE_AND_VERIFY_ONLY_DESCENDANTS_CHANGED(code_to_test) \
root->ResetAllChangeTrackingForSubtree(); \
code_to_test; \
EXPECT_FALSE(root->LayerPropertyChanged()); \
- EXPECT_FALSE(child->LayerPropertyChanged()); \
- EXPECT_FALSE(grand_child->LayerPropertyChanged()); \
- EXPECT_TRUE(root->LayerSurfacePropertyChanged())
+ EXPECT_TRUE(child->LayerPropertyChanged()); \
+ EXPECT_TRUE(grand_child->LayerPropertyChanged());
#define VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(code_to_test) \
root->ResetAllChangeTrackingForSubtree(); \
@@ -99,11 +95,10 @@ TEST(LayerImplTest, VerifyLayerChangesAreTrackedProperly) {
gfx::RectF(arbitrary_point_f, gfx::SizeF(1.234f, 5.678f));
SkColor arbitrary_color = SkColorSetRGB(10, 20, 30);
gfx::Transform arbitrary_transform;
- arbitrary_transform.Scale3d(0.1, 0.2, 0.3);
+ arbitrary_transform.Scale3d(0.1f, 0.2f, 0.3f);
FilterOperations arbitrary_filters;
arbitrary_filters.Append(FilterOperation::CreateOpacityFilter(0.5f));
- skia::RefPtr<SkImageFilter> arbitrary_filter =
- skia::AdoptRef(new SkBlurImageFilter(SK_Scalar1, SK_Scalar1));
+ SkXfermode::Mode arbitrary_blend_mode = SkXfermode::kMultiply_Mode;
// These properties are internal, and should not be considered "change" when
// they are used.
@@ -117,7 +112,6 @@ TEST(LayerImplTest, VerifyLayerChangesAreTrackedProperly) {
EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->SetAnchorPointZ(arbitrary_number));
EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->SetFilters(arbitrary_filters));
EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->SetFilters(FilterOperations()));
- EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->SetFilter(arbitrary_filter));
EXECUTE_AND_VERIFY_SUBTREE_CHANGED(
root->SetMaskLayer(LayerImpl::Create(host_impl.active_tree(), 4)));
EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->SetMasksToBounds(true));
@@ -132,6 +126,9 @@ TEST(LayerImplTest, VerifyLayerChangesAreTrackedProperly) {
EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->SetScrollDelta(gfx::Vector2d()));
EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->SetScrollOffset(arbitrary_vector2d));
EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->SetHideLayerAndSubtree(true));
+ EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->SetOpacity(arbitrary_number));
+ EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->SetBlendMode(arbitrary_blend_mode));
+ EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->SetTransform(arbitrary_transform));
// Changing these properties only affects the layer itself.
EXECUTE_AND_VERIFY_ONLY_LAYER_CHANGED(root->SetContentBounds(arbitrary_size));
@@ -143,18 +140,10 @@ TEST(LayerImplTest, VerifyLayerChangesAreTrackedProperly) {
EXECUTE_AND_VERIFY_ONLY_LAYER_CHANGED(
root->SetBackgroundFilters(arbitrary_filters));
- // Changing these properties only affects how render surface is drawn
- EXECUTE_AND_VERIFY_ONLY_SURFACE_CHANGED(root->SetOpacity(arbitrary_number));
- EXECUTE_AND_VERIFY_ONLY_SURFACE_CHANGED(
- root->SetTransform(arbitrary_transform));
-
- // Special case: check that sublayer transform changes all layer's
- // descendants, but not the layer itself.
- root->ResetAllChangeTrackingForSubtree();
- root->SetSublayerTransform(arbitrary_transform);
- EXPECT_FALSE(root->LayerPropertyChanged());
- EXPECT_TRUE(child->LayerPropertyChanged());
- EXPECT_TRUE(grand_child->LayerPropertyChanged());
+ // Changing these properties affects all layer's descendants,
+ // but not the layer itself.
+ EXECUTE_AND_VERIFY_ONLY_DESCENDANTS_CHANGED(
+ root->SetSublayerTransform(arbitrary_transform));
// Special case: check that SetBounds changes behavior depending on
// masksToBounds.
@@ -165,6 +154,9 @@ TEST(LayerImplTest, VerifyLayerChangesAreTrackedProperly) {
// changed.
EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->SetBounds(arbitrary_size));
+ EXECUTE_AND_VERIFY_SUBTREE_DID_NOT_CHANGE(
+ root->SetIsRootForIsolatedGroup(true));
+
// After setting all these properties already, setting to the exact same
// values again should not cause any change.
EXECUTE_AND_VERIFY_SUBTREE_DID_NOT_CHANGE(
@@ -189,6 +181,10 @@ TEST(LayerImplTest, VerifyLayerChangesAreTrackedProperly) {
root->SetContentsScale(arbitrary_number, arbitrary_number));
EXECUTE_AND_VERIFY_SUBTREE_DID_NOT_CHANGE(root->SetContentsOpaque(true));
EXECUTE_AND_VERIFY_SUBTREE_DID_NOT_CHANGE(root->SetOpacity(arbitrary_number));
+ EXECUTE_AND_VERIFY_SUBTREE_DID_NOT_CHANGE(
+ root->SetBlendMode(arbitrary_blend_mode));
+ EXECUTE_AND_VERIFY_SUBTREE_DID_NOT_CHANGE(
+ root->SetIsRootForIsolatedGroup(true));
EXECUTE_AND_VERIFY_SUBTREE_DID_NOT_CHANGE(root->SetDrawsContent(true));
EXECUTE_AND_VERIFY_SUBTREE_DID_NOT_CHANGE(
root->SetSublayerTransform(arbitrary_transform));
@@ -213,18 +209,16 @@ TEST(LayerImplTest, VerifyNeedsUpdateDrawProperties) {
gfx::RectF(arbitrary_point_f, gfx::SizeF(1.234f, 5.678f));
SkColor arbitrary_color = SkColorSetRGB(10, 20, 30);
gfx::Transform arbitrary_transform;
- arbitrary_transform.Scale3d(0.1, 0.2, 0.3);
+ arbitrary_transform.Scale3d(0.1f, 0.2f, 0.3f);
FilterOperations arbitrary_filters;
arbitrary_filters.Append(FilterOperation::CreateOpacityFilter(0.5f));
- skia::RefPtr<SkImageFilter> arbitrary_filter =
- skia::AdoptRef(new SkBlurImageFilter(SK_Scalar1, SK_Scalar1));
+ SkXfermode::Mode arbitrary_blend_mode = SkXfermode::kMultiply_Mode;
// Related filter functions.
VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(root->SetFilters(arbitrary_filters));
VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES(root->SetFilters(arbitrary_filters));
VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(root->SetFilters(FilterOperations()));
- VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(root->SetFilter(arbitrary_filter));
- VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES(root->SetFilter(arbitrary_filter));
+ VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(root->SetFilters(arbitrary_filters));
// Related scrolling functions.
VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(root->SetMaxScrollOffset(large_vector2d));
@@ -263,6 +257,7 @@ TEST(LayerImplTest, VerifyNeedsUpdateDrawProperties) {
VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(
root->SetBackgroundFilters(arbitrary_filters));
VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(root->SetOpacity(arbitrary_number));
+ VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(root->SetBlendMode(arbitrary_blend_mode));
VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(root->SetTransform(arbitrary_transform));
VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(
root->SetSublayerTransform(arbitrary_transform));
@@ -271,7 +266,8 @@ TEST(LayerImplTest, VerifyNeedsUpdateDrawProperties) {
// Unrelated functions, set to the same values, no needs update.
VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES(
root->SetAnchorPointZ(arbitrary_number));
- VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES(root->SetFilter(arbitrary_filter));
+ VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES(root->SetIsRootForIsolatedGroup(true));
+ VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES(root->SetFilters(arbitrary_filters));
VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES(root->SetMasksToBounds(true));
VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES(root->SetContentsOpaque(true));
VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES(root->SetPosition(arbitrary_point_f));
@@ -289,6 +285,9 @@ TEST(LayerImplTest, VerifyNeedsUpdateDrawProperties) {
root->SetBackgroundFilters(arbitrary_filters));
VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES(root->SetOpacity(arbitrary_number));
VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES(
+ root->SetBlendMode(arbitrary_blend_mode));
+ VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES(root->SetIsRootForIsolatedGroup(true));
+ VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES(
root->SetTransform(arbitrary_transform));
VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES(
root->SetSublayerTransform(arbitrary_transform));
@@ -391,15 +390,20 @@ TEST_F(LayerImplScrollTest, ScrollByWithNonZeroOffset) {
class ScrollDelegateIgnore : public LayerScrollOffsetDelegate {
public:
+ virtual void SetMaxScrollOffset(gfx::Vector2dF max_scroll_offset) OVERRIDE {}
virtual void SetTotalScrollOffset(gfx::Vector2dF new_value) OVERRIDE {}
virtual gfx::Vector2dF GetTotalScrollOffset() OVERRIDE {
return fixed_offset_;
}
+ virtual bool IsExternalFlingActive() const OVERRIDE { return false; }
void set_fixed_offset(gfx::Vector2dF fixed_offset) {
fixed_offset_ = fixed_offset;
}
+ virtual void SetTotalPageScaleFactor(float page_scale_factor) OVERRIDE {}
+ virtual void SetScrollableSize(gfx::SizeF scrollable_size) OVERRIDE {}
+
private:
gfx::Vector2dF fixed_offset_;
};
@@ -441,12 +445,16 @@ TEST_F(LayerImplScrollTest, ScrollByWithIgnoringDelegate) {
class ScrollDelegateAccept : public LayerScrollOffsetDelegate {
public:
+ virtual void SetMaxScrollOffset(gfx::Vector2dF max_scroll_offset) OVERRIDE {}
virtual void SetTotalScrollOffset(gfx::Vector2dF new_value) OVERRIDE {
current_offset_ = new_value;
}
virtual gfx::Vector2dF GetTotalScrollOffset() OVERRIDE {
return current_offset_;
}
+ virtual bool IsExternalFlingActive() const OVERRIDE { return false; }
+ virtual void SetTotalPageScaleFactor(float page_scale_factor) OVERRIDE {}
+ virtual void SetScrollableSize(gfx::SizeF scrollable_size) OVERRIDE {}
private:
gfx::Vector2dF current_offset_;
@@ -558,5 +566,21 @@ TEST_F(LayerImplScrollTest, ApplySentScrollsWithAcceptingDelegate) {
EXPECT_VECTOR_EQ(gfx::Vector2d(), layer()->sent_scroll_delta());
}
+// The user-scrollability breaks for zoomed-in pages. So disable this.
+// http://crbug.com/322223
+TEST_F(LayerImplScrollTest, DISABLED_ScrollUserUnscrollableLayer) {
+ gfx::Vector2d max_scroll_offset(50, 80);
+ gfx::Vector2d scroll_offset(10, 5);
+ gfx::Vector2dF scroll_delta(20.5f, 8.5f);
+
+ layer()->set_user_scrollable_vertical(false);
+ layer()->SetMaxScrollOffset(max_scroll_offset);
+ layer()->SetScrollOffset(scroll_offset);
+ gfx::Vector2dF unscrolled = layer()->ScrollBy(scroll_delta);
+
+ EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 8.5f), unscrolled);
+ EXPECT_VECTOR_EQ(gfx::Vector2dF(30.5f, 5), layer()->TotalScrollOffset());
+}
+
} // namespace
} // namespace cc
diff --git a/chromium/cc/layers/layer_iterator.cc b/chromium/cc/layers/layer_iterator.cc
index c33e7536ec0..a52c3f1f39a 100644
--- a/chromium/cc/layers/layer_iterator.cc
+++ b/chromium/cc/layers/layer_iterator.cc
@@ -17,81 +17,6 @@ template <typename LayerType,
typename LayerList,
typename RenderSurfaceType,
typename ActionType>
-void LayerIteratorActions::BackToFront::Begin(
- LayerIterator<LayerType, LayerList, RenderSurfaceType, ActionType>* it) {
- it->target_render_surface_layer_index_ = 0;
- it->current_layer_index_ =
- LayerIteratorValue::kLayerIndexRepresentingTargetRenderSurface;
-
- highest_target_render_surface_layer_ = 0;
-}
-
-template <typename LayerType,
- typename LayerList,
- typename RenderSurfaceType,
- typename ActionType>
-void LayerIteratorActions::BackToFront::End(
- LayerIterator<LayerType, LayerList, RenderSurfaceType, ActionType>* it) {
- it->target_render_surface_layer_index_ =
- LayerIteratorValue::kInvalidTargetRenderSurfaceLayerIndex;
- it->current_layer_index_ = 0;
-}
-
-template <typename LayerType,
- typename LayerList,
- typename RenderSurfaceType,
- typename ActionType>
-void LayerIteratorActions::BackToFront::Next(
- LayerIterator<LayerType, LayerList, RenderSurfaceType, ActionType>* it) {
- // If the current layer has a RS, move to its layer list. Otherwise,
- // visit the next layer in the current RS layer list.
- if (it->current_layer_represents_contributing_render_surface()) {
- // Save our position in the child_layers list for the RenderSurface,
- // then jump to the next RenderSurface. Save where we
- // came from in the next RenderSurface so we can get back to it.
- it->target_render_surface()->current_layer_index_history_ =
- it->current_layer_index_;
- int previous_target_render_surface_layer =
- it->target_render_surface_layer_index_;
-
- it->target_render_surface_layer_index_ =
- ++highest_target_render_surface_layer_;
- it->current_layer_index_ =
- LayerIteratorValue::kLayerIndexRepresentingTargetRenderSurface;
-
- it->target_render_surface()->target_render_surface_layer_index_history_ =
- previous_target_render_surface_layer;
- } else {
- ++it->current_layer_index_;
-
- int target_render_surface_num_children =
- it->target_render_surface_children().size();
- while (it->current_layer_index_ == target_render_surface_num_children) {
- // Jump back to the previous RenderSurface,
- // and get back the position where we were in that list,
- // and move to the next position there.
- if (!it->target_render_surface_layer_index_) {
- // End of the list
- it->target_render_surface_layer_index_ =
- LayerIteratorValue::kInvalidTargetRenderSurfaceLayerIndex;
- it->current_layer_index_ = 0;
- return;
- }
- it->target_render_surface_layer_index_ = it->target_render_surface()
- ->target_render_surface_layer_index_history_;
- it->current_layer_index_ =
- it->target_render_surface()->current_layer_index_history_ + 1;
-
- target_render_surface_num_children =
- it->target_render_surface_children().size();
- }
- }
-}
-
-template <typename LayerType,
- typename LayerList,
- typename RenderSurfaceType,
- typename ActionType>
void LayerIteratorActions::FrontToBack::Begin(
LayerIterator<LayerType, LayerList, RenderSurfaceType, ActionType>* it) {
it->target_render_surface_layer_index_ = 0;
@@ -176,26 +101,6 @@ void LayerIteratorActions::FrontToBack::GoToHighestInSubtree(
// Declare each of the above functions for Layer and LayerImpl classes
// so that they are linked.
-template CC_EXPORT void LayerIteratorActions::BackToFront::Begin(
- LayerIterator<Layer, RenderSurfaceLayerList, RenderSurface, BackToFront>*
- it);
-template CC_EXPORT void LayerIteratorActions::BackToFront::End(
- LayerIterator<Layer, RenderSurfaceLayerList, RenderSurface, BackToFront>*
- it);
-template CC_EXPORT void LayerIteratorActions::BackToFront::Next(
- LayerIterator<Layer, RenderSurfaceLayerList, RenderSurface, BackToFront>*
- it);
-
-template CC_EXPORT void LayerIteratorActions::BackToFront::Begin(
- LayerIterator<LayerImpl, LayerImplList, RenderSurfaceImpl, BackToFront>*
- it);
-template CC_EXPORT void LayerIteratorActions::BackToFront::End(
- LayerIterator<LayerImpl, LayerImplList, RenderSurfaceImpl, BackToFront>*
- it);
-template CC_EXPORT void LayerIteratorActions::BackToFront::Next(
- LayerIterator<LayerImpl, LayerImplList, RenderSurfaceImpl, BackToFront>*
- it);
-
template CC_EXPORT void LayerIteratorActions::FrontToBack::Next(
LayerIterator<Layer, RenderSurfaceLayerList, RenderSurface, FrontToBack>*
it);
diff --git a/chromium/cc/layers/layer_iterator.h b/chromium/cc/layers/layer_iterator.h
index b8a02c34e22..5b132732545 100644
--- a/chromium/cc/layers/layer_iterator.h
+++ b/chromium/cc/layers/layer_iterator.h
@@ -69,11 +69,8 @@ namespace cc {
// refers to the layer itself, as a child of the
// current target RenderSurface.
//
-// The BackToFront iterator will return a layer representing the target surface
-// before returning layers representing themselves as children of the current
-// target surface. Whereas the FrontToBack ordering will iterate over children
-// layers of a surface before the layer representing the surface
-// as a target surface.
+// The FrontToBack iterator will iterate over children layers of a surface
+// before the layer representing the surface as a target surface.
//
// To use the iterators:
//
@@ -237,34 +234,6 @@ class LayerIterator {
// Orderings for iterating over the RenderSurface-Layer tree.
struct CC_EXPORT LayerIteratorActions {
- // Walks layers sorted by z-order from back to front.
- class CC_EXPORT BackToFront {
- public:
- template <typename LayerType,
- typename LayerList,
- typename RenderSurfaceType,
- typename ActionType>
- void Begin(
- LayerIterator<LayerType, LayerList, RenderSurfaceType, ActionType>* it);
-
- template <typename LayerType,
- typename LayerList,
- typename RenderSurfaceType,
- typename ActionType>
- void End(
- LayerIterator<LayerType, LayerList, RenderSurfaceType, ActionType>* it);
-
- template <typename LayerType,
- typename LayerList,
- typename RenderSurfaceType,
- typename ActionType>
- void Next(
- LayerIterator<LayerType, LayerList, RenderSurfaceType, ActionType>* it);
-
- private:
- int highest_target_render_surface_layer_;
- };
-
// Walks layers sorted by z-order from front to back
class CC_EXPORT FrontToBack {
public:
diff --git a/chromium/cc/layers/layer_iterator_unittest.cc b/chromium/cc/layers/layer_iterator_unittest.cc
index c2ab71b3f92..c781d28b13f 100644
--- a/chromium/cc/layers/layer_iterator_unittest.cc
+++ b/chromium/cc/layers/layer_iterator_unittest.cc
@@ -54,10 +54,6 @@ typedef LayerIterator<Layer,
RenderSurfaceLayerList,
RenderSurface,
LayerIteratorActions::FrontToBack> FrontToBack;
-typedef LayerIterator<Layer,
- RenderSurfaceLayerList,
- RenderSurface,
- LayerIteratorActions::BackToFront> BackToFront;
void ResetCounts(RenderSurfaceLayerList* render_surface_layer_list) {
for (unsigned surface_index = 0;
@@ -101,27 +97,9 @@ void IterateFrontToBack(
}
}
-void IterateBackToFront(
- RenderSurfaceLayerList* render_surface_layer_list) {
- ResetCounts(render_surface_layer_list);
- int count = 0;
- for (BackToFront it = BackToFront::Begin(render_surface_layer_list);
- it != BackToFront::End(render_surface_layer_list);
- ++it, ++count) {
- TestLayer* layer = static_cast<TestLayer*>(*it);
- if (it.represents_target_render_surface())
- layer->count_representing_target_surface_ = count;
- if (it.represents_contributing_render_surface())
- layer->count_representing_contributing_surface_ = count;
- if (it.represents_itself())
- layer->count_representing_itself_ = count;
- }
-}
-
TEST(LayerIteratorTest, EmptyTree) {
RenderSurfaceLayerList render_surface_layer_list;
- IterateBackToFront(&render_surface_layer_list);
IterateFrontToBack(&render_surface_layer_list);
}
@@ -145,13 +123,6 @@ TEST(LayerIteratorTest, SimpleTree) {
root_layer.get(), root_layer->bounds(), &render_surface_layer_list);
LayerTreeHostCommon::CalculateDrawProperties(&inputs);
- IterateBackToFront(&render_surface_layer_list);
- EXPECT_COUNT(root_layer, 0, -1, 1);
- EXPECT_COUNT(first, -1, -1, 2);
- EXPECT_COUNT(second, -1, -1, 3);
- EXPECT_COUNT(third, -1, -1, 4);
- EXPECT_COUNT(fourth, -1, -1, 5);
-
IterateFrontToBack(&render_surface_layer_list);
EXPECT_COUNT(root_layer, 5, -1, 4);
EXPECT_COUNT(first, -1, -1, 3);
@@ -188,17 +159,6 @@ TEST(LayerIteratorTest, ComplexTree) {
root_layer.get(), root_layer->bounds(), &render_surface_layer_list);
LayerTreeHostCommon::CalculateDrawProperties(&inputs);
- IterateBackToFront(&render_surface_layer_list);
- EXPECT_COUNT(root_layer, 0, -1, 1);
- EXPECT_COUNT(root1, -1, -1, 2);
- EXPECT_COUNT(root2, -1, -1, 3);
- EXPECT_COUNT(root21, -1, -1, 4);
- EXPECT_COUNT(root22, -1, -1, 5);
- EXPECT_COUNT(root221, -1, -1, 6);
- EXPECT_COUNT(root23, -1, -1, 7);
- EXPECT_COUNT(root231, -1, -1, 8);
- EXPECT_COUNT(root3, -1, -1, 9);
-
IterateFrontToBack(&render_surface_layer_list);
EXPECT_COUNT(root_layer, 9, -1, 8);
EXPECT_COUNT(root1, -1, -1, 7);
@@ -244,17 +204,6 @@ TEST(LayerIteratorTest, ComplexTreeMultiSurface) {
root_layer.get(), root_layer->bounds(), &render_surface_layer_list);
LayerTreeHostCommon::CalculateDrawProperties(&inputs);
- IterateBackToFront(&render_surface_layer_list);
- EXPECT_COUNT(root_layer, 0, -1, 1);
- EXPECT_COUNT(root1, -1, -1, 2);
- EXPECT_COUNT(root2, 4, 3, -1);
- EXPECT_COUNT(root21, -1, -1, 5);
- EXPECT_COUNT(root22, 7, 6, 8);
- EXPECT_COUNT(root221, -1, -1, 9);
- EXPECT_COUNT(root23, 11, 10, 12);
- EXPECT_COUNT(root231, -1, -1, 13);
- EXPECT_COUNT(root3, -1, -1, 14);
-
IterateFrontToBack(&render_surface_layer_list);
EXPECT_COUNT(root_layer, 14, -1, 13);
EXPECT_COUNT(root1, -1, -1, 12);
diff --git a/chromium/cc/layers/layer_lists.cc b/chromium/cc/layers/layer_lists.cc
index 89cd4985701..fda1a1cf9f8 100644
--- a/chromium/cc/layers/layer_lists.cc
+++ b/chromium/cc/layers/layer_lists.cc
@@ -35,6 +35,13 @@ 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();
}
diff --git a/chromium/cc/layers/layer_lists.h b/chromium/cc/layers/layer_lists.h
index 24a9c3c14d6..01a7966888f 100644
--- a/chromium/cc/layers/layer_lists.h
+++ b/chromium/cc/layers/layer_lists.h
@@ -31,6 +31,8 @@ class CC_EXPORT RenderSurfaceLayerList {
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;
diff --git a/chromium/cc/layers/layer_perftest.cc b/chromium/cc/layers/layer_perftest.cc
new file mode 100644
index 00000000000..5a2de60d203
--- /dev/null
+++ b/chromium/cc/layers/layer_perftest.cc
@@ -0,0 +1,120 @@
+// 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.h"
+
+#include "cc/resources/layer_painter.h"
+#include "cc/test/fake_impl_proxy.h"
+#include "cc/test/fake_layer_tree_host.h"
+#include "cc/test/fake_layer_tree_host_client.h"
+#include "cc/test/fake_layer_tree_host_impl.h"
+#include "cc/test/lap_timer.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/perf/perf_test.h"
+
+namespace cc {
+namespace {
+
+static const int kTimeLimitMillis = 3000;
+static const int kWarmupRuns = 5;
+static const int kTimeCheckInterval = 10;
+
+class MockLayerPainter : public LayerPainter {
+ public:
+ virtual void Paint(SkCanvas* canvas,
+ gfx::Rect content_rect,
+ gfx::RectF* opaque) OVERRIDE {}
+};
+
+
+class LayerPerfTest : public testing::Test {
+ public:
+ LayerPerfTest()
+ : host_impl_(&proxy_),
+ fake_client_(FakeLayerTreeHostClient::DIRECT_3D),
+ timer_(kWarmupRuns,
+ base::TimeDelta::FromMilliseconds(kTimeLimitMillis),
+ kTimeCheckInterval) {}
+
+ protected:
+ virtual void SetUp() OVERRIDE {
+ layer_tree_host_ = FakeLayerTreeHost::Create();
+ layer_tree_host_->InitializeSingleThreaded(&fake_client_);
+ }
+
+ virtual void TearDown() OVERRIDE {
+ layer_tree_host_->SetRootLayer(NULL);
+ layer_tree_host_.reset();
+ }
+
+ FakeImplProxy proxy_;
+ FakeLayerTreeHostImpl host_impl_;
+
+ FakeLayerTreeHostClient fake_client_;
+ scoped_ptr<FakeLayerTreeHost> layer_tree_host_;
+ LapTimer timer_;
+};
+
+TEST_F(LayerPerfTest, PushPropertiesTo) {
+ scoped_refptr<Layer> test_layer = Layer::Create();
+ scoped_ptr<LayerImpl> impl_layer =
+ LayerImpl::Create(host_impl_.active_tree(), 1);
+
+ layer_tree_host_->SetRootLayer(test_layer);
+
+ float anchor_point_z = 0;
+ bool scrollable = true;
+ bool contents_opaque = true;
+ bool double_sided = true;
+ bool hide_layer_and_subtree = true;
+ bool masks_to_bounds = true;
+
+ // Properties changed.
+ timer_.Reset();
+ do {
+ test_layer->SetNeedsDisplayRect(gfx::RectF(0.f, 0.f, 5.f, 5.f));
+ test_layer->SetAnchorPointZ(anchor_point_z);
+ test_layer->SetContentsOpaque(contents_opaque);
+ test_layer->SetDoubleSided(double_sided);
+ test_layer->SetHideLayerAndSubtree(hide_layer_and_subtree);
+ test_layer->SetMasksToBounds(masks_to_bounds);
+ test_layer->SetScrollable(scrollable);
+ test_layer->PushPropertiesTo(impl_layer.get());
+
+ anchor_point_z += 0.01f;
+ scrollable = !scrollable;
+ contents_opaque = !contents_opaque;
+ double_sided = !double_sided;
+ hide_layer_and_subtree = !hide_layer_and_subtree;
+ masks_to_bounds = !masks_to_bounds;
+
+ timer_.NextLap();
+ } while (!timer_.HasTimeLimitExpired());
+
+ perf_test::PrintResult("push_properties_to",
+ "",
+ "props_changed",
+ timer_.LapsPerSecond(),
+ "runs/s",
+ true);
+
+ // Properties didn't change.
+ timer_.Reset();
+ do {
+ test_layer->PushPropertiesTo(impl_layer.get());
+ timer_.NextLap();
+ } while (!timer_.HasTimeLimitExpired());
+
+ perf_test::PrintResult("push_properties_to",
+ "",
+ "props_didnt_change",
+ timer_.LapsPerSecond(),
+ "runs/s",
+ true);
+}
+
+
+} // namespace
+} // namespace cc
diff --git a/chromium/cc/layers/layer_position_constraint_unittest.cc b/chromium/cc/layers/layer_position_constraint_unittest.cc
index 6384ba45327..8f6dcb11798 100644
--- a/chromium/cc/layers/layer_position_constraint_unittest.cc
+++ b/chromium/cc/layers/layer_position_constraint_unittest.cc
@@ -1094,5 +1094,120 @@ TEST_F(LayerPositionConstraintTest,
grand_child->draw_transform());
}
+TEST_F(LayerPositionConstraintTest,
+ ScrollCompensationForFixedWithinFixedWithSameContainer) {
+ // This test checks scroll compensation for a fixed-position layer that is
+ // inside of another fixed-position layer and both share the same container.
+ // In this situation, the parent fixed-position layer will receive
+ // the scroll compensation, and the child fixed-position layer does not
+ // need to compensate further.
+
+ LayerImpl* child = root_->children()[0];
+ LayerImpl* grand_child = child->children()[0];
+ LayerImpl* great_grand_child = grand_child->children()[0];
+
+ child->SetIsContainerForFixedPositionLayers(true);
+ grand_child->SetPositionConstraint(fixed_to_top_left_);
+
+ // Note carefully - great_grand_child is fixed to bottom right, to test
+ // sizeDelta being applied correctly; the compensation skips the grand_child
+ // because it is fixed to top left.
+ great_grand_child->SetPositionConstraint(fixed_to_bottom_right_);
+
+ // Case 1: scrollDelta
+ child->SetScrollDelta(gfx::Vector2d(10, 10));
+ ExecuteCalculateDrawProperties(root_.get());
+
+ // Here the child is affected by scroll delta, but the fixed position
+ // grand_child should not be affected.
+ gfx::Transform expected_child_transform;
+ expected_child_transform.Translate(-10.0, -10.0);
+
+ gfx::Transform expected_grand_child_transform;
+ gfx::Transform expected_great_grand_child_transform;
+
+ EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
+ child->draw_transform());
+ EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
+ grand_child->draw_transform());
+ EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
+ great_grand_child->draw_transform());
+
+ // Case 2: sizeDelta
+ child->SetScrollDelta(gfx::Vector2d(0, 0));
+ child->SetFixedContainerSizeDelta(gfx::Vector2d(20, 20));
+ ExecuteCalculateDrawProperties(root_.get());
+
+ expected_child_transform.MakeIdentity();
+
+ expected_grand_child_transform.MakeIdentity();
+
+ // Fixed to bottom-right, size-delta compensation is applied.
+ expected_great_grand_child_transform.MakeIdentity();
+ expected_great_grand_child_transform.Translate(20.0, 20.0);
+
+ EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
+ child->draw_transform());
+ EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
+ grand_child->draw_transform());
+ EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
+ great_grand_child->draw_transform());
+}
+
+TEST_F(LayerPositionConstraintTest,
+ ScrollCompensationForFixedWithinFixedWithInterveningContainer) {
+ // This test checks scroll compensation for a fixed-position layer that is
+ // inside of another fixed-position layer, but they have different fixed
+ // position containers. In this situation, the child fixed-position element
+ // would still have to compensate with respect to its container.
+
+ LayerImpl* container1 = root_->children()[0];
+ LayerImpl* fixed_to_container1 = container1->children()[0];
+ LayerImpl* container2 = fixed_to_container1->children()[0];
+
+ {
+ // Add one more layer to the hierarchy for this test.
+ scoped_ptr<LayerImpl> fixed_to_container2_ptr =
+ LayerImpl::Create(host_impl_.active_tree(), 5);
+ container2->AddChild(fixed_to_container2_ptr.Pass());
+ }
+
+ LayerImpl* fixed_to_container2 = container2->children()[0];
+
+ container1->SetIsContainerForFixedPositionLayers(true);
+ fixed_to_container1->SetPositionConstraint(fixed_to_top_left_);
+ container2->SetIsContainerForFixedPositionLayers(true);
+ fixed_to_container2->SetPositionConstraint(fixed_to_top_left_);
+
+ container1->SetScrollDelta(gfx::Vector2d(0, 15));
+ container2->SetScrollDelta(gfx::Vector2d(30, 0));
+ ExecuteCalculateDrawProperties(root_.get());
+
+ gfx::Transform expected_container1_transform;
+ expected_container1_transform.Translate(0.0, -15.0);
+
+ gfx::Transform expected_fixed_to_container1_transform;
+
+ // Since the container is a descendant of the fixed layer above,
+ // the expected draw transform for container2 would not
+ // include the scrollDelta that was applied to container1.
+ gfx::Transform expected_container2_transform;
+ expected_container2_transform.Translate(-30.0, 0.0);
+
+ gfx::Transform expected_fixed_to_container2_transform;
+
+ EXPECT_TRANSFORMATION_MATRIX_EQ(expected_container1_transform,
+ container1->draw_transform());
+
+ EXPECT_TRANSFORMATION_MATRIX_EQ(expected_fixed_to_container1_transform,
+ fixed_to_container1->draw_transform());
+
+ EXPECT_TRANSFORMATION_MATRIX_EQ(expected_container2_transform,
+ container2->draw_transform());
+
+ EXPECT_TRANSFORMATION_MATRIX_EQ(expected_fixed_to_container2_transform,
+ fixed_to_container2->draw_transform());
+}
+
} // namespace
} // namespace cc
diff --git a/chromium/cc/layers/layer_unittest.cc b/chromium/cc/layers/layer_unittest.cc
index c5c5286d2aa..a77a5fb8819 100644
--- a/chromium/cc/layers/layer_unittest.cc
+++ b/chromium/cc/layers/layer_unittest.cc
@@ -38,9 +38,9 @@ namespace {
class MockLayerTreeHost : public LayerTreeHost {
public:
- explicit MockLayerTreeHost(LayerTreeHostClient* client)
- : LayerTreeHost(client, LayerTreeSettings()) {
- Initialize(NULL);
+ explicit MockLayerTreeHost(FakeLayerTreeHostClient* client)
+ : LayerTreeHost(client, NULL, LayerTreeSettings()) {
+ InitializeSingleThreaded(client);
}
MOCK_METHOD0(SetNeedsCommit, void());
@@ -545,11 +545,14 @@ TEST_F(LayerTest, CheckPropertyChangeCausesCorrectBehavior) {
EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetBackgroundColor(SK_ColorLTGRAY));
EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetMasksToBounds(true));
EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetOpacity(0.5f));
+ EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetBlendMode(SkXfermode::kHue_Mode));
+ EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetIsRootForIsolatedGroup(true));
EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetContentsOpaque(true));
EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetPosition(gfx::PointF(4.f, 9.f)));
EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetSublayerTransform(
gfx::Transform(0.0, 0.0, 0.0, 0.0, 0.0, 0.0)));
EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetScrollable(true));
+ EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetUserScrollable(true, false));
EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetScrollOffset(
gfx::Vector2d(10, 10)));
EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetShouldScrollOnMainThread(true));
@@ -607,7 +610,7 @@ TEST_F(LayerTest, PushPropertiesAccumulatesUpdateRect) {
impl_layer->update_rect());
}
-TEST_F(LayerTest, PushPropertiesCausesSurfacePropertyChangedForTransform) {
+TEST_F(LayerTest, PushPropertiesCausesLayerPropertyChangedForTransform) {
scoped_refptr<Layer> test_layer = Layer::Create();
scoped_ptr<LayerImpl> impl_layer =
LayerImpl::Create(host_impl_.active_tree(), 1);
@@ -619,14 +622,14 @@ TEST_F(LayerTest, PushPropertiesCausesSurfacePropertyChangedForTransform) {
transform.Rotate(45.0);
EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetTransform(transform));
- EXPECT_FALSE(impl_layer->LayerSurfacePropertyChanged());
+ EXPECT_FALSE(impl_layer->LayerPropertyChanged());
test_layer->PushPropertiesTo(impl_layer.get());
- EXPECT_TRUE(impl_layer->LayerSurfacePropertyChanged());
+ EXPECT_TRUE(impl_layer->LayerPropertyChanged());
}
-TEST_F(LayerTest, PushPropertiesCausesSurfacePropertyChangedForOpacity) {
+TEST_F(LayerTest, PushPropertiesCausesLayerPropertyChangedForOpacity) {
scoped_refptr<Layer> test_layer = Layer::Create();
scoped_ptr<LayerImpl> impl_layer =
LayerImpl::Create(host_impl_.active_tree(), 1);
@@ -636,15 +639,15 @@ TEST_F(LayerTest, PushPropertiesCausesSurfacePropertyChangedForOpacity) {
EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetOpacity(0.5f));
- EXPECT_FALSE(impl_layer->LayerSurfacePropertyChanged());
+ EXPECT_FALSE(impl_layer->LayerPropertyChanged());
test_layer->PushPropertiesTo(impl_layer.get());
- EXPECT_TRUE(impl_layer->LayerSurfacePropertyChanged());
+ EXPECT_TRUE(impl_layer->LayerPropertyChanged());
}
TEST_F(LayerTest,
- PushPropsDoesntCauseSurfacePropertyChangedDuringImplOnlyTransformAnim) {
+ PushPropsDoesntCauseLayerPropertyChangedDuringImplOnlyTransformAnim) {
scoped_refptr<Layer> test_layer = Layer::Create();
scoped_ptr<LayerImpl> impl_layer =
LayerImpl::Create(host_impl_.active_tree(), 1);
@@ -665,9 +668,9 @@ TEST_F(LayerTest,
transform.Rotate(45.0);
EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetTransform(transform));
- EXPECT_FALSE(impl_layer->LayerSurfacePropertyChanged());
+ EXPECT_FALSE(impl_layer->LayerPropertyChanged());
test_layer->PushPropertiesTo(impl_layer.get());
- EXPECT_TRUE(impl_layer->LayerSurfacePropertyChanged());
+ EXPECT_TRUE(impl_layer->LayerPropertyChanged());
impl_layer->ResetAllChangeTrackingForSubtree();
AddAnimatedTransformToController(impl_layer->layer_animation_controller(),
@@ -679,13 +682,13 @@ TEST_F(LayerTest,
transform.Rotate(45.0);
EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetTransform(transform));
- EXPECT_FALSE(impl_layer->LayerSurfacePropertyChanged());
+ EXPECT_FALSE(impl_layer->LayerPropertyChanged());
test_layer->PushPropertiesTo(impl_layer.get());
- EXPECT_FALSE(impl_layer->LayerSurfacePropertyChanged());
+ EXPECT_FALSE(impl_layer->LayerPropertyChanged());
}
TEST_F(LayerTest,
- PushPropsDoesntCauseSurfacePropertyChangedDuringImplOnlyOpacityAnim) {
+ PushPropsDoesntCauseLayerPropertyChangedDuringImplOnlyOpacityAnim) {
scoped_refptr<Layer> test_layer = Layer::Create();
scoped_ptr<LayerImpl> impl_layer =
LayerImpl::Create(host_impl_.active_tree(), 1);
@@ -705,9 +708,9 @@ TEST_F(LayerTest,
EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetOpacity(0.5f));
- EXPECT_FALSE(impl_layer->LayerSurfacePropertyChanged());
+ EXPECT_FALSE(impl_layer->LayerPropertyChanged());
test_layer->PushPropertiesTo(impl_layer.get());
- EXPECT_TRUE(impl_layer->LayerSurfacePropertyChanged());
+ EXPECT_TRUE(impl_layer->LayerPropertyChanged());
impl_layer->ResetAllChangeTrackingForSubtree();
AddOpacityTransitionToController(impl_layer->layer_animation_controller(),
@@ -719,11 +722,47 @@ TEST_F(LayerTest,
set_is_impl_only(true);
EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetOpacity(0.75f));
- EXPECT_FALSE(impl_layer->LayerSurfacePropertyChanged());
+ EXPECT_FALSE(impl_layer->LayerPropertyChanged());
test_layer->PushPropertiesTo(impl_layer.get());
- EXPECT_FALSE(impl_layer->LayerSurfacePropertyChanged());
+ EXPECT_FALSE(impl_layer->LayerPropertyChanged());
}
+TEST_F(LayerTest,
+ PushPropsDoesntCauseLayerPropertyChangedDuringImplOnlyFilterAnim) {
+ scoped_refptr<Layer> test_layer = Layer::Create();
+ scoped_ptr<LayerImpl> impl_layer =
+ LayerImpl::Create(host_impl_.active_tree(), 1);
+
+ EXPECT_SET_NEEDS_FULL_TREE_SYNC(1,
+ layer_tree_host_->SetRootLayer(test_layer));
+
+ scoped_ptr<AnimationRegistrar> registrar = AnimationRegistrar::Create();
+ impl_layer->layer_animation_controller()->SetAnimationRegistrar(
+ registrar.get());
+
+ AddAnimatedFilterToController(
+ impl_layer->layer_animation_controller(), 1.0, 1.f, 2.f);
+
+ FilterOperations filters;
+ filters.Append(FilterOperation::CreateBlurFilter(2.f));
+ EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetFilters(filters));
+
+ EXPECT_FALSE(impl_layer->LayerPropertyChanged());
+ test_layer->PushPropertiesTo(impl_layer.get());
+ EXPECT_TRUE(impl_layer->LayerPropertyChanged());
+
+ impl_layer->ResetAllChangeTrackingForSubtree();
+ AddAnimatedFilterToController(
+ impl_layer->layer_animation_controller(), 1.0, 1.f, 2.f);
+ impl_layer->layer_animation_controller()->GetAnimation(Animation::Filter)->
+ set_is_impl_only(true);
+ filters.Append(FilterOperation::CreateSepiaFilter(0.5f));
+ EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetFilters(filters));
+
+ EXPECT_FALSE(impl_layer->LayerPropertyChanged());
+ test_layer->PushPropertiesTo(impl_layer.get());
+ EXPECT_FALSE(impl_layer->LayerPropertyChanged());
+}
TEST_F(LayerTest, MaskAndReplicaHasParent) {
scoped_refptr<Layer> parent = Layer::Create();
@@ -766,11 +805,17 @@ class LayerTreeHostFactory {
: client_(FakeLayerTreeHostClient::DIRECT_3D) {}
scoped_ptr<LayerTreeHost> Create() {
- return LayerTreeHost::Create(&client_, LayerTreeSettings(), NULL).Pass();
+ return LayerTreeHost::CreateSingleThreaded(&client_,
+ &client_,
+ NULL,
+ LayerTreeSettings()).Pass();
}
scoped_ptr<LayerTreeHost> Create(LayerTreeSettings settings) {
- return LayerTreeHost::Create(&client_, settings, NULL).Pass();
+ return LayerTreeHost::CreateSingleThreaded(&client_,
+ &client_,
+ NULL,
+ settings).Pass();
}
private:
diff --git a/chromium/cc/layers/nine_patch_layer.cc b/chromium/cc/layers/nine_patch_layer.cc
index 5e000072f28..f6761318cd8 100644
--- a/chromium/cc/layers/nine_patch_layer.cc
+++ b/chromium/cc/layers/nine_patch_layer.cc
@@ -14,44 +14,6 @@
namespace cc {
-
-namespace {
-
-class ScopedUIResourceHolder : public NinePatchLayer::UIResourceHolder {
- public:
- static scoped_ptr<ScopedUIResourceHolder> Create(LayerTreeHost* host,
- const SkBitmap& skbitmap) {
- return make_scoped_ptr(new ScopedUIResourceHolder(host, skbitmap));
- }
- virtual UIResourceId id() OVERRIDE { return resource_->id(); }
-
- private:
- ScopedUIResourceHolder(LayerTreeHost* host, const SkBitmap& skbitmap) {
- resource_ = ScopedUIResource::Create(host, UIResourceBitmap(skbitmap));
- }
-
- scoped_ptr<ScopedUIResource> resource_;
-};
-
-class SharedUIResourceHolder : public NinePatchLayer::UIResourceHolder {
- public:
- static scoped_ptr<SharedUIResourceHolder> Create(UIResourceId id) {
- return make_scoped_ptr(new SharedUIResourceHolder(id));
- }
-
- virtual UIResourceId id() OVERRIDE { return id_; }
-
- private:
- explicit SharedUIResourceHolder(UIResourceId id) : id_(id) {}
-
- UIResourceId id_;
-};
-
-} // anonymous namespace
-
-
-NinePatchLayer::UIResourceHolder::~UIResourceHolder() {}
-
scoped_refptr<NinePatchLayer> NinePatchLayer::Create() {
return make_scoped_refptr(new NinePatchLayer());
}
@@ -65,25 +27,6 @@ scoped_ptr<LayerImpl> NinePatchLayer::CreateLayerImpl(
return NinePatchLayerImpl::Create(tree_impl, id()).PassAs<LayerImpl>();
}
-void NinePatchLayer::SetLayerTreeHost(LayerTreeHost* host) {
- if (host == layer_tree_host())
- return;
-
- Layer::SetLayerTreeHost(host);
-
- // Recreate the resource hold against the new LTH.
- RecreateUIResourceHolder();
-}
-
-void NinePatchLayer::RecreateUIResourceHolder() {
- ui_resource_holder_.reset();
- if (!layer_tree_host() || bitmap_.empty())
- return;
-
- ui_resource_holder_ =
- ScopedUIResourceHolder::Create(layer_tree_host(), bitmap_);
-}
-
void NinePatchLayer::SetBorder(gfx::Rect border) {
if (border == border_)
return;
@@ -91,34 +34,11 @@ void NinePatchLayer::SetBorder(gfx::Rect border) {
SetNeedsCommit();
}
-void NinePatchLayer::SetBitmap(const SkBitmap& skbitmap, gfx::Rect aperture) {
- image_aperture_ = aperture;
- bitmap_ = skbitmap;
-
- // TODO(ccameron): Remove this. This provides the default border that was
- // provided before borders were required to be explicitly provided. Once Blink
- // fixes its callers to call SetBorder, this can be removed.
- SetBorder(gfx::Rect(aperture.x(),
- aperture.y(),
- skbitmap.width() - aperture.width(),
- skbitmap.height() - aperture.height()));
- RecreateUIResourceHolder();
- SetNeedsCommit();
-}
-
-void NinePatchLayer::SetUIResourceId(UIResourceId resource_id,
- gfx::Rect aperture) {
- if (ui_resource_holder_ && ui_resource_holder_->id() == resource_id &&
- image_aperture_ == aperture)
+void NinePatchLayer::SetAperture(gfx::Rect aperture) {
+ if (image_aperture_ == aperture)
return;
image_aperture_ = aperture;
- if (resource_id) {
- ui_resource_holder_ = SharedUIResourceHolder::Create(resource_id);
- } else {
- ui_resource_holder_.reset();
- }
-
SetNeedsCommit();
}
@@ -130,13 +50,8 @@ void NinePatchLayer::SetFillCenter(bool fill_center) {
SetNeedsCommit();
}
-bool NinePatchLayer::DrawsContent() const {
- return ui_resource_holder_ && ui_resource_holder_->id() &&
- Layer::DrawsContent();
-}
-
void NinePatchLayer::PushPropertiesTo(LayerImpl* layer) {
- Layer::PushPropertiesTo(layer);
+ UIResourceLayer::PushPropertiesTo(layer);
NinePatchLayerImpl* layer_impl = static_cast<NinePatchLayerImpl*>(layer);
if (!ui_resource_holder_) {
@@ -144,10 +59,7 @@ void NinePatchLayer::PushPropertiesTo(LayerImpl* layer) {
} else {
DCHECK(layer_tree_host());
- gfx::Size image_size =
- layer_tree_host()->GetUIResourceSize(ui_resource_holder_->id());
- layer_impl->SetUIResourceId(ui_resource_holder_->id());
- layer_impl->SetLayout(image_size, image_aperture_, border_, fill_center_);
+ layer_impl->SetLayout(image_aperture_, border_, fill_center_);
}
}
diff --git a/chromium/cc/layers/nine_patch_layer.h b/chromium/cc/layers/nine_patch_layer.h
index 5880635389a..dc9f81f6e18 100644
--- a/chromium/cc/layers/nine_patch_layer.h
+++ b/chromium/cc/layers/nine_patch_layer.h
@@ -8,6 +8,7 @@
#include "base/memory/scoped_ptr.h"
#include "cc/base/cc_export.h"
#include "cc/layers/layer.h"
+#include "cc/layers/ui_resource_layer.h"
#include "cc/resources/ui_resource_client.h"
#include "ui/gfx/rect.h"
@@ -16,16 +17,12 @@ namespace cc {
class LayerTreeHost;
class ScopedUIResource;
-class CC_EXPORT NinePatchLayer : public Layer {
+class CC_EXPORT NinePatchLayer : public UIResourceLayer {
public:
static scoped_refptr<NinePatchLayer> Create();
- virtual bool DrawsContent() const OVERRIDE;
-
virtual void PushPropertiesTo(LayerImpl* layer) OVERRIDE;
- virtual void SetLayerTreeHost(LayerTreeHost* host) OVERRIDE;
-
// |border| is the space around the center rectangular region in layer space
// (known as aperture in image space). |border.x()| and |border.y()| are the
// size of the left and top boundary, respectively.
@@ -39,29 +36,17 @@ class CC_EXPORT NinePatchLayer : public Layer {
// on the edges of the layer. The corners are unscaled, the top and bottom
// rects are x-stretched to fit, and the left and right rects are
// y-stretched to fit.
- void SetBitmap(const SkBitmap& skbitmap, gfx::Rect aperture);
-
- // An alternative way of setting the resource to allow for sharing.
- void SetUIResourceId(UIResourceId resource_id, gfx::Rect aperture);
+ void SetAperture(gfx::Rect aperture);
void SetFillCenter(bool fill_center);
- class UIResourceHolder {
- public:
- virtual UIResourceId id() = 0;
- virtual ~UIResourceHolder();
- };
-
private:
NinePatchLayer();
virtual ~NinePatchLayer();
virtual scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl)
OVERRIDE;
- void RecreateUIResourceHolder();
gfx::Rect border_;
bool fill_center_;
- scoped_ptr<UIResourceHolder> ui_resource_holder_;
- SkBitmap bitmap_;
// The transparent center region that shows the parent layer's contents in
// image space.
diff --git a/chromium/cc/layers/nine_patch_layer_impl.cc b/chromium/cc/layers/nine_patch_layer_impl.cc
index f609c3d2fda..2987179ae2e 100644
--- a/chromium/cc/layers/nine_patch_layer_impl.cc
+++ b/chromium/cc/layers/nine_patch_layer_impl.cc
@@ -15,27 +15,21 @@
namespace cc {
NinePatchLayerImpl::NinePatchLayerImpl(LayerTreeImpl* tree_impl, int id)
- : LayerImpl(tree_impl, id),
- fill_center_(false),
- ui_resource_id_(0) {}
+ : UIResourceLayerImpl(tree_impl, id),
+ fill_center_(false) {}
NinePatchLayerImpl::~NinePatchLayerImpl() {}
-ResourceProvider::ResourceId NinePatchLayerImpl::ContentsResourceId() const {
- return 0;
-}
-
scoped_ptr<LayerImpl> NinePatchLayerImpl::CreateLayerImpl(
LayerTreeImpl* tree_impl) {
return NinePatchLayerImpl::Create(tree_impl, id()).PassAs<LayerImpl>();
}
void NinePatchLayerImpl::PushPropertiesTo(LayerImpl* layer) {
- LayerImpl::PushPropertiesTo(layer);
+ UIResourceLayerImpl::PushPropertiesTo(layer);
NinePatchLayerImpl* layer_impl = static_cast<NinePatchLayerImpl*>(layer);
- layer_impl->SetUIResourceId(ui_resource_id_);
- layer_impl->SetLayout(image_bounds_, image_aperture_, border_, fill_center_);
+ layer_impl->SetLayout(image_aperture_, border_, fill_center_);
}
static gfx::RectF NormalizedRect(float x,
@@ -50,70 +44,57 @@ static gfx::RectF NormalizedRect(float x,
height / total_height);
}
-void NinePatchLayerImpl::SetUIResourceId(UIResourceId uid) {
- if (uid == ui_resource_id_)
- return;
- ui_resource_id_ = uid;
- NoteLayerPropertyChanged();
-}
-
-void NinePatchLayerImpl::SetLayout(gfx::Size image_bounds,
- gfx::Rect aperture,
+void NinePatchLayerImpl::SetLayout(gfx::Rect aperture,
gfx::Rect border,
bool fill_center) {
// This check imposes an ordering on the call sequence. An UIResource must
// exist before SetLayout can be called.
DCHECK(ui_resource_id_);
+ if (image_aperture_ == aperture &&
+ border_ == border && fill_center_ == fill_center)
+ return;
+
+ image_aperture_ = aperture;
+ border_ = border;
+ fill_center_ = fill_center;
+
+ NoteLayerPropertyChanged();
+}
+
+void NinePatchLayerImpl::CheckGeometryLimitations() {
// TODO(ccameron): the following "greater than or equal to" (GE) checks should
// be greater than (GT) to avoid degenerate nine-patches. The relaxed
// condition "equal to" is a workaround for the overhang shadow use case and
// should be investigated further.
// |border| is in layer space. It cannot exceed the bounds of the layer.
- DCHECK(!border.size().IsEmpty());
- DCHECK_GE(bounds().width(), border.width());
- DCHECK_GE(bounds().height(), border.height());
+ DCHECK(!border_.size().IsEmpty());
+ DCHECK_GE(bounds().width(), border_.width());
+ DCHECK_GE(bounds().height(), border_.height());
// Sanity Check on |border|
- DCHECK_LT(border.x(), border.width());
- DCHECK_LT(border.y(), border.height());
- DCHECK_GE(border.x(), 0);
- DCHECK_GE(border.y(), 0);
+ DCHECK_LT(border_.x(), border_.width());
+ DCHECK_LT(border_.y(), border_.height());
+ DCHECK_GE(border_.x(), 0);
+ DCHECK_GE(border_.y(), 0);
// |aperture| is in image space. It cannot exceed the bounds of the bitmap.
- DCHECK(!aperture.size().IsEmpty());
- DCHECK(gfx::Rect(image_bounds.width(), image_bounds.height())
- .Contains(aperture));
+ DCHECK(!image_aperture_.size().IsEmpty());
+ DCHECK(gfx::Rect(image_bounds_.width(), image_bounds_.height())
+ .Contains(image_aperture_));
// Avoid the degenerate cases where the aperture touches the edge of the
// image.
- DCHECK_LT(aperture.width(), image_bounds.width() - 1);
- DCHECK_LT(aperture.height(), image_bounds.height() - 1);
- DCHECK_GT(aperture.x(), 0);
- DCHECK_GT(aperture.y(), 0);
-
- if (image_bounds_ == image_bounds && image_aperture_ == aperture &&
- border_ == border && fill_center_ == fill_center)
- return;
-
- image_bounds_ = image_bounds;
- image_aperture_ = aperture;
- border_ = border;
- fill_center_ = fill_center;
-
- NoteLayerPropertyChanged();
-}
-
-bool NinePatchLayerImpl::WillDraw(DrawMode draw_mode,
- ResourceProvider* resource_provider) {
- if (!ui_resource_id_ || draw_mode == DRAW_MODE_RESOURCELESS_SOFTWARE)
- return false;
- return LayerImpl::WillDraw(draw_mode, resource_provider);
+ DCHECK_LT(image_aperture_.width(), image_bounds_.width() - 1);
+ DCHECK_LT(image_aperture_.height(), image_bounds_.height() - 1);
+ DCHECK_GT(image_aperture_.x(), 0);
+ DCHECK_GT(image_aperture_.y(), 0);
}
void NinePatchLayerImpl::AppendQuads(QuadSink* quad_sink,
AppendQuadsData* append_quads_data) {
+ CheckGeometryLimitations();
SharedQuadState* shared_quad_state =
quad_sink->UseSharedQuadState(CreateSharedQuadState());
AppendDebugBorderQuad(quad_sink, shared_quad_state, append_quads_data);
@@ -373,7 +354,11 @@ base::DictionaryValue* NinePatchLayerImpl::LayerTreeAsJson() const {
list->AppendInteger(image_aperture_.size().height());
result->Set("ImageAperture", list);
- result->Set("ImageBounds", MathUtil::AsValue(image_bounds_).release());
+ list = new base::ListValue;
+ list->AppendInteger(image_bounds_.width());
+ list->AppendInteger(image_bounds_.height());
+ result->Set("ImageBounds", list);
+
result->Set("Border", MathUtil::AsValue(border_).release());
base::FundamentalValue* fill_center =
diff --git a/chromium/cc/layers/nine_patch_layer_impl.h b/chromium/cc/layers/nine_patch_layer_impl.h
index ba414aed391..d85e40f3049 100644
--- a/chromium/cc/layers/nine_patch_layer_impl.h
+++ b/chromium/cc/layers/nine_patch_layer_impl.h
@@ -9,6 +9,7 @@
#include "cc/base/cc_export.h"
#include "cc/layers/layer_impl.h"
+#include "cc/layers/ui_resource_layer_impl.h"
#include "cc/resources/resource_provider.h"
#include "cc/resources/ui_resource_client.h"
#include "ui/gfx/rect.h"
@@ -20,7 +21,7 @@ class DictionaryValue;
namespace cc {
-class CC_EXPORT NinePatchLayerImpl : public LayerImpl {
+class CC_EXPORT NinePatchLayerImpl : public UIResourceLayerImpl {
public:
static scoped_ptr<NinePatchLayerImpl> Create(LayerTreeImpl* tree_impl,
int id) {
@@ -28,9 +29,6 @@ class CC_EXPORT NinePatchLayerImpl : public LayerImpl {
}
virtual ~NinePatchLayerImpl();
-
- void SetUIResourceId(UIResourceId uid);
-
// The bitmap stretches out the bounds of the layer. The following picture
// illustrates the parameters associated with the dimensions.
//
@@ -55,8 +53,7 @@ class CC_EXPORT NinePatchLayerImpl : public LayerImpl {
// |image_aperture| = (X, Y, P, Q)
// |border| = (A, C, A + B, C + D)
// |fill_center| indicates whether to draw the center quad or not.
- void SetLayout(gfx::Size image_bounds,
- gfx::Rect image_aperture,
+ void SetLayout(gfx::Rect image_aperture,
gfx::Rect border,
bool fill_center);
@@ -64,11 +61,8 @@ class CC_EXPORT NinePatchLayerImpl : public LayerImpl {
OVERRIDE;
virtual void PushPropertiesTo(LayerImpl* layer) OVERRIDE;
- virtual bool WillDraw(DrawMode draw_mode,
- ResourceProvider* resource_provider) OVERRIDE;
virtual void AppendQuads(QuadSink* quad_sink,
AppendQuadsData* append_quads_data) OVERRIDE;
- virtual ResourceProvider::ResourceId ContentsResourceId() const OVERRIDE;
virtual base::DictionaryValue* LayerTreeAsJson() const OVERRIDE;
@@ -78,8 +72,7 @@ class CC_EXPORT NinePatchLayerImpl : public LayerImpl {
private:
virtual const char* LayerTypeAsString() const OVERRIDE;
- // The size of the NinePatch bitmap in pixels.
- gfx::Size image_bounds_;
+ void CheckGeometryLimitations();
// The transparent center region that shows the parent layer's contents in
// image space.
@@ -90,8 +83,6 @@ class CC_EXPORT NinePatchLayerImpl : public LayerImpl {
bool fill_center_;
- UIResourceId ui_resource_id_;
-
DISALLOW_COPY_AND_ASSIGN(NinePatchLayerImpl);
};
diff --git a/chromium/cc/layers/nine_patch_layer_impl_unittest.cc b/chromium/cc/layers/nine_patch_layer_impl_unittest.cc
index 0fbc645be1b..60201110a25 100644
--- a/chromium/cc/layers/nine_patch_layer_impl_unittest.cc
+++ b/chromium/cc/layers/nine_patch_layer_impl_unittest.cc
@@ -9,7 +9,7 @@
#include "cc/resources/ui_resource_bitmap.h"
#include "cc/resources/ui_resource_client.h"
#include "cc/test/fake_impl_proxy.h"
-#include "cc/test/fake_layer_tree_host_impl.h"
+#include "cc/test/fake_ui_resource_layer_tree_host_impl.h"
#include "cc/test/geometry_test_utils.h"
#include "cc/test/layer_test_common.h"
#include "cc/test/mock_quad_culler.h"
@@ -23,40 +23,6 @@
namespace cc {
namespace {
-class FakeUIResourceLayerTreeHostImpl : public FakeLayerTreeHostImpl {
- public:
- explicit FakeUIResourceLayerTreeHostImpl(Proxy* proxy)
- : FakeLayerTreeHostImpl(proxy), fake_next_resource_id_(1) {}
-
- virtual void CreateUIResource(
- UIResourceId uid,
- const UIResourceBitmap& bitmap) OVERRIDE {
- if (ResourceIdForUIResource(uid))
- DeleteUIResource(uid);
- fake_ui_resource_map_[uid] = fake_next_resource_id_;
- }
-
- virtual void DeleteUIResource(UIResourceId uid) OVERRIDE {
- ResourceProvider::ResourceId id = ResourceIdForUIResource(uid);
- if (id)
- fake_ui_resource_map_.erase(uid);
- }
-
- virtual ResourceProvider::ResourceId ResourceIdForUIResource(
- UIResourceId uid) const OVERRIDE {
- UIResourceMap::const_iterator iter = fake_ui_resource_map_.find(uid);
- if (iter != fake_ui_resource_map_.end())
- return iter->second;
- return 0;
- }
-
- private:
- ResourceProvider::ResourceId fake_next_resource_id_;
- typedef base::hash_map<UIResourceId, ResourceProvider::ResourceId>
- UIResourceMap;
- UIResourceMap fake_ui_resource_map_;
-};
-
gfx::Rect ToRoundedIntRect(gfx::RectF rect_f) {
return gfx::Rect(gfx::ToRoundedInt(rect_f.x()),
gfx::ToRoundedInt(rect_f.y()),
@@ -97,8 +63,8 @@ void NinePatchLayerLayoutTest(gfx::Size bitmap_size,
host_impl.CreateUIResource(uid, bitmap);
layer->SetUIResourceId(uid);
-
- layer->SetLayout(bitmap_size, aperture_rect, border, fill_center);
+ layer->SetImageBounds(bitmap_size);
+ layer->SetLayout(aperture_rect, border, fill_center);
AppendQuadsData data;
layer->AppendQuads(&quad_culler, &data);
diff --git a/chromium/cc/layers/nine_patch_layer_unittest.cc b/chromium/cc/layers/nine_patch_layer_unittest.cc
index 101146c0077..41da351088e 100644
--- a/chromium/cc/layers/nine_patch_layer_unittest.cc
+++ b/chromium/cc/layers/nine_patch_layer_unittest.cc
@@ -10,6 +10,7 @@
#include "cc/resources/resource_update_queue.h"
#include "cc/resources/scoped_ui_resource.h"
#include "cc/scheduler/texture_uploader.h"
+#include "cc/test/fake_layer_tree_host.h"
#include "cc/test/fake_layer_tree_host_client.h"
#include "cc/test/fake_output_surface.h"
#include "cc/test/fake_output_surface_client.h"
@@ -29,34 +30,24 @@ using ::testing::AnyNumber;
namespace cc {
namespace {
-class MockLayerTreeHost : public LayerTreeHost {
- public:
- explicit MockLayerTreeHost(LayerTreeHostClient* client)
- : LayerTreeHost(client, LayerTreeSettings()) {
- Initialize(NULL);
- }
-};
-
class NinePatchLayerTest : public testing::Test {
public:
NinePatchLayerTest() : fake_client_(FakeLayerTreeHostClient::DIRECT_3D) {}
- cc::Proxy* Proxy() const { return layer_tree_host_->proxy(); }
-
protected:
virtual void SetUp() {
- layer_tree_host_.reset(new MockLayerTreeHost(&fake_client_));
+ layer_tree_host_ = FakeLayerTreeHost::Create();
}
virtual void TearDown() {
Mock::VerifyAndClearExpectations(layer_tree_host_.get());
}
- scoped_ptr<MockLayerTreeHost> layer_tree_host_;
+ scoped_ptr<FakeLayerTreeHost> layer_tree_host_;
FakeLayerTreeHostClient fake_client_;
};
-TEST_F(NinePatchLayerTest, SetBitmap) {
+TEST_F(NinePatchLayerTest, SetLayerProperties) {
scoped_refptr<NinePatchLayer> test_layer = NinePatchLayer::Create();
ASSERT_TRUE(test_layer.get());
test_layer->SetIsDrawable(true);
@@ -66,41 +57,6 @@ TEST_F(NinePatchLayerTest, SetBitmap) {
Mock::VerifyAndClearExpectations(layer_tree_host_.get());
EXPECT_EQ(test_layer->layer_tree_host(), layer_tree_host_.get());
- layer_tree_host_->InitializeOutputSurfaceIfNeeded();
-
- ResourceUpdateQueue queue;
- OcclusionTracker occlusion_tracker(gfx::Rect(), false);
- test_layer->SavePaintProperties();
- test_layer->Update(&queue, &occlusion_tracker);
-
- EXPECT_FALSE(test_layer->DrawsContent());
-
- SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kARGB_8888_Config, 10, 10);
- bitmap.allocPixels();
- bitmap.setImmutable();
-
- gfx::Rect aperture(5, 5, 1, 1);
- bool fill_center = false;
- test_layer->SetBitmap(bitmap, aperture);
- test_layer->SetFillCenter(fill_center);
- test_layer->Update(&queue, &occlusion_tracker);
-
- EXPECT_TRUE(test_layer->DrawsContent());
-}
-
-TEST_F(NinePatchLayerTest, SetUIResourceId) {
- scoped_refptr<NinePatchLayer> test_layer = NinePatchLayer::Create();
- ASSERT_TRUE(test_layer.get());
- test_layer->SetIsDrawable(true);
- test_layer->SetBounds(gfx::Size(100, 100));
-
- layer_tree_host_->SetRootLayer(test_layer);
- Mock::VerifyAndClearExpectations(layer_tree_host_.get());
- EXPECT_EQ(test_layer->layer_tree_host(), layer_tree_host_.get());
-
- layer_tree_host_->InitializeOutputSurfaceIfNeeded();
-
ResourceUpdateQueue queue;
OcclusionTracker occlusion_tracker(gfx::Rect(), false);
test_layer->SavePaintProperties();
@@ -117,7 +73,8 @@ TEST_F(NinePatchLayerTest, SetUIResourceId) {
layer_tree_host_.get(), UIResourceBitmap(bitmap));
gfx::Rect aperture(5, 5, 1, 1);
bool fill_center = true;
- test_layer->SetUIResourceId(resource->id(), aperture);
+ test_layer->SetAperture(aperture);
+ test_layer->SetUIResourceId(resource->id());
test_layer->SetFillCenter(fill_center);
test_layer->Update(&queue, &occlusion_tracker);
diff --git a/chromium/cc/layers/painted_scrollbar_layer.cc b/chromium/cc/layers/painted_scrollbar_layer.cc
index 4272fe688cc..6bb76368c48 100644
--- a/chromium/cc/layers/painted_scrollbar_layer.cc
+++ b/chromium/cc/layers/painted_scrollbar_layer.cc
@@ -39,7 +39,9 @@ PaintedScrollbarLayer::PaintedScrollbarLayer(
: scrollbar_(scrollbar.Pass()),
scroll_layer_id_(scroll_layer_id),
thumb_thickness_(scrollbar_->ThumbThickness()),
- thumb_length_(scrollbar_->ThumbLength()) {
+ thumb_length_(scrollbar_->ThumbLength()),
+ is_overlay_(scrollbar_->IsOverlay()),
+ has_thumb_(scrollbar_->HasThumb()) {
if (!scrollbar_->IsOverlay())
SetShouldScrollOnMainThread(true);
}
@@ -127,10 +129,7 @@ void PaintedScrollbarLayer::PushPropertiesTo(LayerImpl* layer) {
if (thumb_resource_.get())
scrollbar_layer->set_thumb_ui_resource_id(thumb_resource_->id());
- scrollbar_layer->set_is_overlay_scrollbar(scrollbar_->IsOverlay());
-
- // PaintedScrollbarLayer must push properties every frame. crbug.com/259095
- needs_push_properties_ = true;
+ scrollbar_layer->set_is_overlay_scrollbar(is_overlay_);
}
ScrollbarLayerInterface* PaintedScrollbarLayer::ToScrollbarLayer() {
@@ -174,16 +173,18 @@ gfx::Rect PaintedScrollbarLayer::OriginThumbRect() const {
}
void PaintedScrollbarLayer::UpdateThumbAndTrackGeometry() {
- track_rect_ = scrollbar_->TrackRect();
- location_ = scrollbar_->Location();
- if (scrollbar_->HasThumb()) {
- thumb_thickness_ = scrollbar_->ThumbThickness();
- thumb_length_ = scrollbar_->ThumbLength();
+ UpdateProperty(scrollbar_->TrackRect(), &track_rect_);
+ UpdateProperty(scrollbar_->Location(), &location_);
+ UpdateProperty(scrollbar_->IsOverlay(), &is_overlay_);
+ UpdateProperty(scrollbar_->HasThumb(), &has_thumb_);
+ if (has_thumb_) {
+ UpdateProperty(scrollbar_->ThumbThickness(), &thumb_thickness_);
+ UpdateProperty(scrollbar_->ThumbLength(), &thumb_length_);
}
}
bool PaintedScrollbarLayer::Update(ResourceUpdateQueue* queue,
- const OcclusionTracker* occlusion) {
+ const OcclusionTracker* occlusion) {
UpdateThumbAndTrackGeometry();
gfx::Rect scaled_track_rect = ScrollbarLayerRectToContentRect(
@@ -198,15 +199,20 @@ bool PaintedScrollbarLayer::Update(ResourceUpdateQueue* queue,
ContentsScalingLayer::Update(queue, occlusion);
}
+ if (update_rect_.IsEmpty() && track_resource_)
+ return false;
+
track_resource_ = ScopedUIResource::Create(
layer_tree_host(), RasterizeScrollbarPart(scaled_track_rect, TRACK));
- gfx::Rect thumb_rect = OriginThumbRect();
- if (scrollbar_->HasThumb() && !thumb_rect.IsEmpty()) {
+ gfx::Rect thumb_rect = OriginThumbRect();
+ if (has_thumb_ && !thumb_rect.IsEmpty()) {
thumb_resource_ = ScopedUIResource::Create(
layer_tree_host(), RasterizeScrollbarPart(thumb_rect, THUMB));
}
+ // UI resources changed so push properties is needed.
+ SetNeedsPushProperties();
return true;
}
diff --git a/chromium/cc/layers/painted_scrollbar_layer.h b/chromium/cc/layers/painted_scrollbar_layer.h
index e84377d1e5a..606ad69b905 100644
--- a/chromium/cc/layers/painted_scrollbar_layer.h
+++ b/chromium/cc/layers/painted_scrollbar_layer.h
@@ -65,6 +65,13 @@ class CC_EXPORT PaintedScrollbarLayer : public ScrollbarLayerInterface,
gfx::Rect ScrollbarLayerRectToContentRect(gfx::Rect layer_rect) const;
gfx::Rect OriginThumbRect() const;
+ template<typename T> void UpdateProperty(T value, T* prop) {
+ if (*prop == value)
+ return;
+ *prop = value;
+ SetNeedsPushProperties();
+ }
+
int MaxTextureSize();
float ClampScaleToMaxTextureSize(float scale);
@@ -80,6 +87,8 @@ class CC_EXPORT PaintedScrollbarLayer : public ScrollbarLayerInterface,
int thumb_length_;
gfx::Point location_;
gfx::Rect track_rect_;
+ bool is_overlay_;
+ bool has_thumb_;
scoped_ptr<ScopedUIResource> track_resource_;
scoped_ptr<ScopedUIResource> thumb_resource_;
diff --git a/chromium/cc/layers/painted_scrollbar_layer_impl.cc b/chromium/cc/layers/painted_scrollbar_layer_impl.cc
index e38a1a640be..a7fdfa3081d 100644
--- a/chromium/cc/layers/painted_scrollbar_layer_impl.cc
+++ b/chromium/cc/layers/painted_scrollbar_layer_impl.cc
@@ -125,11 +125,6 @@ void PaintedScrollbarLayerImpl::AppendQuads(
}
}
-void PaintedScrollbarLayerImpl::DidLoseOutputSurface() {
- track_ui_resource_id_ = 0;
- thumb_ui_resource_id_ = 0;
-}
-
void PaintedScrollbarLayerImpl::SetThumbThickness(int thumb_thickness) {
if (thumb_thickness_ == thumb_thickness)
return;
diff --git a/chromium/cc/layers/painted_scrollbar_layer_impl.h b/chromium/cc/layers/painted_scrollbar_layer_impl.h
index c9d1f3dc0fc..a094416261f 100644
--- a/chromium/cc/layers/painted_scrollbar_layer_impl.h
+++ b/chromium/cc/layers/painted_scrollbar_layer_impl.h
@@ -33,8 +33,6 @@ class CC_EXPORT PaintedScrollbarLayerImpl : public ScrollbarLayerImplBase {
virtual void AppendQuads(QuadSink* quad_sink,
AppendQuadsData* append_quads_data) OVERRIDE;
- virtual void DidLoseOutputSurface() OVERRIDE;
-
void SetThumbThickness(int thumb_thickness);
void SetThumbLength(int thumb_length);
void SetTrackStart(int track_start);
diff --git a/chromium/cc/layers/picture_image_layer_impl.cc b/chromium/cc/layers/picture_image_layer_impl.cc
index 7ae9de41004..b9a57f2b7b0 100644
--- a/chromium/cc/layers/picture_image_layer_impl.cc
+++ b/chromium/cc/layers/picture_image_layer_impl.cc
@@ -27,6 +27,26 @@ scoped_ptr<LayerImpl> PictureImageLayerImpl::CreateLayerImpl(
return PictureImageLayerImpl::Create(tree_impl, id()).PassAs<LayerImpl>();
}
+void PictureImageLayerImpl::CalculateContentsScale(
+ float ideal_contents_scale,
+ float device_scale_factor,
+ float page_scale_factor,
+ bool animating_transform_to_screen,
+ float* contents_scale_x,
+ float* contents_scale_y,
+ gfx::Size* content_bounds) {
+ // CalculateRasterContentsScale always returns 1.f, so make that the ideal
+ // scale.
+ ideal_contents_scale = 1.f;
+ PictureLayerImpl::CalculateContentsScale(ideal_contents_scale,
+ device_scale_factor,
+ page_scale_factor,
+ animating_transform_to_screen,
+ contents_scale_x,
+ contents_scale_y,
+ content_bounds);
+}
+
void PictureImageLayerImpl::GetDebugBorderProperties(
SkColor* color, float* width) const {
*color = DebugColors::ImageLayerBorderColor();
@@ -38,15 +58,16 @@ bool PictureImageLayerImpl::ShouldAdjustRasterScale(
return false;
}
-void PictureImageLayerImpl::CalculateRasterContentsScale(
- bool animating_transform_to_screen,
- float* raster_contents_scale,
- float* low_res_raster_contents_scale) const {
+void PictureImageLayerImpl::RecalculateRasterScales(
+ bool animating_transform_to_screen) {
+ // Defaults from PictureLayerImpl.
+ PictureLayerImpl::RecalculateRasterScales(animating_transform_to_screen);
+
// Don't scale images during rastering to ensure image quality, save memory
// and avoid frequent re-rastering on change of scale.
- *raster_contents_scale = std::max(1.f, MinimumContentsScale());
+ raster_contents_scale_ = std::max(1.f, MinimumContentsScale());
// We don't need low res tiles.
- *low_res_raster_contents_scale = *raster_contents_scale;
+ low_res_raster_contents_scale_ = raster_contents_scale_;
}
} // namespace cc
diff --git a/chromium/cc/layers/picture_image_layer_impl.h b/chromium/cc/layers/picture_image_layer_impl.h
index 4a2db50f668..0b3b246259d 100644
--- a/chromium/cc/layers/picture_image_layer_impl.h
+++ b/chromium/cc/layers/picture_image_layer_impl.h
@@ -17,22 +17,29 @@ class CC_EXPORT PictureImageLayerImpl : public PictureLayerImpl {
}
virtual ~PictureImageLayerImpl();
+ // LayerImpl overrides.
virtual const char* LayerTypeAsString() const OVERRIDE;
virtual scoped_ptr<LayerImpl> CreateLayerImpl(
LayerTreeImpl* tree_impl) OVERRIDE;
+ virtual void CalculateContentsScale(float ideal_contents_scale,
+ float device_scale_factor,
+ float page_scale_factor,
+ bool animating_transform_to_screen,
+ float* contents_scale_x,
+ float* contents_scale_y,
+ gfx::Size* content_bounds) OVERRIDE;
protected:
PictureImageLayerImpl(LayerTreeImpl* tree_impl, int id);
virtual bool ShouldAdjustRasterScale(
bool animating_transform_to_screen) const OVERRIDE;
- virtual void CalculateRasterContentsScale(
- bool animating_transform_to_screen,
- float* raster_contents_scale,
- float* low_res_raster_contents_scale) const OVERRIDE;
+ virtual void RecalculateRasterScales(
+ bool animating_transform_to_screen) OVERRIDE;
virtual void GetDebugBorderProperties(
SkColor* color, float* width) const OVERRIDE;
+ private:
DISALLOW_COPY_AND_ASSIGN(PictureImageLayerImpl);
};
diff --git a/chromium/cc/layers/picture_image_layer_impl_unittest.cc b/chromium/cc/layers/picture_image_layer_impl_unittest.cc
index 9aae4d6f7d2..2910da1d5e7 100644
--- a/chromium/cc/layers/picture_image_layer_impl_unittest.cc
+++ b/chromium/cc/layers/picture_image_layer_impl_unittest.cc
@@ -4,11 +4,14 @@
#include "cc/layers/picture_image_layer_impl.h"
+#include "cc/layers/append_quads_data.h"
+#include "cc/resources/tile_priority.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_tiling_client.h"
#include "cc/test/impl_side_painting_settings.h"
+#include "cc/test/mock_quad_culler.h"
#include "cc/trees/layer_tree_impl.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -20,6 +23,9 @@ class TestablePictureImageLayerImpl : public PictureImageLayerImpl {
TestablePictureImageLayerImpl(LayerTreeImpl* tree_impl, int id)
: PictureImageLayerImpl(tree_impl, id) {
}
+
+ PictureLayerTilingSet* tilings() { return tilings_.get(); }
+
friend class PictureImageLayerImplTest;
};
@@ -32,9 +38,22 @@ class PictureImageLayerImplTest : public testing::Test {
host_impl_.InitializeRenderer(CreateFakeOutputSurface());
}
- scoped_ptr<TestablePictureImageLayerImpl> CreateLayer(int id) {
+ scoped_ptr<TestablePictureImageLayerImpl> CreateLayer(int id,
+ WhichTree which_tree) {
+ LayerTreeImpl* tree = NULL;
+ switch (which_tree) {
+ case ACTIVE_TREE:
+ tree = host_impl_.active_tree();
+ break;
+ case PENDING_TREE:
+ tree = host_impl_.pending_tree();
+ break;
+ case NUM_TREES:
+ NOTREACHED();
+ break;
+ }
TestablePictureImageLayerImpl* layer =
- new TestablePictureImageLayerImpl(host_impl_.pending_tree(), id);
+ new TestablePictureImageLayerImpl(tree, id);
layer->SetBounds(gfx::Size(100, 200));
layer->tilings_.reset(new PictureLayerTilingSet(&tiling_client_,
layer->bounds()));
@@ -46,14 +65,14 @@ class PictureImageLayerImplTest : public testing::Test {
host_impl_.pending_tree()->UpdateDrawProperties();
}
- private:
+ protected:
FakeImplProxy proxy_;
FakeLayerTreeHostImpl host_impl_;
FakePictureLayerTilingClient tiling_client_;
};
TEST_F(PictureImageLayerImplTest, CalculateContentsScale) {
- scoped_ptr<TestablePictureImageLayerImpl> layer(CreateLayer(1));
+ scoped_ptr<TestablePictureImageLayerImpl> layer(CreateLayer(1, PENDING_TREE));
layer->SetDrawsContent(true);
float contents_scale_x;
@@ -68,7 +87,7 @@ TEST_F(PictureImageLayerImplTest, CalculateContentsScale) {
}
TEST_F(PictureImageLayerImplTest, AreVisibleResourcesReady) {
- scoped_ptr<TestablePictureImageLayerImpl> layer(CreateLayer(1));
+ scoped_ptr<TestablePictureImageLayerImpl> layer(CreateLayer(1, PENDING_TREE));
layer->SetBounds(gfx::Size(100, 200));
layer->SetDrawsContent(true);
@@ -85,5 +104,61 @@ TEST_F(PictureImageLayerImplTest, AreVisibleResourcesReady) {
EXPECT_TRUE(layer->AreVisibleResourcesReady());
}
+TEST_F(PictureImageLayerImplTest, IgnoreIdealContentScale) {
+ scoped_ptr<TestablePictureImageLayerImpl> pending_layer(
+ CreateLayer(1, PENDING_TREE));
+ pending_layer->SetDrawsContent(true);
+
+ // Set PictureLayerImpl::ideal_contents_scale_ to 2.f which is not equal
+ // to the content scale used by PictureImageLayerImpl.
+ const float suggested_ideal_contents_scale = 2.f;
+ const float device_scale_factor = 3.f;
+ const float page_scale_factor = 4.f;
+ const bool animating_transform_to_screen = false;
+ float contents_scale_x;
+ float contents_scale_y;
+ gfx::Size content_bounds;
+ pending_layer->CalculateContentsScale(suggested_ideal_contents_scale,
+ device_scale_factor,
+ page_scale_factor,
+ animating_transform_to_screen,
+ &contents_scale_x,
+ &contents_scale_y,
+ &content_bounds);
+
+ // Push to active layer.
+ host_impl_.ActivatePendingTree();
+ scoped_ptr<TestablePictureImageLayerImpl> active_layer(
+ CreateLayer(1, ACTIVE_TREE));
+ pending_layer->PushPropertiesTo(active_layer.get());
+ active_layer->CalculateContentsScale(suggested_ideal_contents_scale,
+ device_scale_factor,
+ page_scale_factor,
+ animating_transform_to_screen,
+ &contents_scale_x,
+ &contents_scale_y,
+ &content_bounds);
+
+ // Create tile and resource.
+ active_layer->tilings()->tiling_at(0)->CreateAllTilesForTesting();
+ host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting(
+ active_layer->tilings()->tiling_at(0)->AllTilesForTesting(),
+ host_impl_.resource_provider());
+
+ // Draw.
+ active_layer->draw_properties().visible_content_rect =
+ gfx::Rect(active_layer->bounds());
+ MockQuadCuller quad_culler;
+ AppendQuadsData data;
+ active_layer->WillDraw(DRAW_MODE_SOFTWARE, NULL);
+ active_layer->AppendQuads(&quad_culler, &data);
+ active_layer->DidDraw(NULL);
+
+ EXPECT_EQ(DrawQuad::TILED_CONTENT, quad_culler.quad_list()[0]->material);
+
+ // Tiles are ready at correct scale, so should not set had_incomplete_tile.
+ EXPECT_FALSE(data.had_incomplete_tile);
+}
+
} // namespace
} // namespace cc
diff --git a/chromium/cc/layers/picture_layer.cc b/chromium/cc/layers/picture_layer.cc
index 4226f1ba713..1415c8075c5 100644
--- a/chromium/cc/layers/picture_layer.cc
+++ b/chromium/cc/layers/picture_layer.cc
@@ -4,8 +4,6 @@
#include "cc/layers/picture_layer.h"
-#include "cc/debug/benchmark_instrumentation.h"
-#include "cc/debug/devtools_instrumentation.h"
#include "cc/layers/content_layer_client.h"
#include "cc/layers/picture_layer_impl.h"
#include "cc/trees/layer_tree_impl.h"
@@ -21,7 +19,8 @@ PictureLayer::PictureLayer(ContentLayerClient* client)
: client_(client),
pile_(make_scoped_refptr(new PicturePile())),
instrumentation_object_tracker_(id()),
- is_mask_(false) {
+ is_mask_(false),
+ update_source_frame_number_(-1) {
}
PictureLayer::~PictureLayer() {
@@ -43,12 +42,12 @@ void PictureLayer::PushPropertiesTo(LayerImpl* base_layer) {
// Update may not get called for an empty layer, so resize here instead.
// Using layer_impl because either bounds() or paint_properties().bounds
// may disagree and either one could have been pushed to layer_impl.
- pile_->Resize(layer_impl->bounds());
+ pile_->Resize(gfx::Size());
pile_->UpdateRecordedRegion();
- }
-
- if (DrawsContent()) {
- DCHECK(paint_properties().bounds == pile_->size());
+ } else if (update_source_frame_number_ ==
+ layer_tree_host()->source_frame_number()) {
+ // If update called, then pile size must match bounds pushed to impl layer.
+ DCHECK_EQ(layer_impl->bounds().ToString(), pile_->size().ToString());
}
layer_impl->SetIsMask(is_mask_);
@@ -84,15 +83,19 @@ void PictureLayer::SetNeedsDisplayRect(const gfx::RectF& layer_rect) {
bool PictureLayer::Update(ResourceUpdateQueue* queue,
const OcclusionTracker* occlusion) {
- // Do not early-out of this function so that PicturePile::Update has a chance
- // to record pictures due to changing visibility of this layer.
+ update_source_frame_number_ = layer_tree_host()->source_frame_number();
+ bool updated = Layer::Update(queue, occlusion);
- TRACE_EVENT1(benchmark_instrumentation::kCategory,
- benchmark_instrumentation::kPictureLayerUpdate,
- benchmark_instrumentation::kSourceFrameNumber,
- layer_tree_host()->source_frame_number());
+ if (last_updated_visible_content_rect_ == visible_content_rect() &&
+ pile_->size() == paint_properties().bounds &&
+ pending_invalidation_.IsEmpty()) {
+ // Only early out if the visible content rect of this layer hasn't changed.
+ return updated;
+ }
- bool updated = Layer::Update(queue, occlusion);
+ TRACE_EVENT1("cc", "PictureLayer::Update",
+ "source_frame_number",
+ layer_tree_host()->source_frame_number());
pile_->Resize(paint_properties().bounds);
@@ -108,14 +111,15 @@ bool PictureLayer::Update(ResourceUpdateQueue* queue,
// the full page content must always be provided in the picture layer.
visible_layer_rect = gfx::Rect(bounds());
}
- devtools_instrumentation::ScopedLayerTask paint_layer(
- devtools_instrumentation::kPaintLayer, id());
updated |= pile_->Update(client_,
SafeOpaqueBackgroundColor(),
contents_opaque(),
pile_invalidation_,
visible_layer_rect,
+ update_source_frame_number_,
rendering_stats_instrumentation());
+ last_updated_visible_content_rect_ = visible_content_rect();
+
if (updated) {
SetNeedsPushProperties();
} else {
@@ -153,4 +157,8 @@ skia::RefPtr<SkPicture> PictureLayer::GetPicture() const {
return picture;
}
+void PictureLayer::RunMicroBenchmark(MicroBenchmark* benchmark) {
+ benchmark->RunOnLayer(this);
+}
+
} // namespace cc
diff --git a/chromium/cc/layers/picture_layer.h b/chromium/cc/layers/picture_layer.h
index d7943307ddc..d986a9bfbbc 100644
--- a/chromium/cc/layers/picture_layer.h
+++ b/chromium/cc/layers/picture_layer.h
@@ -7,6 +7,7 @@
#include "cc/base/invalidation_region.h"
#include "cc/debug/devtools_instrumentation.h"
+#include "cc/debug/micro_benchmark_controller.h"
#include "cc/layers/layer.h"
#include "cc/resources/picture_pile.h"
#include "cc/trees/occlusion_tracker.h"
@@ -36,6 +37,10 @@ class CC_EXPORT PictureLayer : public Layer {
virtual bool SupportsLCDText() const OVERRIDE;
virtual skia::RefPtr<SkPicture> GetPicture() const OVERRIDE;
+ virtual void RunMicroBenchmark(MicroBenchmark* benchmark) OVERRIDE;
+
+ ContentLayerClient* client() { return client_; }
+
protected:
explicit PictureLayer(ContentLayerClient* client);
virtual ~PictureLayer();
@@ -49,8 +54,11 @@ class CC_EXPORT PictureLayer : public Layer {
InvalidationRegion pending_invalidation_;
// Invalidation from the last time update was called.
Region pile_invalidation_;
+ gfx::Rect last_updated_visible_content_rect_;
bool is_mask_;
+ int update_source_frame_number_;
+
DISALLOW_COPY_AND_ASSIGN(PictureLayer);
};
diff --git a/chromium/cc/layers/picture_layer_impl.cc b/chromium/cc/layers/picture_layer_impl.cc
index 95a4a076520..2f5ca94ba15 100644
--- a/chromium/cc/layers/picture_layer_impl.cc
+++ b/chromium/cc/layers/picture_layer_impl.cc
@@ -5,11 +5,13 @@
#include "cc/layers/picture_layer_impl.h"
#include <algorithm>
+#include <limits>
#include "base/time/time.h"
#include "cc/base/math_util.h"
#include "cc/base/util.h"
#include "cc/debug/debug_colors.h"
+#include "cc/debug/micro_benchmark_impl.h"
#include "cc/debug/traced_value.h"
#include "cc/layers/append_quads_data.h"
#include "cc/layers/quad_sink.h"
@@ -18,6 +20,7 @@
#include "cc/quads/picture_draw_quad.h"
#include "cc/quads/solid_color_draw_quad.h"
#include "cc/quads/tile_draw_quad.h"
+#include "cc/resources/tile_manager.h"
#include "cc/trees/layer_tree_impl.h"
#include "ui/gfx/quad_f.h"
#include "ui/gfx/rect_conversions.h"
@@ -25,6 +28,10 @@
namespace {
const float kMaxScaleRatioDuringPinch = 2.0f;
+
+// When creating a new tiling during pinch, snap to an existing
+// tiling's scale if the desired scale is within this ratio.
+const float kSnapToExistingTilingRatio = 0.2f;
}
namespace cc {
@@ -64,10 +71,18 @@ void PictureLayerImpl::PushPropertiesTo(LayerImpl* base_layer) {
// It's possible this layer was never drawn or updated (e.g. because it was
// a descendant of an opacity 0 layer).
DoPostCommitInitializationIfNeeded();
+ PictureLayerImpl* layer_impl = static_cast<PictureLayerImpl*>(base_layer);
- LayerImpl::PushPropertiesTo(base_layer);
+ // We have already synced the important bits from the the active layer, and
+ // we will soon swap out its tilings and use them for recycling. However,
+ // there are now tiles in this layer's tilings that were unref'd and replaced
+ // with new tiles (due to invalidation). This resets all active priorities on
+ // the to-be-recycled tiling to ensure replaced tiles don't linger and take
+ // memory (due to a stale 'active' priority).
+ if (layer_impl->tilings_)
+ layer_impl->tilings_->DidBecomeRecycled();
- PictureLayerImpl* layer_impl = static_cast<PictureLayerImpl*>(base_layer);
+ LayerImpl::PushPropertiesTo(base_layer);
// When the pending tree pushes to the active tree, the pending twin
// disappears.
@@ -110,12 +125,7 @@ void PictureLayerImpl::AppendQuads(QuadSink* quad_sink,
SharedQuadState* shared_quad_state =
quad_sink->UseSharedQuadState(CreateSharedQuadState());
- bool draw_direct_to_backbuffer =
- draw_properties().can_draw_directly_to_backbuffer &&
- layer_tree_impl()->settings().force_direct_layer_drawing;
-
- if (draw_direct_to_backbuffer ||
- current_draw_mode_ == DRAW_MODE_RESOURCELESS_SOFTWARE) {
+ if (current_draw_mode_ == DRAW_MODE_RESOURCELESS_SOFTWARE) {
AppendDebugBorderQuad(
quad_sink,
shared_quad_state,
@@ -139,7 +149,6 @@ void PictureLayerImpl::AppendQuads(QuadSink* quad_sink,
RGBA_8888,
quad_content_rect,
contents_scale,
- draw_direct_to_backbuffer,
pile_);
if (quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data))
append_quads_data->num_missing_tiles++;
@@ -227,7 +236,7 @@ void PictureLayerImpl::AppendQuads(QuadSink* quad_sink,
case ManagedTileState::TileVersion::RESOURCE_MODE: {
gfx::RectF texture_rect = iter.texture_rect();
gfx::Rect opaque_rect = iter->opaque_rect();
- opaque_rect.Intersect(content_rect);
+ opaque_rect.Intersect(geometry_rect);
if (iter->contents_scale() != ideal_contents_scale_)
append_quads_data->had_incomplete_tile = true;
@@ -246,7 +255,7 @@ void PictureLayerImpl::AppendQuads(QuadSink* quad_sink,
case ManagedTileState::TileVersion::PICTURE_PILE_MODE: {
gfx::RectF texture_rect = iter.texture_rect();
gfx::Rect opaque_rect = iter->opaque_rect();
- opaque_rect.Intersect(content_rect);
+ opaque_rect.Intersect(geometry_rect);
ResourceProvider* resource_provider =
layer_tree_impl()->resource_provider();
@@ -261,7 +270,6 @@ void PictureLayerImpl::AppendQuads(QuadSink* quad_sink,
format,
iter->content_rect(),
iter->contents_scale(),
- draw_direct_to_backbuffer,
pile_);
draw_quad = quad.PassAs<DrawQuad>();
break;
@@ -373,7 +381,7 @@ void PictureLayerImpl::DidBeginTracing() {
void PictureLayerImpl::DidLoseOutputSurface() {
if (tilings_)
- tilings_->RemoveAllTilings();
+ RemoveAllTilings();
ResetRasterScale();
}
@@ -448,13 +456,24 @@ skia::RefPtr<SkPicture> PictureLayerImpl::GetPicture() {
return pile_->GetFlattenedPicture();
}
+bool PictureLayerImpl::ShouldUseGPURasterization() const {
+ // TODO(skaslev): Add a proper heuristic for hybrid (software or GPU)
+ // tile rasterization. Currently, when --enable-gpu-rasterization is
+ // set all tiles get GPU rasterized.
+ return layer_tree_impl()->settings().gpu_rasterization;
+}
+
scoped_refptr<Tile> PictureLayerImpl::CreateTile(PictureLayerTiling* tiling,
gfx::Rect content_rect) {
if (!pile_->CanRaster(tiling->contents_scale(), content_rect))
return scoped_refptr<Tile>();
- return make_scoped_refptr(new Tile(
- layer_tree_impl()->tile_manager(),
+ int flags = 0;
+ if (is_using_lcd_text_)
+ flags |= Tile::USE_LCD_TEXT;
+ if (ShouldUseGPURasterization())
+ flags |= Tile::USE_GPU_RASTERIZATION;
+ return layer_tree_impl()->tile_manager()->CreateTile(
pile_.get(),
content_rect.size(),
content_rect,
@@ -462,7 +481,7 @@ scoped_refptr<Tile> PictureLayerImpl::CreateTile(PictureLayerTiling* tiling,
tiling->contents_scale(),
id(),
layer_tree_impl()->source_frame_number(),
- is_using_lcd_text_));
+ flags);
}
void PictureLayerImpl::UpdatePile(Tile* tile) {
@@ -474,7 +493,7 @@ const Region* PictureLayerImpl::GetInvalidation() {
}
const PictureLayerTiling* PictureLayerImpl::GetTwinTiling(
- const PictureLayerTiling* tiling) {
+ const PictureLayerTiling* tiling) const {
if (!twin_layer_)
return NULL;
@@ -544,7 +563,7 @@ void PictureLayerImpl::SyncFromActiveLayer(const PictureLayerImpl* other) {
UpdateLCDTextStatus(other->is_using_lcd_text_);
if (!DrawsContent()) {
- ResetRasterScale();
+ RemoveAllTilings();
return;
}
@@ -587,7 +606,7 @@ void PictureLayerImpl::SyncFromActiveLayer(const PictureLayerImpl* other) {
tiling_invalidation,
MinimumContentsScale());
} else {
- tilings_->RemoveAllTilings();
+ RemoveAllTilings();
}
SanityCheckTilingState();
@@ -645,6 +664,10 @@ void PictureLayerImpl::MarkVisibleResourcesAsRequired() const {
DCHECK(ideal_contents_scale_);
DCHECK_GT(tilings_->num_tilings(), 0u);
+ // The goal of this function is to find the minimum set of tiles that need to
+ // be ready to draw in order to activate without flashing content from a
+ // higher res on the active tree to a lower res on the pending tree.
+
gfx::Rect rect(visible_content_rect());
float min_acceptable_scale =
@@ -661,17 +684,21 @@ void PictureLayerImpl::MarkVisibleResourcesAsRequired() const {
}
}
- // Mark tiles for activation in two passes. Ready to draw tiles in acceptable
- // but non-ideal tilings are marked as required for activation, but any
- // non-ready tiles are not marked as required. From there, any missing holes
- // will need to be filled in from the high res tiling.
-
PictureLayerTiling* high_res = NULL;
+ PictureLayerTiling* low_res = NULL;
+
+ // First pass: ready to draw tiles in acceptable but non-ideal tilings are
+ // marked as required for activation so that their textures are not thrown
+ // away; any non-ready tiles are not marked as required.
Region missing_region = rect;
for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
PictureLayerTiling* tiling = tilings_->tiling_at(i);
DCHECK(tiling->has_ever_been_updated());
+ if (tiling->resolution() == LOW_RESOLUTION) {
+ DCHECK(!low_res) << "There can only be one low res tiling";
+ low_res = tiling;
+ }
if (tiling->contents_scale() < min_acceptable_scale)
continue;
if (tiling->resolution() == HIGH_RESOLUTION) {
@@ -697,21 +724,73 @@ void PictureLayerImpl::MarkVisibleResourcesAsRequired() const {
iter->MarkRequiredForActivation();
}
}
-
DCHECK(high_res) << "There must be one high res tiling";
- for (PictureLayerTiling::CoverageIterator iter(high_res,
- contents_scale_x(),
+
+ // If these pointers are null (because no twin, no matching tiling, or the
+ // simpification just below), then high res tiles will be required to fill any
+ // holes left by the first pass above. If the pointers are valid, then this
+ // layer is allowed to skip any tiles that are not ready on its twin.
+ const PictureLayerTiling* twin_high_res = NULL;
+ const PictureLayerTiling* twin_low_res = NULL;
+
+ // As a simplification, only allow activating to skip twin tiles that the
+ // active layer is also missing when both this layer and its twin have 2
+ // tilings (high and low). This avoids having to iterate/track coverage of
+ // non-ideal tilings during the last draw call on the active layer.
+ if (high_res && low_res && tilings_->num_tilings() == 2 &&
+ twin_layer_ && twin_layer_->tilings_->num_tilings() == 2) {
+ twin_low_res = GetTwinTiling(low_res);
+ if (twin_low_res)
+ twin_high_res = GetTwinTiling(high_res);
+ }
+ // If this layer and its twin have different transforms, then don't compare
+ // them and only allow activating to high res tiles, since tiles on each layer
+ // will be in different places on screen.
+ if (!twin_high_res || !twin_low_res ||
+ draw_properties().screen_space_transform !=
+ twin_layer_->draw_properties().screen_space_transform) {
+ twin_high_res = NULL;
+ twin_low_res = NULL;
+ }
+
+ // TODO(enne): temporarily disable this optimization: http://crbug.com/335289
+ twin_high_res = NULL;
+ twin_low_res = NULL;
+
+ // As a second pass, mark as required any visible high res tiles not filled in
+ // by acceptable non-ideal tiles from the first pass.
+ if (MarkVisibleTilesAsRequired(
+ high_res, twin_high_res, contents_scale_x(), rect, missing_region)) {
+ // As an optional third pass, if a high res tile was skipped because its
+ // twin was also missing, then fall back to mark low res tiles as required
+ // in case the active twin is substituting those for missing high res
+ // content.
+ MarkVisibleTilesAsRequired(
+ low_res, twin_low_res, contents_scale_x(), rect, missing_region);
+ }
+}
+
+bool PictureLayerImpl::MarkVisibleTilesAsRequired(
+ PictureLayerTiling* tiling,
+ const PictureLayerTiling* optional_twin_tiling,
+ float contents_scale,
+ gfx::Rect rect,
+ const Region& missing_region) const {
+ bool twin_had_missing_tile = false;
+ for (PictureLayerTiling::CoverageIterator iter(tiling,
+ contents_scale,
rect);
iter;
++iter) {
+ Tile* tile = *iter;
// A null tile (i.e. missing recording) can just be skipped.
- if (!*iter)
+ if (!tile)
continue;
// This iteration is over the visible content rect which is potentially
// less conservative than projecting the viewport into the layer.
// Ignore tiles that are know to be outside the viewport.
- if (iter->priority(PENDING_TREE).distance_to_visible_in_pixels != 0)
+ if (tile->priority(PENDING_TREE).distance_to_visible_in_pixels != 0)
continue;
// If the missing region doesn't cover it, this tile is fully
@@ -719,8 +798,20 @@ void PictureLayerImpl::MarkVisibleResourcesAsRequired() const {
if (!missing_region.Intersects(iter.geometry_rect()))
continue;
- iter->MarkRequiredForActivation();
+ // If the twin tile doesn't exist (i.e. missing recording or so far away
+ // that it is outside the visible tile rect) or this tile is shared between
+ // with the twin, then this tile isn't required to prevent flashing.
+ if (optional_twin_tiling) {
+ Tile* twin_tile = optional_twin_tiling->TileAt(iter.i(), iter.j());
+ if (!twin_tile || twin_tile == tile) {
+ twin_had_missing_tile = true;
+ continue;
+ }
+ }
+
+ tile->MarkRequiredForActivation();
}
+ return twin_had_missing_tile;
}
void PictureLayerImpl::DoPostCommitInitialization() {
@@ -768,9 +859,17 @@ void PictureLayerImpl::RemoveTiling(float contents_scale) {
break;
}
}
+ if (tilings_->num_tilings() == 0)
+ ResetRasterScale();
SanityCheckTilingState();
}
+void PictureLayerImpl::RemoveAllTilings() {
+ tilings_->RemoveAllTilings();
+ // If there are no tilings, then raster scales are no longer meaningful.
+ ResetRasterScale();
+}
+
namespace {
inline float PositiveRatio(float float1, float float2) {
@@ -779,16 +878,6 @@ inline float PositiveRatio(float float1, float float2) {
return float1 > float2 ? float1 / float2 : float2 / float1;
}
-inline bool IsCloserToThan(
- PictureLayerTiling* layer1,
- PictureLayerTiling* layer2,
- float contents_scale) {
- // Absolute value for ratios.
- float ratio1 = PositiveRatio(layer1->contents_scale(), contents_scale);
- float ratio2 = PositiveRatio(layer2->contents_scale(), contents_scale);
- return ratio1 < ratio2;
-}
-
} // namespace
void PictureLayerImpl::ManageTilings(bool animating_transform_to_screen) {
@@ -807,6 +896,11 @@ void PictureLayerImpl::ManageTilings(bool animating_transform_to_screen) {
low_res_raster_contents_scale_ == 0.f ||
ShouldAdjustRasterScale(animating_transform_to_screen);
+ if (tilings_->num_tilings() == 0) {
+ DCHECK(change_target_tiling)
+ << "A layer with no tilings shouldn't have valid raster scales";
+ }
+
// Store the value for the next time ShouldAdjustRasterScale is called.
raster_source_scale_was_animating_ = animating_transform_to_screen;
@@ -816,13 +910,7 @@ void PictureLayerImpl::ManageTilings(bool animating_transform_to_screen) {
if (!layer_tree_impl()->device_viewport_valid_for_tile_management())
return;
- raster_page_scale_ = ideal_page_scale_;
- raster_device_scale_ = ideal_device_scale_;
- raster_source_scale_ = ideal_source_scale_;
-
- CalculateRasterContentsScale(animating_transform_to_screen,
- &raster_contents_scale_,
- &low_res_raster_contents_scale_);
+ RecalculateRasterScales(animating_transform_to_screen);
PictureLayerTiling* high_res = NULL;
PictureLayerTiling* low_res = NULL;
@@ -855,11 +943,14 @@ void PictureLayerImpl::ManageTilings(bool animating_transform_to_screen) {
low_res != high_res)
low_res = AddTiling(low_res_raster_contents_scale_);
- high_res->set_resolution(HIGH_RESOLUTION);
+ // Set low-res if we have one.
+ if (!low_res)
+ low_res = previous_low_res;
if (low_res && low_res != high_res)
low_res->set_resolution(LOW_RESOLUTION);
- else if (!low_res && previous_low_res)
- previous_low_res->set_resolution(LOW_RESOLUTION);
+
+ // Make sure we always have one high-res (even if high == low).
+ high_res->set_resolution(HIGH_RESOLUTION);
SanityCheckTilingState();
}
@@ -876,10 +967,12 @@ bool PictureLayerImpl::ShouldAdjustRasterScale(
bool is_pinching = layer_tree_impl()->PinchGestureActive();
if (is_pinching && raster_page_scale_) {
- // If the page scale diverges too far during pinch, change raster target to
- // the current page scale.
- float ratio = PositiveRatio(ideal_page_scale_, raster_page_scale_);
- if (ratio >= kMaxScaleRatioDuringPinch)
+ // We change our raster scale when it is:
+ // - Higher than ideal (need a lower-res tiling available)
+ // - Too far from ideal (need a higher-res tiling available)
+ float ratio = ideal_page_scale_ / raster_page_scale_;
+ if (raster_page_scale_ > ideal_page_scale_ ||
+ ratio > kMaxScaleRatioDuringPinch)
return true;
}
@@ -896,41 +989,77 @@ bool PictureLayerImpl::ShouldAdjustRasterScale(
return false;
}
-void PictureLayerImpl::CalculateRasterContentsScale(
- bool animating_transform_to_screen,
- float* raster_contents_scale,
- float* low_res_raster_contents_scale) const {
- *raster_contents_scale = ideal_contents_scale_;
+float PictureLayerImpl::SnappedContentsScale(float scale) {
+ // If a tiling exists within the max snapping ratio, snap to its scale.
+ float snapped_contents_scale = scale;
+ float snapped_ratio = kSnapToExistingTilingRatio;
+ for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
+ float tiling_contents_scale = tilings_->tiling_at(i)->contents_scale();
+ float ratio = PositiveRatio(tiling_contents_scale, scale);
+ if (ratio < snapped_ratio) {
+ snapped_contents_scale = tiling_contents_scale;
+ snapped_ratio = ratio;
+ }
+ }
+ return snapped_contents_scale;
+}
+
+void PictureLayerImpl::RecalculateRasterScales(
+ bool animating_transform_to_screen) {
+ raster_device_scale_ = ideal_device_scale_;
+ raster_source_scale_ = ideal_source_scale_;
+
+ bool is_pinching = layer_tree_impl()->PinchGestureActive();
+ if (!is_pinching || raster_contents_scale_ == 0.f) {
+ // When not pinching or when we have no previous scale, we use ideal scale:
+ raster_page_scale_ = ideal_page_scale_;
+ raster_contents_scale_ = ideal_contents_scale_;
+ } else {
+ // See ShouldAdjustRasterScale:
+ // - When zooming out, preemptively create new tiling at lower resolution.
+ // - When zooming in, approximate ideal using multiple of kMaxScaleRatio.
+ bool zooming_out = raster_page_scale_ > ideal_page_scale_;
+ float desired_contents_scale =
+ zooming_out ? raster_contents_scale_ / kMaxScaleRatioDuringPinch
+ : raster_contents_scale_ * kMaxScaleRatioDuringPinch;
+ raster_contents_scale_ = SnappedContentsScale(desired_contents_scale);
+ raster_page_scale_ = raster_contents_scale_ / raster_device_scale_;
+ }
+
+ raster_contents_scale_ =
+ std::max(raster_contents_scale_, MinimumContentsScale());
// Don't allow animating CSS scales to drop below 1. This is needed because
// changes in raster source scale aren't handled. See the comment in
// ShouldAdjustRasterScale.
if (animating_transform_to_screen) {
- *raster_contents_scale = std::max(
- *raster_contents_scale, 1.f * ideal_page_scale_ * ideal_device_scale_);
+ raster_contents_scale_ = std::max(
+ raster_contents_scale_, 1.f * ideal_page_scale_ * ideal_device_scale_);
}
// If this layer would only create one tile at this content scale,
// don't create a low res tiling.
gfx::Size content_bounds =
- gfx::ToCeiledSize(gfx::ScaleSize(bounds(), *raster_contents_scale));
+ gfx::ToCeiledSize(gfx::ScaleSize(bounds(), raster_contents_scale_));
gfx::Size tile_size = CalculateTileSize(content_bounds);
if (tile_size.width() >= content_bounds.width() &&
tile_size.height() >= content_bounds.height()) {
- *low_res_raster_contents_scale = *raster_contents_scale;
+ low_res_raster_contents_scale_ = raster_contents_scale_;
return;
}
float low_res_factor =
layer_tree_impl()->settings().low_res_contents_scale_factor;
- *low_res_raster_contents_scale = std::max(
- *raster_contents_scale * low_res_factor,
+ low_res_raster_contents_scale_ = std::max(
+ raster_contents_scale_ * low_res_factor,
MinimumContentsScale());
}
void PictureLayerImpl::CleanUpTilingsOnActiveLayer(
std::vector<PictureLayerTiling*> used_tilings) {
DCHECK(layer_tree_impl()->IsActiveTree());
+ if (tilings_->num_tilings() == 0)
+ return;
float min_acceptable_high_res_scale = std::min(
raster_contents_scale_, ideal_contents_scale_);
@@ -970,10 +1099,14 @@ void PictureLayerImpl::CleanUpTilingsOnActiveLayer(
}
for (size_t i = 0; i < to_remove.size(); ++i) {
- if (twin)
+ const PictureLayerTiling* twin_tiling = GetTwinTiling(to_remove[i]);
+ // Only remove tilings from the twin layer if they have
+ // NON_IDEAL_RESOLUTION.
+ if (twin_tiling && twin_tiling->resolution() == NON_IDEAL_RESOLUTION)
twin->RemoveTiling(to_remove[i]->contents_scale());
tilings_->Remove(to_remove[i]);
}
+ DCHECK_GT(tilings_->num_tilings(), 0u);
SanityCheckTilingState();
}
@@ -1021,9 +1154,6 @@ bool PictureLayerImpl::CanHaveTilings() const {
return false;
if (pile_->recorded_region().IsEmpty())
return false;
- if (draw_properties().can_draw_directly_to_backbuffer &&
- layer_tree_impl()->settings().force_direct_layer_drawing)
- return false;
return true;
}
@@ -1059,6 +1189,7 @@ void PictureLayerImpl::GetDebugBorderProperties(
}
void PictureLayerImpl::AsValueInto(base::DictionaryValue* state) const {
+ const_cast<PictureLayerImpl*>(this)->DoPostCommitInitializationIfNeeded();
LayerImpl::AsValueInto(state);
state->SetDouble("ideal_contents_scale", ideal_contents_scale_);
state->SetDouble("geometry_contents_scale", contents_scale_x());
@@ -1066,6 +1197,11 @@ void PictureLayerImpl::AsValueInto(base::DictionaryValue* state) const {
state->Set("pictures", pile_->AsValue().release());
state->Set("invalidation", invalidation_.AsValue().release());
+ Region unrecorded_region(gfx::Rect(pile_->size()));
+ unrecorded_region.Subtract(pile_->recorded_region());
+ if (!unrecorded_region.IsEmpty())
+ state->Set("unrecorded_region", unrecorded_region.AsValue().release());
+
scoped_ptr<base::ListValue> coverage_tiles(new base::ListValue);
for (PictureLayerTilingSet::CoverageIterator iter(tilings_.get(),
contents_scale_x(),
@@ -1082,10 +1218,16 @@ void PictureLayerImpl::AsValueInto(base::DictionaryValue* state) const {
coverage_tiles->Append(tile_data.release());
}
state->Set("coverage_tiles", coverage_tiles.release());
+ state->SetBoolean("is_using_lcd_text", is_using_lcd_text_);
}
size_t PictureLayerImpl::GPUMemoryUsageInBytes() const {
+ const_cast<PictureLayerImpl*>(this)->DoPostCommitInitializationIfNeeded();
return tilings_->GPUMemoryUsageInBytes();
}
+void PictureLayerImpl::RunMicroBenchmark(MicroBenchmarkImpl* benchmark) {
+ benchmark->RunOnLayer(this);
+}
+
} // namespace cc
diff --git a/chromium/cc/layers/picture_layer_impl.h b/chromium/cc/layers/picture_layer_impl.h
index fd5c0677a98..ab6aad7138b 100644
--- a/chromium/cc/layers/picture_layer_impl.h
+++ b/chromium/cc/layers/picture_layer_impl.h
@@ -21,6 +21,7 @@ namespace cc {
struct AppendQuadsData;
class QuadSink;
+class MicroBenchmarkImpl;
class CC_EXPORT PictureLayerImpl
: public LayerImpl,
@@ -59,7 +60,7 @@ class CC_EXPORT PictureLayerImpl
gfx::Size content_bounds) const OVERRIDE;
virtual const Region* GetInvalidation() OVERRIDE;
virtual const PictureLayerTiling* GetTwinTiling(
- const PictureLayerTiling* tiling) OVERRIDE;
+ const PictureLayerTiling* tiling) const OVERRIDE;
// PushPropertiesTo active tree => pending tree.
void SyncTiling(const PictureLayerTiling* tiling);
@@ -70,24 +71,33 @@ class CC_EXPORT PictureLayerImpl
virtual size_t GPUMemoryUsageInBytes() const OVERRIDE;
+ virtual void RunMicroBenchmark(MicroBenchmarkImpl* benchmark) OVERRIDE;
+
protected:
PictureLayerImpl(LayerTreeImpl* tree_impl, int id);
PictureLayerTiling* AddTiling(float contents_scale);
void RemoveTiling(float contents_scale);
+ void RemoveAllTilings();
void SyncFromActiveLayer(const PictureLayerImpl* other);
void ManageTilings(bool animating_transform_to_screen);
virtual bool ShouldAdjustRasterScale(
bool animating_transform_to_screen) const;
- virtual void CalculateRasterContentsScale(
- bool animating_transform_to_screen,
- float* raster_contents_scale,
- float* low_res_raster_contents_scale) const;
+ virtual void RecalculateRasterScales(
+ bool animating_transform_to_screen);
void CleanUpTilingsOnActiveLayer(
std::vector<PictureLayerTiling*> used_tilings);
float MinimumContentsScale() const;
+ float SnappedContentsScale(float new_contents_scale);
void UpdateLCDTextStatus(bool new_status);
void ResetRasterScale();
void MarkVisibleResourcesAsRequired() const;
+ bool MarkVisibleTilesAsRequired(
+ PictureLayerTiling* tiling,
+ const PictureLayerTiling* optional_twin_tiling,
+ float contents_scale,
+ gfx::Rect rect,
+ const Region& missing_region) const;
+
void DoPostCommitInitializationIfNeeded() {
if (needs_post_commit_initialization_)
DoPostCommitInitialization();
@@ -97,6 +107,7 @@ class CC_EXPORT PictureLayerImpl
bool CanHaveTilings() const;
bool CanHaveTilingWithScale(float contents_scale) const;
void SanityCheckTilingState() const;
+ bool ShouldUseGPURasterization() const;
virtual void GetDebugBorderProperties(
SkColor* color, float* width) const OVERRIDE;
diff --git a/chromium/cc/layers/picture_layer_impl_unittest.cc b/chromium/cc/layers/picture_layer_impl_unittest.cc
index e1cd39ada41..eb3b0597194 100644
--- a/chromium/cc/layers/picture_layer_impl_unittest.cc
+++ b/chromium/cc/layers/picture_layer_impl_unittest.cc
@@ -6,7 +6,6 @@
#include <utility>
-#include "cc/debug/test_web_graphics_context_3d.h"
#include "cc/layers/append_quads_data.h"
#include "cc/layers/picture_layer.h"
#include "cc/test/fake_content_layer_client.h"
@@ -18,6 +17,7 @@
#include "cc/test/geometry_test_utils.h"
#include "cc/test/impl_side_painting_settings.h"
#include "cc/test/mock_quad_culler.h"
+#include "cc/test/test_web_graphics_context_3d.h"
#include "cc/trees/layer_tree_impl.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkBitmapDevice.h"
@@ -68,18 +68,37 @@ class PictureLayerImplTest : public testing::Test {
SetupTrees(pending_pile, active_pile);
}
- void SetupTrees(
- scoped_refptr<PicturePileImpl> pending_pile,
- scoped_refptr<PicturePileImpl> active_pile) {
- SetupPendingTree(active_pile);
+ void ActivateTree() {
host_impl_.ActivatePendingTree();
-
+ CHECK(!host_impl_.pending_tree());
+ pending_layer_ = NULL;
active_layer_ = static_cast<FakePictureLayerImpl*>(
host_impl_.active_tree()->LayerById(id_));
+ }
+ void SetupDefaultTreesWithFixedTileSize(gfx::Size layer_bounds,
+ gfx::Size tile_size) {
+ SetupDefaultTrees(layer_bounds);
+ pending_layer_->set_fixed_tile_size(tile_size);
+ active_layer_->set_fixed_tile_size(tile_size);
+ }
+
+ void SetupTrees(
+ scoped_refptr<PicturePileImpl> pending_pile,
+ scoped_refptr<PicturePileImpl> active_pile) {
+ SetupPendingTree(active_pile);
+ ActivateTree();
SetupPendingTree(pending_pile);
}
+ void CreateHighLowResAndSetAllTilesVisible() {
+ // Active layer must get updated first so pending layer can share from it.
+ active_layer_->CreateDefaultTilingsAndTiles();
+ active_layer_->SetAllTilesVisible();
+ pending_layer_->CreateDefaultTilingsAndTiles();
+ pending_layer_->SetAllTilesVisible();
+ }
+
void AddDefaultTilingsWithInvalidation(const Region& invalidation) {
active_layer_->AddTiling(2.3f);
active_layer_->AddTiling(1.0f);
@@ -149,6 +168,20 @@ class PictureLayerImplTest : public testing::Test {
active_layer_->DidLoseOutputSurface();
}
+ void AssertAllTilesRequired(PictureLayerTiling* tiling) {
+ std::vector<Tile*> tiles = tiling->AllTilesForTesting();
+ for (size_t i = 0; i < tiles.size(); ++i)
+ EXPECT_TRUE(tiles[i]->required_for_activation()) << "i: " << i;
+ EXPECT_GT(tiles.size(), 0u);
+ }
+
+ void AssertNoTilesRequired(PictureLayerTiling* tiling) {
+ std::vector<Tile*> tiles = tiling->AllTilesForTesting();
+ for (size_t i = 0; i < tiles.size(); ++i)
+ EXPECT_FALSE(tiles[i]->required_for_activation()) << "i: " << i;
+ EXPECT_GT(tiles.size(), 0u);
+ }
+
protected:
void TestTileGridAlignmentCommon() {
// Layer to span 4 raster tiles in x and in y
@@ -591,6 +624,157 @@ TEST_F(PictureLayerImplTest, ManageTilingsCreatesTilings) {
pending_layer_->tilings()->tiling_at(3)->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::CreateFilledPile(tile_size, gfx::Size(1000, 0));
+ scoped_refptr<FakePicturePileImpl> valid_pile =
+ FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+
+ float low_res_factor = host_impl_.settings().low_res_contents_scale_factor;
+ EXPECT_LT(low_res_factor, 1.f);
+
+ float high_res_scale = 1.3f;
+ float low_res_scale = high_res_scale * low_res_factor;
+ float device_scale = 1.7f;
+ float page_scale = 3.2f;
+ float result_scale_x, result_scale_y;
+ gfx::Size result_bounds;
+
+ SetupPendingTree(valid_pile);
+ pending_layer_->CalculateContentsScale(high_res_scale,
+ device_scale,
+ page_scale,
+ false,
+ &result_scale_x,
+ &result_scale_y,
+ &result_bounds);
+ ASSERT_EQ(2u, pending_layer_->tilings()->num_tilings());
+ EXPECT_FLOAT_EQ(high_res_scale,
+ pending_layer_->HighResTiling()->contents_scale());
+ EXPECT_FLOAT_EQ(low_res_scale,
+ pending_layer_->LowResTiling()->contents_scale());
+
+ ActivateTree();
+ SetupPendingTree(empty_pile);
+ pending_layer_->CalculateContentsScale(high_res_scale,
+ device_scale,
+ page_scale,
+ false,
+ &result_scale_x,
+ &result_scale_y,
+ &result_bounds);
+ ASSERT_EQ(2u, active_layer_->tilings()->num_tilings());
+ ASSERT_EQ(0u, pending_layer_->tilings()->num_tilings());
+
+ ActivateTree();
+ active_layer_->CalculateContentsScale(high_res_scale,
+ device_scale,
+ page_scale,
+ false,
+ &result_scale_x,
+ &result_scale_y,
+ &result_bounds);
+ ASSERT_EQ(0u, active_layer_->tilings()->num_tilings());
+
+ SetupPendingTree(valid_pile);
+ pending_layer_->CalculateContentsScale(high_res_scale,
+ device_scale,
+ page_scale,
+ false,
+ &result_scale_x,
+ &result_scale_y,
+ &result_bounds);
+ ASSERT_EQ(2u, pending_layer_->tilings()->num_tilings());
+ ASSERT_EQ(0u, active_layer_->tilings()->num_tilings());
+ EXPECT_FLOAT_EQ(high_res_scale,
+ pending_layer_->HighResTiling()->contents_scale());
+ EXPECT_FLOAT_EQ(low_res_scale,
+ pending_layer_->LowResTiling()->contents_scale());
+}
+
+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);
+ EXPECT_EQ(0u, active_layer_->tilings()->num_tilings());
+ SetContentsScaleOnBothLayers(32.0f, 1.0f, 32.0f, false);
+ host_impl_.PinchGestureBegin();
+ SetContentsScaleOnBothLayers(1.0f, 1.0f, 1.0f, false);
+ SetContentsScaleOnBothLayers(1.0f, 1.0f, 1.0f, false);
+ EXPECT_EQ(active_layer_->tilings()->NumHighResTilings(), 1);
+}
+
+TEST_F(PictureLayerImplTest, PinchGestureTilings) {
+ 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);
+
+ // Set up the high and low res tilings before pinch zoom.
+ SetupTrees(pending_pile, active_pile);
+ EXPECT_EQ(0u, active_layer_->tilings()->num_tilings());
+ SetContentsScaleOnBothLayers(1.0f, 1.0f, 1.0f, false);
+ float low_res_factor = host_impl_.settings().low_res_contents_scale_factor;
+ EXPECT_EQ(2u, active_layer_->tilings()->num_tilings());
+ EXPECT_FLOAT_EQ(
+ 1.0f,
+ active_layer_->tilings()->tiling_at(0)->contents_scale());
+ EXPECT_FLOAT_EQ(
+ 1.0f * low_res_factor,
+ active_layer_->tilings()->tiling_at(1)->contents_scale());
+
+ // Start a pinch gesture.
+ host_impl_.PinchGestureBegin();
+
+ // Zoom out by a small amount. We should create a tiling at half
+ // the scale (1/kMaxScaleRatioDuringPinch).
+ SetContentsScaleOnBothLayers(0.90f, 1.0f, 0.9f, false);
+ EXPECT_EQ(3u, active_layer_->tilings()->num_tilings());
+ EXPECT_FLOAT_EQ(
+ 1.0f,
+ active_layer_->tilings()->tiling_at(0)->contents_scale());
+ EXPECT_FLOAT_EQ(
+ 0.5f,
+ active_layer_->tilings()->tiling_at(1)->contents_scale());
+ EXPECT_FLOAT_EQ(
+ 1.0f * low_res_factor,
+ active_layer_->tilings()->tiling_at(2)->contents_scale());
+
+ // Zoom out further, close to our low-res scale factor. We should
+ // use that tiling as high-res, and not create a new tiling.
+ SetContentsScaleOnBothLayers(low_res_factor, 1.0f, low_res_factor, false);
+ EXPECT_EQ(3u, active_layer_->tilings()->num_tilings());
+
+ // Zoom in a lot now. Since we increase by increments of
+ // kMaxScaleRatioDuringPinch, this will first use 0.5, then 1.0
+ // and then finally create a new tiling at 2.0.
+ SetContentsScaleOnBothLayers(2.1f, 1.0f, 2.1f, false);
+ EXPECT_EQ(3u, active_layer_->tilings()->num_tilings());
+ SetContentsScaleOnBothLayers(2.1f, 1.0f, 2.1f, false);
+ EXPECT_EQ(3u, active_layer_->tilings()->num_tilings());
+ SetContentsScaleOnBothLayers(2.1f, 1.0f, 2.1f, false);
+ EXPECT_EQ(4u, active_layer_->tilings()->num_tilings());
+ EXPECT_FLOAT_EQ(
+ 2.0f,
+ active_layer_->tilings()->tiling_at(0)->contents_scale());
+}
+
TEST_F(PictureLayerImplTest, CleanUpTilings) {
gfx::Size tile_size(400, 400);
gfx::Size layer_bounds(1300, 1900);
@@ -742,12 +926,12 @@ TEST_F(PictureLayerImplTest, DontAddLowResDuringAnimation) {
EXPECT_BOTH_EQ(num_tilings(), 2u);
// Page scale animation, new high res, but not new low res because animating.
- contents_scale = 4.f;
- page_scale = 4.f;
+ contents_scale = 2.f;
+ page_scale = 2.f;
animating_transform = true;
SetContentsScaleOnBothLayers(
contents_scale, device_scale, page_scale, animating_transform);
- EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 4.f);
+ EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 2.f);
EXPECT_BOTH_EQ(LowResTiling()->contents_scale(), low_res_factor);
EXPECT_BOTH_EQ(num_tilings(), 3u);
@@ -755,8 +939,8 @@ TEST_F(PictureLayerImplTest, DontAddLowResDuringAnimation) {
animating_transform = false;
SetContentsScaleOnBothLayers(
contents_scale, device_scale, page_scale, animating_transform);
- EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 4.f);
- EXPECT_BOTH_EQ(LowResTiling()->contents_scale(), 4.f * low_res_factor);
+ EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 2.f);
+ EXPECT_BOTH_EQ(LowResTiling()->contents_scale(), 2.f * low_res_factor);
EXPECT_BOTH_EQ(num_tilings(), 4u);
}
@@ -885,6 +1069,7 @@ TEST_F(PictureLayerImplTest, ClampTilesToToMaxTileSize) {
scoped_ptr<TestWebGraphicsContext3D> context =
TestWebGraphicsContext3D::Create();
context->set_max_texture_size(140);
+ host_impl_.DidLoseOutputSurface();
host_impl_.InitializeRenderer(FakeOutputSurface::Create3d(
context.Pass()).PassAs<OutputSurface>());
@@ -936,6 +1121,7 @@ TEST_F(PictureLayerImplTest, ClampSingleTileToToMaxTileSize) {
scoped_ptr<TestWebGraphicsContext3D> context =
TestWebGraphicsContext3D::Create();
context->set_max_texture_size(140);
+ host_impl_.DidLoseOutputSurface();
host_impl_.InitializeRenderer(FakeOutputSurface::Create3d(
context.Pass()).PassAs<OutputSurface>());
@@ -1071,6 +1257,101 @@ TEST_F(PictureLayerImplTest, MarkRequiredOffscreenTiles) {
EXPECT_GT(num_offscreen, 0);
}
+TEST_F(PictureLayerImplTest, HighResRequiredWhenUnsharedActiveAllReady) {
+ gfx::Size layer_bounds(400, 400);
+ gfx::Size tile_size(100, 100);
+ SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size);
+
+ // No tiles shared.
+ pending_layer_->set_invalidation(gfx::Rect(layer_bounds));
+
+ CreateHighLowResAndSetAllTilesVisible();
+
+ active_layer_->SetAllTilesReady();
+
+ // No shared tiles and all active tiles ready, so pending can only
+ // activate with all high res tiles.
+ pending_layer_->MarkVisibleResourcesAsRequired();
+ AssertAllTilesRequired(pending_layer_->HighResTiling());
+ AssertNoTilesRequired(pending_layer_->LowResTiling());
+}
+
+// TODO(enne): temporarily disabled: http://crbug.com/335289
+TEST_F(PictureLayerImplTest, DISABLED_NothingRequiredIfAllHighResTilesShared) {
+ gfx::Size layer_bounds(400, 400);
+ gfx::Size tile_size(100, 100);
+ SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size);
+
+ CreateHighLowResAndSetAllTilesVisible();
+
+ Tile* some_active_tile =
+ active_layer_->HighResTiling()->AllTilesForTesting()[0];
+ EXPECT_FALSE(some_active_tile->IsReadyToDraw());
+
+ // All tiles shared (no invalidation), so even though the active tree's
+ // tiles aren't ready, there is nothing required.
+ pending_layer_->MarkVisibleResourcesAsRequired();
+ AssertNoTilesRequired(pending_layer_->HighResTiling());
+ AssertNoTilesRequired(pending_layer_->LowResTiling());
+}
+
+// TODO(enne): temporarily disabled: http://crbug.com/335289
+TEST_F(PictureLayerImplTest, DISABLED_NothingRequiredIfActiveMissingTiles) {
+ gfx::Size layer_bounds(400, 400);
+ gfx::Size tile_size(100, 100);
+ scoped_refptr<FakePicturePileImpl> pending_pile =
+ FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ // An arbitrary bogus outside the layer recording. Enough for the layer to
+ // think it can create tiles, but not in bounds so all tiles are null.
+ Region active_recorded_region;
+ active_recorded_region.Union(gfx::Rect(1000, 1000, 1, 1));
+ scoped_refptr<FakePicturePileImpl> active_pile =
+ FakePicturePileImpl::CreatePileWithRecordedRegion(
+ tile_size, layer_bounds, active_recorded_region);
+ SetupTrees(pending_pile, active_pile);
+ pending_layer_->set_fixed_tile_size(tile_size);
+ active_layer_->set_fixed_tile_size(tile_size);
+
+ CreateHighLowResAndSetAllTilesVisible();
+
+ // Active layer has tilings, but no tiles due to missing recordings.
+ EXPECT_TRUE(active_layer_->CanHaveTilings());
+ EXPECT_EQ(active_layer_->tilings()->num_tilings(), 2u);
+ EXPECT_EQ(active_layer_->HighResTiling()->AllTilesForTesting().size(), 0u);
+
+ // Since the active layer has no tiles at all, the pending layer doesn't
+ // need content in order to activate. This is attempting to simulate
+ // scrolling past the end of recorded content on the active layer.
+ pending_layer_->MarkVisibleResourcesAsRequired();
+ 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);
+ SetupTrees(pending_pile, active_pile);
+ pending_layer_->set_fixed_tile_size(tile_size);
+ active_layer_->set_fixed_tile_size(tile_size);
+
+ CreateHighLowResAndSetAllTilesVisible();
+
+ // Active layer can't have tiles.
+ EXPECT_FALSE(active_layer_->CanHaveTilings());
+
+ // All high res tiles required. This should be considered identical
+ // to the case where there is no active layer, to avoid flashing content.
+ // This can happen if a layer exists for a while and switches from
+ // not being able to have content to having content.
+ pending_layer_->MarkVisibleResourcesAsRequired();
+ AssertAllTilesRequired(pending_layer_->HighResTiling());
+ AssertNoTilesRequired(pending_layer_->LowResTiling());
+}
+
TEST_F(PictureLayerImplTest, ActivateUninitializedLayer) {
gfx::Size tile_size(100, 100);
gfx::Size layer_bounds(400, 400);
@@ -1106,19 +1387,92 @@ TEST_F(PictureLayerImplTest, ActivateUninitializedLayer) {
EXPECT_FALSE(active_layer_->needs_post_commit_initialization());
}
-// Solid color scrollbar setting is required for deferred initialization.
-class ImplSidePaintingSolidColorScrollbarSettings
- : public ImplSidePaintingSettings {
- public:
- ImplSidePaintingSolidColorScrollbarSettings() {
- solid_color_scrollbars = true;
- }
-};
+TEST_F(PictureLayerImplTest, SyncTilingAfterReleaseResource) {
+ SetupDefaultTrees(gfx::Size(10, 10));
+ host_impl_.active_tree()->UpdateDrawProperties();
+ EXPECT_FALSE(host_impl_.active_tree()->needs_update_draw_properties());
+
+ // Contrived unit test of a real crash. A layer is transparent during a
+ // context loss, and later becomes opaque, causing active layer SyncTiling to
+ // be called.
+ const float tile_scale = 2.f;
+ active_layer_->DidLoseOutputSurface();
+ EXPECT_FALSE(active_layer_->tilings()->TilingAtScale(tile_scale));
+ pending_layer_->AddTiling(2.f);
+ EXPECT_TRUE(active_layer_->tilings()->TilingAtScale(tile_scale));
+}
+
+TEST_F(PictureLayerImplTest, NoTilingIfDoesNotDrawContent) {
+ // Set up layers with tilings.
+ SetupDefaultTrees(gfx::Size(10, 10));
+ SetContentsScaleOnBothLayers(1.f, 1.f, 1.f, false);
+ pending_layer_->PushPropertiesTo(active_layer_);
+ EXPECT_TRUE(pending_layer_->DrawsContent());
+ EXPECT_TRUE(pending_layer_->CanHaveTilings());
+ EXPECT_GE(pending_layer_->num_tilings(), 0u);
+ EXPECT_GE(active_layer_->num_tilings(), 0u);
+
+ // Set content to false, which should make CanHaveTilings return false.
+ pending_layer_->SetDrawsContent(false);
+ EXPECT_FALSE(pending_layer_->DrawsContent());
+ EXPECT_FALSE(pending_layer_->CanHaveTilings());
+
+ // No tilings should be pushed to active layer.
+ pending_layer_->PushPropertiesTo(active_layer_);
+ EXPECT_EQ(0u, active_layer_->num_tilings());
+}
+
+TEST_F(PictureLayerImplTest, FirstTilingDuringPinch) {
+ SetupDefaultTrees(gfx::Size(10, 10));
+ host_impl_.PinchGestureBegin();
+ float high_res_scale = 2.3f;
+ SetContentsScaleOnBothLayers(high_res_scale, 1.f, 1.f, false);
+
+ ASSERT_GE(pending_layer_->num_tilings(), 0u);
+ EXPECT_FLOAT_EQ(high_res_scale,
+ pending_layer_->HighResTiling()->contents_scale());
+}
+
+TEST_F(PictureLayerImplTest, FirstTilingTooSmall) {
+ SetupDefaultTrees(gfx::Size(10, 10));
+ host_impl_.PinchGestureBegin();
+ float high_res_scale = 0.0001f;
+ EXPECT_GT(pending_layer_->MinimumContentsScale(), high_res_scale);
+
+ SetContentsScaleOnBothLayers(high_res_scale, 1.f, 1.f, false);
+
+ ASSERT_GE(pending_layer_->num_tilings(), 0u);
+ EXPECT_FLOAT_EQ(pending_layer_->MinimumContentsScale(),
+ pending_layer_->HighResTiling()->contents_scale());
+}
+
+TEST_F(PictureLayerImplTest, PinchingTooSmall) {
+ SetupDefaultTrees(gfx::Size(10, 10));
+
+ float contents_scale = 0.15f;
+ SetContentsScaleOnBothLayers(contents_scale, 1.f, 1.f, false);
+
+ ASSERT_GE(pending_layer_->num_tilings(), 0u);
+ EXPECT_FLOAT_EQ(contents_scale,
+ pending_layer_->HighResTiling()->contents_scale());
+
+ host_impl_.PinchGestureBegin();
+
+ float page_scale = 0.0001f;
+ EXPECT_LT(page_scale * contents_scale,
+ pending_layer_->MinimumContentsScale());
+
+
+ SetContentsScaleOnBothLayers(contents_scale, 1.f, page_scale, false);
+ ASSERT_GE(pending_layer_->num_tilings(), 0u);
+ EXPECT_FLOAT_EQ(pending_layer_->MinimumContentsScale(),
+ pending_layer_->HighResTiling()->contents_scale());
+}
class DeferredInitPictureLayerImplTest : public PictureLayerImplTest {
public:
DeferredInitPictureLayerImplTest()
- : PictureLayerImplTest(ImplSidePaintingSolidColorScrollbarSettings()) {}
+ : PictureLayerImplTest(ImplSidePaintingSettings()) {}
virtual void InitializeRenderer() OVERRIDE {
host_impl_.InitializeRenderer(FakeOutputSurface::CreateDeferredGL(
diff --git a/chromium/cc/layers/render_surface.cc b/chromium/cc/layers/render_surface.cc
index a17beab9ba7..0eab856a956 100644
--- a/chromium/cc/layers/render_surface.cc
+++ b/chromium/cc/layers/render_surface.cc
@@ -18,7 +18,7 @@ RenderSurface::RenderSurface(Layer* owning_layer)
screen_space_transforms_are_animating_(false),
is_clipped_(false),
contributes_to_drawn_surface_(false),
- nearest_ancestor_that_moves_pixels_(NULL) {}
+ nearest_occlusion_immune_ancestor_(NULL) {}
RenderSurface::~RenderSurface() {
for (size_t i = 0; i < layer_list_.size(); ++i) {
diff --git a/chromium/cc/layers/render_surface.h b/chromium/cc/layers/render_surface.h
index adce0a8a201..ef9ba229736 100644
--- a/chromium/cc/layers/render_surface.h
+++ b/chromium/cc/layers/render_surface.h
@@ -102,11 +102,11 @@ class CC_EXPORT RenderSurface {
// RenderPasses so they can't contribute to a surface.
void AddContributingDelegatedRenderPassLayer(Layer* layer) {}
- void SetNearestAncestorThatMovesPixels(RenderSurface* surface) {
- nearest_ancestor_that_moves_pixels_ = surface;
+ void SetNearestOcclusionImmuneAncestor(RenderSurface* surface) {
+ nearest_occlusion_immune_ancestor_ = surface;
}
- const RenderSurface* nearest_ancestor_that_moves_pixels() const {
- return nearest_ancestor_that_moves_pixels_;
+ const RenderSurface* nearest_occlusion_immune_ancestor() const {
+ return nearest_occlusion_immune_ancestor_;
}
private:
@@ -135,9 +135,8 @@ class CC_EXPORT RenderSurface {
RenderSurfaceLayerList layer_list_;
// The nearest ancestor target surface that will contain the contents of this
- // surface, and that is going to move pixels within the surface (such as with
- // a blur). This can point to itself.
- RenderSurface* nearest_ancestor_that_moves_pixels_;
+ // surface, and that ignores outside occlusion. This can point to itself.
+ RenderSurface* nearest_occlusion_immune_ancestor_;
// For LayerIteratorActions
int target_render_surface_layer_index_history_;
diff --git a/chromium/cc/layers/render_surface_impl.cc b/chromium/cc/layers/render_surface_impl.cc
index 3262e281bbd..a8336bcaf4f 100644
--- a/chromium/cc/layers/render_surface_impl.cc
+++ b/chromium/cc/layers/render_surface_impl.cc
@@ -28,13 +28,13 @@ namespace cc {
RenderSurfaceImpl::RenderSurfaceImpl(LayerImpl* owning_layer)
: owning_layer_(owning_layer),
surface_property_changed_(false),
- 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_ancestor_that_moves_pixels_(NULL),
+ draw_opacity_(1),
+ nearest_occlusion_immune_ancestor_(NULL),
target_render_surface_layer_index_history_(0),
current_layer_index_history_(0) {
damage_tracker_ = DamageTracker::Create();
@@ -133,7 +133,7 @@ void RenderSurfaceImpl::AppendRenderPasses(RenderPassSink* pass_sink) {
delegated_renderer_layer->AppendContributingRenderPasses(pass_sink);
}
- scoped_ptr<RenderPass> pass = RenderPass::Create();
+ scoped_ptr<RenderPass> pass = RenderPass::Create(layer_list_.size());
pass->SetNew(RenderPassId(),
content_rect_,
damage_tracker_->current_damage_rect(),
@@ -156,7 +156,8 @@ void RenderSurfaceImpl::AppendQuads(QuadSink* quad_sink,
content_rect_,
clip_rect_,
is_clipped_,
- draw_opacity_);
+ draw_opacity_,
+ owning_layer_->blend_mode());
if (owning_layer_->ShowDebugBorders()) {
SkColor color = for_replica ?
@@ -228,7 +229,6 @@ void RenderSurfaceImpl::AppendQuads(QuadSink* quad_sink,
contents_changed_since_last_frame,
mask_uv_rect,
owning_layer_->filters(),
- owning_layer_->filter(),
owning_layer_->background_filters());
quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data);
}
diff --git a/chromium/cc/layers/render_surface_impl.h b/chromium/cc/layers/render_surface_impl.h
index f887a659394..c02a3194098 100644
--- a/chromium/cc/layers/render_surface_impl.h
+++ b/chromium/cc/layers/render_surface_impl.h
@@ -46,11 +46,11 @@ class CC_EXPORT RenderSurfaceImpl {
void SetDrawOpacity(float opacity) { draw_opacity_ = opacity; }
float draw_opacity() const { return draw_opacity_; }
- void SetNearestAncestorThatMovesPixels(RenderSurfaceImpl* surface) {
- nearest_ancestor_that_moves_pixels_ = surface;
+ void SetNearestOcclusionImmuneAncestor(RenderSurfaceImpl* surface) {
+ nearest_occlusion_immune_ancestor_ = surface;
}
- const RenderSurfaceImpl* nearest_ancestor_that_moves_pixels() const {
- return nearest_ancestor_that_moves_pixels_;
+ const RenderSurfaceImpl* nearest_occlusion_immune_ancestor() const {
+ return nearest_occlusion_immune_ancestor_;
}
void SetDrawOpacityIsAnimating(bool draw_opacity_is_animating) {
@@ -145,19 +145,19 @@ class CC_EXPORT RenderSurfaceImpl {
// Uses this surface's space.
gfx::Rect content_rect_;
- bool surface_property_changed_;
+ 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;
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_;
@@ -167,9 +167,8 @@ class CC_EXPORT RenderSurfaceImpl {
contributing_delegated_render_pass_layer_list_;
// The nearest ancestor target surface that will contain the contents of this
- // surface, and that is going to move pixels within the surface (such as with
- // a blur). This can point to itself.
- RenderSurfaceImpl* nearest_ancestor_that_moves_pixels_;
+ // surface, and that ignores outside occlusion. This can point to itself.
+ RenderSurfaceImpl* nearest_occlusion_immune_ancestor_;
scoped_ptr<DamageTracker> damage_tracker_;
diff --git a/chromium/cc/layers/scrollbar_layer_impl_base.cc b/chromium/cc/layers/scrollbar_layer_impl_base.cc
index c1e7126ff52..362465be3b0 100644
--- a/chromium/cc/layers/scrollbar_layer_impl_base.cc
+++ b/chromium/cc/layers/scrollbar_layer_impl_base.cc
@@ -72,6 +72,13 @@ void ScrollbarLayerImplBase::SetVisibleToTotalLengthRatio(float ratio) {
NoteLayerPropertyChanged();
}
+void ScrollbarLayerImplBase::SetThumbThicknessScaleFactor(float factor) {
+ if (thumb_thickness_scale_factor_ == factor)
+ return;
+ thumb_thickness_scale_factor_ = factor;
+ NoteLayerPropertyChanged();
+}
+
gfx::Rect ScrollbarLayerImplBase::ComputeThumbQuadRect() const {
// Thumb extent is the length of the thumb in the scrolling direction, thumb
// thickness is in the perpendicular direction. Here's an example of a
diff --git a/chromium/cc/layers/scrollbar_layer_impl_base.h b/chromium/cc/layers/scrollbar_layer_impl_base.h
index 55ade6ab04f..360ef970895 100644
--- a/chromium/cc/layers/scrollbar_layer_impl_base.h
+++ b/chromium/cc/layers/scrollbar_layer_impl_base.h
@@ -44,9 +44,7 @@ class CC_EXPORT ScrollbarLayerImplBase : public LayerImpl {
float thumb_thickness_scale_factor() {
return thumb_thickness_scale_factor_;
}
- void set_thumb_thickness_scale_factor(float thumb_thickness_scale_factor) {
- thumb_thickness_scale_factor_ = thumb_thickness_scale_factor;
- }
+ void SetThumbThicknessScaleFactor(float thumb_thickness_scale_factor);
protected:
ScrollbarLayerImplBase(LayerTreeImpl* tree_impl,
diff --git a/chromium/cc/layers/scrollbar_layer_unittest.cc b/chromium/cc/layers/scrollbar_layer_unittest.cc
index 2e1b4b6f483..53a9fa87b68 100644
--- a/chromium/cc/layers/scrollbar_layer_unittest.cc
+++ b/chromium/cc/layers/scrollbar_layer_unittest.cc
@@ -4,7 +4,6 @@
#include "base/containers/hash_tables.h"
#include "cc/animation/scrollbar_animation_controller.h"
-#include "cc/debug/test_web_graphics_context_3d.h"
#include "cc/layers/append_quads_data.h"
#include "cc/layers/painted_scrollbar_layer.h"
#include "cc/layers/painted_scrollbar_layer_impl.h"
@@ -22,6 +21,7 @@
#include "cc/test/geometry_test_utils.h"
#include "cc/test/layer_tree_test.h"
#include "cc/test/mock_quad_culler.h"
+#include "cc/test/test_web_graphics_context_3d.h"
#include "cc/trees/layer_tree_host.h"
#include "cc/trees/layer_tree_impl.h"
#include "cc/trees/single_thread_proxy.h"
@@ -364,7 +364,6 @@ class ScrollbarLayerSolidColorThumbTest : public testing::Test {
public:
ScrollbarLayerSolidColorThumbTest() {
LayerTreeSettings layer_tree_settings;
- layer_tree_settings.solid_color_scrollbars = true;
host_impl_.reset(new FakeLayerTreeHostImpl(layer_tree_settings, &proxy_));
const int kThumbThickness = 3;
@@ -513,13 +512,13 @@ TEST_F(ScrollbarLayerTestMaxTextureSize, DelegatingRenderer) {
class MockLayerTreeHost : public LayerTreeHost {
public:
- MockLayerTreeHost(LayerTreeHostClient* client,
+ MockLayerTreeHost(FakeLayerTreeHostClient* client,
const LayerTreeSettings& settings)
- : LayerTreeHost(client, settings),
+ : LayerTreeHost(client, NULL, settings),
next_id_(1),
total_ui_resource_created_(0),
total_ui_resource_deleted_(0) {
- Initialize(NULL);
+ InitializeSingleThreaded(client);
}
virtual UIResourceId CreateUIResource(UIResourceClient* content) OVERRIDE {
diff --git a/chromium/cc/layers/texture_layer.cc b/chromium/cc/layers/texture_layer.cc
index a845709448f..5c954c140c2 100644
--- a/chromium/cc/layers/texture_layer.cc
+++ b/chromium/cc/layers/texture_layer.cc
@@ -14,7 +14,7 @@
#include "cc/trees/blocking_task_runner.h"
#include "cc/trees/layer_tree_host.h"
#include "third_party/khronos/GLES2/gl2.h"
-#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
+#include "third_party/khronos/GLES2/gl2ext.h"
namespace cc {
@@ -51,7 +51,7 @@ TextureLayer::~TextureLayer() {
void TextureLayer::ClearClient() {
if (rate_limit_context_ && client_ && layer_tree_host())
- layer_tree_host()->StopRateLimiter(client_->Context3d());
+ layer_tree_host()->StopRateLimiter();
client_ = NULL;
if (uses_mailbox_)
SetTextureMailbox(TextureMailbox(), scoped_ptr<SingleReleaseCallback>());
@@ -115,7 +115,7 @@ void TextureLayer::SetBlendBackgroundColor(bool blend) {
void TextureLayer::SetRateLimitContext(bool rate_limit) {
if (!rate_limit && rate_limit_context_ && client_ && layer_tree_host())
- layer_tree_host()->StopRateLimiter(client_->Context3d());
+ layer_tree_host()->StopRateLimiter();
rate_limit_context_ = rate_limit;
}
@@ -133,9 +133,10 @@ void TextureLayer::SetTextureId(unsigned id) {
SetNextCommitWaitsForActivation();
}
-void TextureLayer::SetTextureMailbox(
+void TextureLayer::SetTextureMailboxInternal(
const TextureMailbox& mailbox,
- scoped_ptr<SingleReleaseCallback> release_callback) {
+ scoped_ptr<SingleReleaseCallback> release_callback,
+ bool requires_commit) {
DCHECK(uses_mailbox_);
DCHECK(!mailbox.IsValid() || !holder_ref_ ||
!mailbox.Equals(holder_ref_->holder()->mailbox()));
@@ -147,12 +148,26 @@ void TextureLayer::SetTextureMailbox(
else
holder_ref_.reset();
needs_set_mailbox_ = true;
- SetNeedsCommit();
+ // If we are within a commit, no need to do it again immediately after.
+ if (requires_commit)
+ SetNeedsCommit();
+ else
+ SetNeedsPushProperties();
+
// The active frame needs to be replaced and the mailbox returned before the
// commit is called complete.
SetNextCommitWaitsForActivation();
}
+void TextureLayer::SetTextureMailbox(
+ const TextureMailbox& mailbox,
+ scoped_ptr<SingleReleaseCallback> release_callback) {
+ SetTextureMailboxInternal(
+ mailbox,
+ release_callback.Pass(),
+ true /* requires_commit */);
+}
+
void TextureLayer::WillModifyTexture() {
if (!uses_mailbox_ && layer_tree_host() && (DrawsContent() ||
content_committed_)) {
@@ -165,7 +180,7 @@ void TextureLayer::SetNeedsDisplayRect(const gfx::RectF& dirty_rect) {
Layer::SetNeedsDisplayRect(dirty_rect);
if (rate_limit_context_ && client_ && layer_tree_host() && DrawsContent())
- layer_tree_host()->StartRateLimiter(client_->Context3d());
+ layer_tree_host()->StartRateLimiter();
}
void TextureLayer::SetLayerTreeHost(LayerTreeHost* host) {
@@ -182,7 +197,7 @@ void TextureLayer::SetLayerTreeHost(LayerTreeHost* host) {
SetNextCommitWaitsForActivation();
}
if (rate_limit_context_ && client_)
- layer_tree_host()->StopRateLimiter(client_->Context3d());
+ 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
@@ -211,15 +226,15 @@ bool TextureLayer::Update(ResourceUpdateQueue* queue,
&mailbox,
&release_callback,
layer_tree_host()->UsingSharedMemoryResources())) {
- SetTextureMailbox(mailbox, release_callback.Pass());
+ // Already within a commit, no need to do another one immediately.
+ SetTextureMailboxInternal(
+ mailbox,
+ release_callback.Pass(),
+ false /* requires_commit */);
updated = true;
}
} else {
texture_id_ = client_->PrepareTexture();
- DCHECK_EQ(!!texture_id_, !!client_->Context3d());
- if (client_->Context3d() &&
- client_->Context3d()->getGraphicsResetStatusARB() != GL_NO_ERROR)
- texture_id_ = 0;
updated = true;
SetNeedsPushProperties();
// The texture id needs to be removed from the active tree before the
@@ -270,10 +285,6 @@ Region TextureLayer::VisibleContentOpaqueRegion() const {
return Region();
}
-bool TextureLayer::CanClipSelf() const {
- return true;
-}
-
TextureLayer::MailboxHolder::MainThreadReference::MainThreadReference(
MailboxHolder* holder)
: holder_(holder) {
diff --git a/chromium/cc/layers/texture_layer.h b/chromium/cc/layers/texture_layer.h
index 5fb214c2c13..5f137724b23 100644
--- a/chromium/cc/layers/texture_layer.h
+++ b/chromium/cc/layers/texture_layer.h
@@ -13,8 +13,6 @@
#include "cc/layers/layer.h"
#include "cc/resources/texture_mailbox.h"
-namespace WebKit { class WebGraphicsContext3D; }
-
namespace cc {
class BlockingTaskRunner;
class SingleReleaseCallback;
@@ -143,13 +141,16 @@ class CC_EXPORT TextureLayer : public Layer {
virtual void PushPropertiesTo(LayerImpl* layer) OVERRIDE;
virtual Region VisibleContentOpaqueRegion() const OVERRIDE;
- virtual bool CanClipSelf() const OVERRIDE;
-
protected:
TextureLayer(TextureLayerClient* client, bool uses_mailbox);
virtual ~TextureLayer();
private:
+ void SetTextureMailboxInternal(
+ const TextureMailbox& mailbox,
+ scoped_ptr<SingleReleaseCallback> release_callback,
+ bool requires_commit);
+
TextureLayerClient* client_;
bool uses_mailbox_;
diff --git a/chromium/cc/layers/texture_layer_client.h b/chromium/cc/layers/texture_layer_client.h
index 187b12f16c4..47d6ae0e174 100644
--- a/chromium/cc/layers/texture_layer_client.h
+++ b/chromium/cc/layers/texture_layer_client.h
@@ -7,8 +7,6 @@
#include "cc/resources/single_release_callback.h"
-namespace WebKit { class WebGraphicsContext3D; }
-
namespace cc {
class ResourceUpdateQueue;
class TextureMailbox;
@@ -19,10 +17,6 @@ class TextureLayerClient {
// Returns the texture ID to be used for compositing.
virtual unsigned PrepareTexture() = 0;
- // Returns the context that is providing the texture. Used for rate limiting
- // and detecting lost context.
- virtual WebKit::WebGraphicsContext3D* Context3d() = 0;
-
// Returns true and provides a mailbox if a new frame is available.
// Returns false if no new data is available
// and the old mailbox is to be reused.
diff --git a/chromium/cc/layers/texture_layer_impl.cc b/chromium/cc/layers/texture_layer_impl.cc
index e16fd3c3f18..96b44c75792 100644
--- a/chromium/cc/layers/texture_layer_impl.cc
+++ b/chromium/cc/layers/texture_layer_impl.cc
@@ -66,6 +66,7 @@ void TextureLayerImpl::PushPropertiesTo(LayerImpl* layer) {
texture_layer->set_uv_bottom_right(uv_bottom_right_);
texture_layer->set_vertex_opacity(vertex_opacity_);
texture_layer->set_premultiplied_alpha(premultiplied_alpha_);
+ texture_layer->set_blend_background_color(blend_background_color_);
if (uses_mailbox_ && own_mailbox_) {
texture_layer->SetTextureMailbox(texture_mailbox_,
release_callback_.Pass());
@@ -104,7 +105,7 @@ bool TextureLayerImpl::WillDraw(DrawMode draw_mode,
// Have to upload a copy to a texture for it to be used in a
// hardware draw.
if (!texture_copy_)
- texture_copy_ = ScopedResource::create(resource_provider);
+ texture_copy_ = ScopedResource::Create(resource_provider);
if (texture_copy_->size() != texture_mailbox_.shared_memory_size() ||
resource_provider->InUseByConsumer(texture_copy_->id()))
texture_copy_->Free();
@@ -183,12 +184,7 @@ void TextureLayerImpl::AppendQuads(QuadSink* quad_sink,
bg_color,
vertex_opacity_,
flipped_);
-
- // Perform explicit clipping on a quad to avoid setting a scissor later.
- if (shared_quad_state->is_clipped && quad->PerformClipping())
- shared_quad_state->is_clipped = false;
- if (!quad->rect.IsEmpty())
- quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data);
+ quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data);
}
void TextureLayerImpl::DidDraw(ResourceProvider* resource_provider) {
@@ -229,10 +225,6 @@ const char* TextureLayerImpl::LayerTypeAsString() const {
return "cc::TextureLayerImpl";
}
-bool TextureLayerImpl::CanClipSelf() const {
- return true;
-}
-
void TextureLayerImpl::FreeTextureMailbox() {
if (!uses_mailbox_)
return;
diff --git a/chromium/cc/layers/texture_layer_impl.h b/chromium/cc/layers/texture_layer_impl.h
index 90c26923c8e..c20d9604387 100644
--- a/chromium/cc/layers/texture_layer_impl.h
+++ b/chromium/cc/layers/texture_layer_impl.h
@@ -60,8 +60,6 @@ class CC_EXPORT TextureLayerImpl : public LayerImpl {
vertex_opacity_[3] = vertex_opacity[3];
}
- virtual bool CanClipSelf() const OVERRIDE;
-
void SetTextureMailbox(const TextureMailbox& mailbox,
scoped_ptr<SingleReleaseCallback> release_callback);
diff --git a/chromium/cc/layers/texture_layer_unittest.cc b/chromium/cc/layers/texture_layer_unittest.cc
index 239c5b8fa22..3ae0c2944cd 100644
--- a/chromium/cc/layers/texture_layer_unittest.cc
+++ b/chromium/cc/layers/texture_layer_unittest.cc
@@ -12,7 +12,6 @@
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread.h"
#include "base/time/time.h"
-#include "cc/debug/test_web_graphics_context_3d.h"
#include "cc/layers/solid_color_layer.h"
#include "cc/layers/texture_layer_client.h"
#include "cc/layers/texture_layer_impl.h"
@@ -25,6 +24,7 @@
#include "cc/test/fake_output_surface.h"
#include "cc/test/layer_test_common.h"
#include "cc/test/layer_tree_test.h"
+#include "cc/test/test_web_graphics_context_3d.h"
#include "cc/trees/blocking_task_runner.h"
#include "cc/trees/layer_tree_host.h"
#include "cc/trees/layer_tree_impl.h"
@@ -43,16 +43,16 @@ namespace {
class MockLayerTreeHost : public LayerTreeHost {
public:
- explicit MockLayerTreeHost(LayerTreeHostClient* client)
- : LayerTreeHost(client, LayerTreeSettings()) {
- Initialize(NULL);
+ explicit MockLayerTreeHost(FakeLayerTreeHostClient* client)
+ : LayerTreeHost(client, NULL, LayerTreeSettings()) {
+ InitializeSingleThreaded(client);
}
MOCK_METHOD0(AcquireLayerTextures, void());
MOCK_METHOD0(SetNeedsCommit, void());
MOCK_METHOD0(SetNeedsUpdateLayers, void());
- MOCK_METHOD1(StartRateLimiter, void(WebKit::WebGraphicsContext3D* context));
- MOCK_METHOD1(StopRateLimiter, void(WebKit::WebGraphicsContext3D* context));
+ MOCK_METHOD0(StartRateLimiter, void());
+ MOCK_METHOD0(StopRateLimiter, void());
};
class TextureLayerTest : public testing::Test {
@@ -245,16 +245,12 @@ TEST_F(TextureLayerTest, VisibleContentOpaqueRegion) {
class FakeTextureLayerClient : public TextureLayerClient {
public:
- FakeTextureLayerClient() : context_(TestWebGraphicsContext3D::Create()) {}
+ FakeTextureLayerClient() {}
virtual unsigned PrepareTexture() OVERRIDE {
return 0;
}
- virtual WebKit::WebGraphicsContext3D* Context3d() OVERRIDE {
- return context_.get();
- }
-
virtual bool PrepareTextureMailbox(
TextureMailbox* mailbox,
scoped_ptr<SingleReleaseCallback>* release_callback,
@@ -265,7 +261,6 @@ class FakeTextureLayerClient : public TextureLayerClient {
}
private:
- scoped_ptr<TestWebGraphicsContext3D> context_;
DISALLOW_COPY_AND_ASSIGN(FakeTextureLayerClient);
};
@@ -278,23 +273,23 @@ TEST_F(TextureLayerTest, RateLimiter) {
layer_tree_host_->SetRootLayer(test_layer);
// Don't rate limit until we invalidate.
- EXPECT_CALL(*layer_tree_host_, StartRateLimiter(_)).Times(0);
+ 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(client.Context3d()));
+ 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(client.Context3d()));
+ 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(client.Context3d()));
+ EXPECT_CALL(*layer_tree_host_, StopRateLimiter());
EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
test_layer->ClearClient();
Mock::VerifyAndClearExpectations(layer_tree_host_.get());
@@ -306,14 +301,14 @@ TEST_F(TextureLayerTest, RateLimiter) {
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);
+ EXPECT_CALL(*layer_tree_host_, StartRateLimiter()).Times(0);
Mock::VerifyAndClearExpectations(layer_tree_host_.get());
- EXPECT_CALL(*layer_tree_host_, StartRateLimiter(client.Context3d()));
+ 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(client.Context3d()));
+ EXPECT_CALL(*layer_tree_host_, StopRateLimiter());
layer_tree_host_->SetRootLayer(NULL);
Mock::VerifyAndClearExpectations(layer_tree_host_.get());
}
@@ -892,7 +887,8 @@ class TextureLayerNoMailboxIsActivatedDuringCommit : public LayerTreeTest,
protected:
TextureLayerNoMailboxIsActivatedDuringCommit()
: wait_thread_("WAIT"),
- wait_event_(false, false) {
+ wait_event_(false, false),
+ texture_(0u) {
wait_thread_.Start();
}
@@ -916,13 +912,16 @@ class TextureLayerNoMailboxIsActivatedDuringCommit : public LayerTreeTest,
PostSetNeedsCommitToMainThread();
}
+ virtual scoped_ptr<OutputSurface> CreateOutputSurface(bool fallback)
+ OVERRIDE {
+ scoped_refptr<TestContextProvider> provider = TestContextProvider::Create();
+ texture_ = provider->UnboundTestContext3d()->createExternalTexture();
+ return FakeOutputSurface::Create3d(provider).PassAs<OutputSurface>();
+ }
+
// TextureLayerClient implementation.
virtual unsigned PrepareTexture() OVERRIDE {
- return OffscreenContextProviderForMainThread()
- ->Context3d()->createTexture();
- }
- virtual WebKit::WebGraphicsContext3D* Context3d() OVERRIDE {
- return OffscreenContextProviderForMainThread()->Context3d();
+ return texture_;
}
virtual bool PrepareTextureMailbox(
TextureMailbox* mailbox,
@@ -1001,8 +1000,8 @@ class TextureLayerNoMailboxIsActivatedDuringCommit : public LayerTreeTest,
base::Thread wait_thread_;
base::WaitableEvent wait_event_;
base::Lock activate_lock_;
+ unsigned texture_;
int activate_count_;
- int activate_commit_;
scoped_refptr<Layer> root_;
scoped_refptr<TextureLayer> layer_;
};
@@ -1166,6 +1165,7 @@ TEST_F(TextureLayerImplWithMailboxTest, TestWillDraw) {
{
scoped_ptr<TextureLayerImpl> impl_layer =
TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
+ impl_layer->SetDrawsContent(true);
impl_layer->SetTextureMailbox(
test_data_.mailbox1_,
SingleReleaseCallback::Create(test_data_.release_mailbox1_));
@@ -1175,6 +1175,7 @@ TEST_F(TextureLayerImplWithMailboxTest, TestWillDraw) {
{
scoped_ptr<TextureLayerImpl> impl_layer =
TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
+ impl_layer->SetDrawsContent(true);
impl_layer->SetTextureMailbox(TextureMailbox(),
scoped_ptr<SingleReleaseCallback>());
EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
@@ -1184,6 +1185,7 @@ TEST_F(TextureLayerImplWithMailboxTest, TestWillDraw) {
// Software resource.
scoped_ptr<TextureLayerImpl> impl_layer =
TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
+ impl_layer->SetDrawsContent(true);
impl_layer->SetTextureMailbox(
test_data_.mailbox3_,
SingleReleaseCallback::Create(test_data_.release_mailbox3_));
@@ -1193,6 +1195,7 @@ TEST_F(TextureLayerImplWithMailboxTest, TestWillDraw) {
{
scoped_ptr<TextureLayerImpl> impl_layer =
TextureLayerImpl::Create(host_impl_.active_tree(), 1, false);
+ impl_layer->SetDrawsContent(true);
ContextProvider* context_provider =
host_impl_.output_surface()->context_provider();
unsigned texture =
@@ -1204,6 +1207,7 @@ TEST_F(TextureLayerImplWithMailboxTest, TestWillDraw) {
{
scoped_ptr<TextureLayerImpl> impl_layer =
TextureLayerImpl::Create(host_impl_.active_tree(), 1, false);
+ impl_layer->SetDrawsContent(true);
impl_layer->set_texture_id(0);
EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
}
@@ -1212,6 +1216,7 @@ TEST_F(TextureLayerImplWithMailboxTest, TestWillDraw) {
{
scoped_ptr<TextureLayerImpl> impl_layer =
TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
+ impl_layer->SetDrawsContent(true);
impl_layer->SetTextureMailbox(
test_data_.mailbox1_,
SingleReleaseCallback::Create(test_data_.release_mailbox1_));
@@ -1221,6 +1226,7 @@ TEST_F(TextureLayerImplWithMailboxTest, TestWillDraw) {
{
scoped_ptr<TextureLayerImpl> impl_layer =
TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
+ impl_layer->SetDrawsContent(true);
impl_layer->SetTextureMailbox(TextureMailbox(),
scoped_ptr<SingleReleaseCallback>());
EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
@@ -1230,6 +1236,7 @@ TEST_F(TextureLayerImplWithMailboxTest, TestWillDraw) {
// Software resource.
scoped_ptr<TextureLayerImpl> impl_layer =
TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
+ impl_layer->SetDrawsContent(true);
impl_layer->SetTextureMailbox(
test_data_.mailbox3_,
SingleReleaseCallback::Create(test_data_.release_mailbox3_));
@@ -1239,6 +1246,7 @@ TEST_F(TextureLayerImplWithMailboxTest, TestWillDraw) {
{
scoped_ptr<TextureLayerImpl> impl_layer =
TextureLayerImpl::Create(host_impl_.active_tree(), 1, false);
+ impl_layer->SetDrawsContent(true);
ContextProvider* context_provider =
host_impl_.output_surface()->context_provider();
unsigned texture =
@@ -1250,6 +1258,7 @@ TEST_F(TextureLayerImplWithMailboxTest, TestWillDraw) {
{
scoped_ptr<TextureLayerImpl> impl_layer =
TextureLayerImpl::Create(host_impl_.active_tree(), 1, false);
+ impl_layer->SetDrawsContent(true);
impl_layer->set_texture_id(0);
EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
}
@@ -1258,6 +1267,7 @@ TEST_F(TextureLayerImplWithMailboxTest, TestWillDraw) {
{
scoped_ptr<TextureLayerImpl> impl_layer =
TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
+ impl_layer->SetDrawsContent(true);
impl_layer->SetTextureMailbox(
test_data_.mailbox1_,
SingleReleaseCallback::Create(test_data_.release_mailbox1_));
@@ -1267,6 +1277,7 @@ TEST_F(TextureLayerImplWithMailboxTest, TestWillDraw) {
{
scoped_ptr<TextureLayerImpl> impl_layer =
TextureLayerImpl::Create(host_impl_.active_tree(), 1, false);
+ impl_layer->SetDrawsContent(true);
ContextProvider* context_provider =
host_impl_.output_surface()->context_provider();
unsigned texture =
@@ -1351,6 +1362,7 @@ TEST_F(TextureLayerImplWithMailboxTest,
impl_layer->SetTextureMailbox(
test_data_.mailbox1_,
SingleReleaseCallback::Create(test_data_.release_mailbox1_));
+ impl_layer->SetDrawsContent(true);
impl_layer->DidBecomeActive();
EXPECT_TRUE(impl_layer->WillDraw(
DRAW_MODE_HARDWARE, host_impl_.active_tree()->resource_provider()));
@@ -1391,28 +1403,19 @@ class TextureLayerClientTest
public TextureLayerClient {
public:
TextureLayerClientTest()
- : context_(NULL),
- texture_(0),
+ : texture_(0),
commit_count_(0),
expected_used_textures_on_draw_(0),
expected_used_textures_on_commit_(0) {}
virtual scoped_ptr<OutputSurface> CreateOutputSurface(bool fallback)
OVERRIDE {
- scoped_ptr<TestWebGraphicsContext3D> context(
- TestWebGraphicsContext3D::Create());
- context_ = context.get();
- texture_ = context->createTexture();
- return FakeOutputSurface::Create3d(context.Pass()).PassAs<OutputSurface>();
+ scoped_refptr<TestContextProvider> provider = TestContextProvider::Create();
+ texture_ = provider->UnboundTestContext3d()->createExternalTexture();
+ return FakeOutputSurface::Create3d(provider).PassAs<OutputSurface>();
}
- virtual unsigned PrepareTexture() OVERRIDE {
- return texture_;
- }
-
- virtual WebKit::WebGraphicsContext3D* Context3d() OVERRIDE {
- return context_;
- }
+ virtual unsigned PrepareTexture() OVERRIDE { return texture_; }
virtual bool PrepareTextureMailbox(
TextureMailbox* mailbox,
@@ -1455,7 +1458,6 @@ class TextureLayerClientTest
base::AutoLock lock(lock_);
expected_used_textures_on_commit_ = 0;
}
- texture_ = 0;
break;
case 2:
EndTest();
@@ -1474,21 +1476,26 @@ class TextureLayerClientTest
virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
LayerTreeHostImpl::FrameData* frame_data,
bool result) OVERRIDE {
- context_->ResetUsedTextures();
+ ContextForImplThread(host_impl)->ResetUsedTextures();
return true;
}
virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
bool result) OVERRIDE {
ASSERT_TRUE(result);
- EXPECT_EQ(expected_used_textures_on_draw_, context_->NumUsedTextures());
+ EXPECT_EQ(expected_used_textures_on_draw_,
+ ContextForImplThread(host_impl)->NumUsedTextures());
}
virtual void AfterTest() OVERRIDE {}
private:
+ TestWebGraphicsContext3D* ContextForImplThread(LayerTreeHostImpl* host_impl) {
+ return static_cast<TestWebGraphicsContext3D*>(
+ host_impl->output_surface()->context_provider()->Context3d());
+ }
+
scoped_refptr<TextureLayer> texture_layer_;
- TestWebGraphicsContext3D* context_;
unsigned texture_;
int commit_count_;
@@ -1513,27 +1520,25 @@ class TextureLayerChangeInvisibleTest
public TextureLayerClient {
public:
TextureLayerChangeInvisibleTest()
- : client_context_(TestWebGraphicsContext3D::Create()),
- texture_(client_context_->createTexture()),
- texture_to_delete_on_next_commit_(0),
+ : texture_(0u),
prepare_called_(0),
commit_count_(0),
expected_texture_on_draw_(0) {}
+ virtual scoped_ptr<OutputSurface> CreateOutputSurface(bool fallback)
+ OVERRIDE {
+ scoped_refptr<TestContextProvider> provider = TestContextProvider::Create();
+ texture_ = provider->UnboundTestContext3d()->createExternalTexture();
+ return FakeOutputSurface::Create3d(provider).PassAs<OutputSurface>();
+ }
+
// TextureLayerClient implementation.
virtual unsigned PrepareTexture() OVERRIDE {
++prepare_called_;
return texture_;
}
-
- // TextureLayerClient implementation.
- virtual WebKit::WebGraphicsContext3D* Context3d() OVERRIDE {
- return client_context_.get();
- }
-
- // TextureLayerClient implementation.
virtual bool PrepareTextureMailbox(
- cc::TextureMailbox* mailbox,
+ TextureMailbox* mailbox,
scoped_ptr<SingleReleaseCallback>* release_callback,
bool use_shared_memory) OVERRIDE {
return false;
@@ -1582,9 +1587,6 @@ class TextureLayerChangeInvisibleTest
case 2: {
// Layer shouldn't have been updated.
EXPECT_EQ(1, prepare_called_);
- // Change the texture.
- texture_to_delete_on_next_commit_ = texture_;
- texture_ = client_context_->createTexture();
texture_layer_->SetNeedsDisplay();
// Force a change to make sure we draw a frame.
solid_layer_->SetBackgroundColor(SK_ColorGRAY);
@@ -1592,8 +1594,6 @@ class TextureLayerChangeInvisibleTest
}
case 3:
EXPECT_EQ(1, prepare_called_);
- client_context_->deleteTexture(texture_to_delete_on_next_commit_);
- texture_to_delete_on_next_commit_ = 0;
// Make layer visible again.
parent_layer_->SetOpacity(1.f);
break;
@@ -1601,7 +1601,6 @@ class TextureLayerChangeInvisibleTest
// Layer should have been updated.
EXPECT_EQ(2, prepare_called_);
texture_layer_->ClearClient();
- client_context_->deleteTexture(texture_);
texture_ = 0;
break;
}
@@ -1661,14 +1660,12 @@ class TextureLayerChangeInvisibleTest
scoped_refptr<SolidColorLayer> solid_layer_;
scoped_refptr<Layer> parent_layer_;
scoped_refptr<TextureLayer> texture_layer_;
- scoped_ptr<TestWebGraphicsContext3D> client_context_;
// Used on the main thread, and on the impl thread while the main thread is
// blocked.
unsigned texture_;
// Used on the main thread.
- unsigned texture_to_delete_on_next_commit_;
int prepare_called_;
int commit_count_;
@@ -1680,6 +1677,114 @@ class TextureLayerChangeInvisibleTest
// delegating renderer.
SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(TextureLayerChangeInvisibleTest);
+// Checks that TextureLayer::Update does not cause an extra commit when setting
+// the texture mailbox.
+class TextureLayerNoExtraCommitForMailboxTest
+ : public LayerTreeTest,
+ public TextureLayerClient {
+ public:
+ // TextureLayerClient implementation.
+ virtual unsigned PrepareTexture() OVERRIDE {
+ NOTREACHED();
+ return 0;
+ }
+ virtual bool PrepareTextureMailbox(
+ TextureMailbox* mailbox,
+ scoped_ptr<SingleReleaseCallback>* release_callback,
+ bool use_shared_memory) OVERRIDE {
+ if (layer_tree_host()->source_frame_number() == 1) {
+ *mailbox = TextureMailbox();
+ return true;
+ }
+
+ *mailbox = TextureMailbox(std::string(64, '1'));
+ *release_callback = SingleReleaseCallback::Create(
+ base::Bind(&TextureLayerNoExtraCommitForMailboxTest::MailboxReleased,
+ base::Unretained(this)));
+ return true;
+ }
+
+ void MailboxReleased(unsigned sync_point, bool lost_resource) {
+ EXPECT_EQ(2, layer_tree_host()->source_frame_number());
+ EndTest();
+ }
+
+ virtual void SetupTree() OVERRIDE {
+ scoped_refptr<Layer> root = Layer::Create();
+ root->SetBounds(gfx::Size(10, 10));
+ root->SetAnchorPoint(gfx::PointF());
+ root->SetIsDrawable(true);
+
+ solid_layer_ = SolidColorLayer::Create();
+ solid_layer_->SetBounds(gfx::Size(10, 10));
+ solid_layer_->SetIsDrawable(true);
+ solid_layer_->SetBackgroundColor(SK_ColorWHITE);
+ root->AddChild(solid_layer_);
+
+ parent_layer_ = Layer::Create();
+ parent_layer_->SetBounds(gfx::Size(10, 10));
+ parent_layer_->SetIsDrawable(true);
+ root->AddChild(parent_layer_);
+
+ texture_layer_ = TextureLayer::CreateForMailbox(this);
+ texture_layer_->SetBounds(gfx::Size(10, 10));
+ texture_layer_->SetAnchorPoint(gfx::PointF());
+ texture_layer_->SetIsDrawable(true);
+ parent_layer_->AddChild(texture_layer_);
+
+ layer_tree_host()->SetRootLayer(root);
+ LayerTreeTest::SetupTree();
+ }
+
+ virtual void BeginTest() OVERRIDE {
+ PostSetNeedsCommitToMainThread();
+ }
+
+ virtual void DidCommitAndDrawFrame() OVERRIDE {
+ switch (layer_tree_host()->source_frame_number()) {
+ case 1:
+ EXPECT_FALSE(proxy()->CommitPendingForTesting());
+ // Invalidate the texture layer to clear the mailbox before
+ // ending the test.
+ texture_layer_->SetNeedsDisplay();
+ break;
+ case 2:
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ }
+
+ virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
+ bool result) OVERRIDE {
+ ASSERT_TRUE(result);
+ DelegatedFrameData* delegated_frame_data =
+ output_surface()->last_sent_frame().delegated_frame_data.get();
+ if (!delegated_frame_data)
+ return;
+
+ // Return all resources immediately.
+ TransferableResourceArray resources_to_return =
+ output_surface()->resources_held_by_parent();
+
+ CompositorFrameAck ack;
+ for (size_t i = 0; i < resources_to_return.size(); ++i)
+ output_surface()->ReturnResource(resources_to_return[i].id, &ack);
+ host_impl->ReclaimResources(&ack);
+ host_impl->OnSwapBuffersComplete();
+ }
+
+ virtual void AfterTest() OVERRIDE {}
+
+ private:
+ scoped_refptr<SolidColorLayer> solid_layer_;
+ scoped_refptr<Layer> parent_layer_;
+ scoped_refptr<TextureLayer> texture_layer_;
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerNoExtraCommitForMailboxTest);
+
// Checks that changing a mailbox in the client for a TextureLayer that's
// invisible correctly works and uses the new mailbox as soon as the layer
// becomes visible (and returns the old one).
@@ -1701,15 +1806,8 @@ class TextureLayerChangeInvisibleMailboxTest
return 0;
}
- // TextureLayerClient implementation.
- virtual WebKit::WebGraphicsContext3D* Context3d() OVERRIDE {
- NOTREACHED();
- return NULL;
- }
-
- // TextureLayerClient implementation.
virtual bool PrepareTextureMailbox(
- cc::TextureMailbox* mailbox,
+ TextureMailbox* mailbox,
scoped_ptr<SingleReleaseCallback>* release_callback,
bool use_shared_memory) OVERRIDE {
++prepare_called_;
@@ -1847,26 +1945,20 @@ class TextureLayerLostContextTest
public TextureLayerClient {
public:
TextureLayerLostContextTest()
- : texture_(0),
+ : context_lost_(false),
draw_count_(0) {}
virtual scoped_ptr<OutputSurface> CreateOutputSurface(bool fallback)
OVERRIDE {
- texture_context_ = TestWebGraphicsContext3D::Create();
- texture_ = texture_context_->createTexture();
return CreateFakeOutputSurface();
}
virtual unsigned PrepareTexture() OVERRIDE {
- if (draw_count_ == 0) {
- texture_context_->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
- GL_INNOCENT_CONTEXT_RESET_ARB);
- }
- return texture_;
- }
-
- virtual WebKit::WebGraphicsContext3D* Context3d() OVERRIDE {
- return texture_context_.get();
+ if (draw_count_ == 0)
+ context_lost_ = true;
+ if (context_lost_)
+ return 0u;
+ return 1u;
}
virtual bool PrepareTextureMailbox(
@@ -1903,7 +1995,7 @@ class TextureLayerLostContextTest
if (++draw_count_ == 1)
EXPECT_EQ(0u, texture_layer->texture_id());
else
- EXPECT_EQ(texture_, texture_layer->texture_id());
+ EXPECT_EQ(1u, texture_layer->texture_id());
return true;
}
@@ -1915,8 +2007,7 @@ class TextureLayerLostContextTest
private:
scoped_refptr<TextureLayer> texture_layer_;
- scoped_ptr<TestWebGraphicsContext3D> texture_context_;
- unsigned texture_;
+ bool context_lost_;
int draw_count_;
};
diff --git a/chromium/cc/layers/tiled_layer.cc b/chromium/cc/layers/tiled_layer.cc
index 8bbf2271bc4..24baef526eb 100644
--- a/chromium/cc/layers/tiled_layer.cc
+++ b/chromium/cc/layers/tiled_layer.cc
@@ -334,8 +334,10 @@ bool TiledLayer::UpdateTiles(int left,
return false;
}
- gfx::Rect paint_rect =
- MarkTilesForUpdate(left, top, right, bottom, ignore_occlusions);
+ gfx::Rect update_rect;
+ gfx::Rect paint_rect;
+ MarkTilesForUpdate(
+ &update_rect, &paint_rect, left, top, right, bottom, ignore_occlusions);
if (occlusion)
occlusion->overdraw_metrics()->DidPaint(paint_rect);
@@ -345,7 +347,7 @@ bool TiledLayer::UpdateTiles(int left,
*updated = true;
UpdateTileTextures(
- paint_rect, left, top, right, bottom, queue, occlusion);
+ update_rect, paint_rect, left, top, right, bottom, queue, occlusion);
return true;
}
@@ -378,10 +380,7 @@ void TiledLayer::MarkOcclusionsAndRequestTextures(
if (occlusion && occlusion->Occluded(render_target(),
visible_tile_rect,
draw_transform(),
- draw_transform_is_animating(),
- is_clipped(),
- clip_rect(),
- NULL)) {
+ draw_transform_is_animating())) {
tile->occluded = true;
occluded_tile_count++;
} else {
@@ -425,12 +424,13 @@ bool TiledLayer::HaveTexturesForTiles(int left,
return true;
}
-gfx::Rect TiledLayer::MarkTilesForUpdate(int left,
- int top,
- int right,
- int bottom,
- bool ignore_occlusions) {
- gfx::Rect paint_rect;
+void TiledLayer::MarkTilesForUpdate(gfx::Rect* update_rect,
+ gfx::Rect* paint_rect,
+ int left,
+ int top,
+ int right,
+ int bottom,
+ bool ignore_occlusions) {
for (int j = top; j <= bottom; ++j) {
for (int i = left; i <= right; ++i) {
UpdatableTile* tile = TileAt(i, j);
@@ -440,10 +440,14 @@ gfx::Rect TiledLayer::MarkTilesForUpdate(int left,
continue;
if (tile->occluded && !ignore_occlusions)
continue;
+
+ // Prepare update rect from original dirty rects.
+ update_rect->Union(tile->dirty_rect);
+
// TODO(reveman): Decide if partial update should be allowed based on cost
// of update. https://bugs.webkit.org/show_bug.cgi?id=77376
- if (tile->is_dirty() && layer_tree_host() &&
- layer_tree_host()->buffered_updates()) {
+ if (tile->is_dirty() &&
+ !layer_tree_host()->AlwaysUsePartialTextureUpdates()) {
// If we get a partial update, we use the same texture, otherwise return
// the current texture backing, so we don't update visible textures
// non-atomically. If the current backing is in-use, it won't be
@@ -458,14 +462,14 @@ gfx::Rect TiledLayer::MarkTilesForUpdate(int left,
}
}
- paint_rect.Union(tile->dirty_rect);
+ paint_rect->Union(tile->dirty_rect);
tile->MarkForUpdate();
}
}
- return paint_rect;
}
-void TiledLayer::UpdateTileTextures(gfx::Rect paint_rect,
+void TiledLayer::UpdateTileTextures(gfx::Rect update_rect,
+ gfx::Rect paint_rect,
int left,
int top,
int right,
@@ -480,7 +484,7 @@ void TiledLayer::UpdateTileTextures(gfx::Rect paint_rect,
float height_scale =
paint_properties().bounds.height() /
static_cast<float>(content_bounds().height());
- update_rect_ = gfx::ScaleRect(paint_rect, width_scale, height_scale);
+ update_rect_ = gfx::ScaleRect(update_rect, width_scale, height_scale);
// Calling PrepareToUpdate() calls into WebKit to paint, which may have the
// side effect of disabling compositing, which causes our reference to the
@@ -853,6 +857,19 @@ bool TiledLayer::Update(ResourceUpdateQueue* queue,
return updated;
}
+void TiledLayer::OnOutputSurfaceCreated() {
+ // Ensure that all textures are of the right format.
+ for (LayerTilingData::TileMap::const_iterator iter = tiler_->tiles().begin();
+ iter != tiler_->tiles().end();
+ ++iter) {
+ UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second);
+ if (!tile)
+ continue;
+ PrioritizedResource* resource = tile->managed_resource();
+ resource->SetDimensions(resource->size(), texture_format_);
+ }
+}
+
bool TiledLayer::NeedsIdlePaint() {
// Don't trigger more paints if we failed (as we'll just fail again).
if (failed_update_ || visible_content_rect().IsEmpty() ||
diff --git a/chromium/cc/layers/tiled_layer.h b/chromium/cc/layers/tiled_layer.h
index 3870d69956b..82063600c71 100644
--- a/chromium/cc/layers/tiled_layer.h
+++ b/chromium/cc/layers/tiled_layer.h
@@ -36,6 +36,7 @@ class CC_EXPORT TiledLayer : public ContentsScalingLayer {
virtual Region VisibleContentOpaqueRegion() const OVERRIDE;
virtual bool Update(ResourceUpdateQueue* queue,
const OcclusionTracker* occlusion) OVERRIDE;
+ virtual void OnOutputSurfaceCreated() OVERRIDE;
protected:
TiledLayer();
@@ -102,12 +103,15 @@ class CC_EXPORT TiledLayer : public ContentsScalingLayer {
int right,
int bottom,
bool ignore_occlusions);
- gfx::Rect MarkTilesForUpdate(int left,
- int top,
- int right,
- int bottom,
- bool ignore_occlusions);
- void UpdateTileTextures(gfx::Rect paint_rect,
+ void MarkTilesForUpdate(gfx::Rect* update_rect,
+ gfx::Rect* paint_rect,
+ int left,
+ int top,
+ int right,
+ int bottom,
+ bool ignore_occlusions);
+ void UpdateTileTextures(gfx::Rect update_rect,
+ gfx::Rect paint_rect,
int left,
int top,
int right,
diff --git a/chromium/cc/layers/tiled_layer_impl.cc b/chromium/cc/layers/tiled_layer_impl.cc
index e3852129da4..88797c224dd 100644
--- a/chromium/cc/layers/tiled_layer_impl.cc
+++ b/chromium/cc/layers/tiled_layer_impl.cc
@@ -21,17 +21,12 @@
namespace cc {
-// Temporary diagnostic.
-static bool s_safe_to_delete_drawable_tile = false;
-
class DrawableTile : public LayerTilingData::Tile {
public:
static scoped_ptr<DrawableTile> Create() {
return make_scoped_ptr(new DrawableTile());
}
- virtual ~DrawableTile() { CHECK(s_safe_to_delete_drawable_tile); }
-
ResourceProvider::ResourceId resource_id() const { return resource_id_; }
void set_resource_id(ResourceProvider::ResourceId resource_id) {
resource_id_ = resource_id;
@@ -54,10 +49,6 @@ TiledLayerImpl::TiledLayerImpl(LayerTreeImpl* tree_impl, int id)
: LayerImpl(tree_impl, id), skips_draw_(true) {}
TiledLayerImpl::~TiledLayerImpl() {
- s_safe_to_delete_drawable_tile = true;
- if (tiler_)
- tiler_->reset();
- s_safe_to_delete_drawable_tile = false;
}
ResourceProvider::ResourceId TiledLayerImpl::ContentsResourceId() const {
@@ -88,10 +79,6 @@ DrawableTile* TiledLayerImpl::CreateTile(int i, int j) {
DrawableTile* added_tile = tile.get();
tiler_->AddTile(tile.PassAs<LayerTilingData::Tile>(), i, j);
- // Temporary diagnostic checks.
- CHECK(added_tile);
- CHECK(TileAt(i, j));
-
return added_tile;
}
@@ -232,8 +219,9 @@ void TiledLayerImpl::AppendQuads(QuadSink* quad_sink,
continue;
}
- gfx::Rect tile_opaque_rect = contents_opaque() ? tile_rect :
- gfx::IntersectRects(tile->opaque_rect(), content_rect);
+ gfx::Rect tile_opaque_rect =
+ contents_opaque() ? tile_rect : gfx::IntersectRects(
+ tile->opaque_rect(), tile_rect);
// Keep track of how the top left has moved, so the texture can be
// offset the same amount.
@@ -260,8 +248,6 @@ void TiledLayerImpl::AppendQuads(QuadSink* quad_sink,
}
void TiledLayerImpl::SetTilingData(const LayerTilingData& tiler) {
- s_safe_to_delete_drawable_tile = true;
-
if (tiler_) {
tiler_->reset();
} else {
@@ -271,8 +257,6 @@ void TiledLayerImpl::SetTilingData(const LayerTilingData& tiler) {
: LayerTilingData::NO_BORDER_TEXELS);
}
*tiler_ = tiler;
-
- s_safe_to_delete_drawable_tile = false;
}
void TiledLayerImpl::PushTileProperties(
@@ -307,11 +291,7 @@ Region TiledLayerImpl::VisibleContentOpaqueRegion() const {
}
void TiledLayerImpl::DidLoseOutputSurface() {
- s_safe_to_delete_drawable_tile = true;
- // Temporary diagnostic check.
- CHECK(tiler_);
tiler_->reset();
- s_safe_to_delete_drawable_tile = false;
}
const char* TiledLayerImpl::LayerTypeAsString() const {
diff --git a/chromium/cc/layers/tiled_layer_impl_unittest.cc b/chromium/cc/layers/tiled_layer_impl_unittest.cc
index 42913ef70b7..801cbf4dc27 100644
--- a/chromium/cc/layers/tiled_layer_impl_unittest.cc
+++ b/chromium/cc/layers/tiled_layer_impl_unittest.cc
@@ -52,11 +52,15 @@ class TiledLayerImplTest : public testing::Test {
scoped_ptr<TiledLayerImpl> layer =
CreateLayerNoTiles(tile_size, layer_size, border_texels);
+ layer->SetDrawsContent(true);
+
ResourceProvider::ResourceId resource_id = 1;
for (int i = 0; i < layer->TilingForTesting()->num_tiles_x(); ++i) {
for (int j = 0; j < layer->TilingForTesting()->num_tiles_y(); ++j) {
- layer->PushTileProperties(
- i, j, resource_id++, gfx::Rect(0, 0, 1, 1), false);
+ gfx::Rect opaque_rect(
+ layer->TilingForTesting()->tile_bounds(i, j).origin(),
+ gfx::Size(1, 1));
+ layer->PushTileProperties(i, j, resource_id++, opaque_rect, false);
}
}
@@ -266,7 +270,7 @@ TEST_F(TiledLayerImplTest, TextureInfoForLayerNoBorders) {
<< LayerTestCommon::quad_string << i;
EXPECT_EQ(tile_size, quad->texture_size) << LayerTestCommon::quad_string
<< i;
- EXPECT_EQ(gfx::Rect(0, 0, 1, 1), quad->opaque_rect)
+ EXPECT_EQ(gfx::Size(1, 1).ToString(), quad->opaque_rect.size().ToString())
<< LayerTestCommon::quad_string << i;
}
}
diff --git a/chromium/cc/layers/tiled_layer_unittest.cc b/chromium/cc/layers/tiled_layer_unittest.cc
index b6da0769f95..42ef29cc93e 100644
--- a/chromium/cc/layers/tiled_layer_unittest.cc
+++ b/chromium/cc/layers/tiled_layer_unittest.cc
@@ -50,18 +50,23 @@ class TiledLayerTest : public testing::Test {
: proxy_(NULL),
output_surface_(FakeOutputSurface::Create3d()),
queue_(make_scoped_ptr(new ResourceUpdateQueue)),
- fake_layer_impl_tree_host_client_(FakeLayerTreeHostClient::DIRECT_3D),
+ impl_thread_("ImplThread"),
+ fake_layer_tree_host_client_(FakeLayerTreeHostClient::DIRECT_3D),
occlusion_(NULL) {
settings_.max_partial_texture_updates = std::numeric_limits<size_t>::max();
settings_.layer_transforms_should_scale_layer_contents = true;
}
virtual void SetUp() {
- layer_tree_host_ = LayerTreeHost::Create(&fake_layer_impl_tree_host_client_,
- settings_,
- NULL);
+ impl_thread_.Start();
+ layer_tree_host_ = LayerTreeHost::CreateThreaded(
+ &fake_layer_tree_host_client_,
+ NULL,
+ settings_,
+ impl_thread_.message_loop_proxy());
proxy_ = layer_tree_host_->proxy();
resource_manager_ = PrioritizedResourceManager::Create(proxy_);
+ layer_tree_host_->SetLayerTreeHostClientReady();
layer_tree_host_->InitializeOutputSurfaceIfNeeded();
layer_tree_host_->SetRootLayer(Layer::Create());
@@ -70,7 +75,7 @@ class TiledLayerTest : public testing::Test {
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(proxy_);
resource_provider_ =
- ResourceProvider::Create(output_surface_.get(), 0, false);
+ ResourceProvider::Create(output_surface_.get(), NULL, 0, false, 1);
host_impl_ = make_scoped_ptr(new FakeLayerTreeHostImpl(proxy_));
}
@@ -192,7 +197,8 @@ class TiledLayerTest : public testing::Test {
scoped_ptr<ResourceProvider> resource_provider_;
scoped_ptr<ResourceUpdateQueue> queue_;
PriorityCalculator priority_calculator_;
- FakeLayerTreeHostClient fake_layer_impl_tree_host_client_;
+ base::Thread impl_thread_;
+ FakeLayerTreeHostClient fake_layer_tree_host_client_;
scoped_ptr<LayerTreeHost> layer_tree_host_;
scoped_ptr<FakeLayerTreeHostImpl> host_impl_;
scoped_ptr<PrioritizedResourceManager> resource_manager_;
diff --git a/chromium/cc/layers/ui_resource_layer.cc b/chromium/cc/layers/ui_resource_layer.cc
new file mode 100644
index 00000000000..09b8d9af4cc
--- /dev/null
+++ b/chromium/cc/layers/ui_resource_layer.cc
@@ -0,0 +1,165 @@
+// 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/ui_resource_layer.h"
+
+#include "cc/layers/ui_resource_layer_impl.h"
+#include "cc/resources/prioritized_resource.h"
+#include "cc/resources/resource_update.h"
+#include "cc/resources/resource_update_queue.h"
+#include "cc/resources/scoped_ui_resource.h"
+#include "cc/resources/ui_resource_bitmap.h"
+#include "cc/trees/layer_tree_host.h"
+
+namespace cc {
+
+
+namespace {
+
+class ScopedUIResourceHolder : public UIResourceLayer::UIResourceHolder {
+ public:
+ static scoped_ptr<ScopedUIResourceHolder> Create(LayerTreeHost* host,
+ const SkBitmap& skbitmap) {
+ return make_scoped_ptr(new ScopedUIResourceHolder(host, skbitmap));
+ }
+ virtual UIResourceId id() OVERRIDE { return resource_->id(); }
+
+ private:
+ ScopedUIResourceHolder(LayerTreeHost* host, const SkBitmap& skbitmap) {
+ resource_ = ScopedUIResource::Create(host, UIResourceBitmap(skbitmap));
+ }
+
+ scoped_ptr<ScopedUIResource> resource_;
+};
+
+class SharedUIResourceHolder : public UIResourceLayer::UIResourceHolder {
+ public:
+ static scoped_ptr<SharedUIResourceHolder> Create(UIResourceId id) {
+ return make_scoped_ptr(new SharedUIResourceHolder(id));
+ }
+
+ virtual UIResourceId id() OVERRIDE { return id_; }
+
+ private:
+ explicit SharedUIResourceHolder(UIResourceId id) : id_(id) {}
+
+ UIResourceId id_;
+};
+
+} // anonymous namespace
+
+UIResourceLayer::UIResourceHolder::~UIResourceHolder() {}
+
+scoped_refptr<UIResourceLayer> UIResourceLayer::Create() {
+ return make_scoped_refptr(new UIResourceLayer());
+}
+
+UIResourceLayer::UIResourceLayer()
+ : Layer(),
+ uv_top_left_(0.f, 0.f),
+ uv_bottom_right_(1.f, 1.f) {
+ vertex_opacity_[0] = 1.0f;
+ vertex_opacity_[1] = 1.0f;
+ vertex_opacity_[2] = 1.0f;
+ vertex_opacity_[3] = 1.0f;
+}
+
+UIResourceLayer::~UIResourceLayer() {}
+
+scoped_ptr<LayerImpl> UIResourceLayer::CreateLayerImpl(
+ LayerTreeImpl* tree_impl) {
+ return UIResourceLayerImpl::Create(tree_impl, id()).PassAs<LayerImpl>();
+}
+
+void UIResourceLayer::SetUV(gfx::PointF top_left, gfx::PointF bottom_right) {
+ if (uv_top_left_ == top_left && uv_bottom_right_ == bottom_right)
+ return;
+ uv_top_left_ = top_left;
+ uv_bottom_right_ = bottom_right;
+ SetNeedsCommit();
+}
+
+void UIResourceLayer::SetVertexOpacity(float bottom_left,
+ float top_left,
+ float top_right,
+ float bottom_right) {
+ // Indexing according to the quad vertex generation:
+ // 1--2
+ // | |
+ // 0--3
+ if (vertex_opacity_[0] == bottom_left &&
+ vertex_opacity_[1] == top_left &&
+ vertex_opacity_[2] == top_right &&
+ vertex_opacity_[3] == bottom_right)
+ return;
+ vertex_opacity_[0] = bottom_left;
+ vertex_opacity_[1] = top_left;
+ vertex_opacity_[2] = top_right;
+ vertex_opacity_[3] = bottom_right;
+ SetNeedsCommit();
+}
+
+void UIResourceLayer::SetLayerTreeHost(LayerTreeHost* host) {
+ if (host == layer_tree_host())
+ return;
+
+ Layer::SetLayerTreeHost(host);
+
+ // Recreate the resource hold against the new LTH.
+ RecreateUIResourceHolder();
+}
+
+void UIResourceLayer::RecreateUIResourceHolder() {
+ ui_resource_holder_.reset();
+ if (!layer_tree_host() || bitmap_.empty())
+ return;
+
+ ui_resource_holder_ =
+ ScopedUIResourceHolder::Create(layer_tree_host(), bitmap_);
+}
+
+void UIResourceLayer::SetBitmap(const SkBitmap& skbitmap) {
+ bitmap_ = skbitmap;
+
+ RecreateUIResourceHolder();
+ SetNeedsCommit();
+}
+
+void UIResourceLayer::SetUIResourceId(UIResourceId resource_id) {
+ if (ui_resource_holder_ && ui_resource_holder_->id() == resource_id)
+ return;
+
+ if (resource_id) {
+ ui_resource_holder_ = SharedUIResourceHolder::Create(resource_id);
+ } else {
+ ui_resource_holder_.reset();
+ }
+
+ SetNeedsCommit();
+}
+
+bool UIResourceLayer::DrawsContent() const {
+ return ui_resource_holder_ && ui_resource_holder_->id() &&
+ Layer::DrawsContent();
+}
+
+void UIResourceLayer::PushPropertiesTo(LayerImpl* layer) {
+ Layer::PushPropertiesTo(layer);
+ UIResourceLayerImpl* layer_impl = static_cast<UIResourceLayerImpl*>(layer);
+
+ if (!ui_resource_holder_) {
+ layer_impl->SetUIResourceId(0);
+ } else {
+ DCHECK(layer_tree_host());
+
+ gfx::Size image_size =
+ layer_tree_host()->GetUIResourceSize(ui_resource_holder_->id());
+ layer_impl->SetUIResourceId(ui_resource_holder_->id());
+ layer_impl->SetImageBounds(image_size);
+ layer_impl->SetUV(uv_top_left_, uv_bottom_right_);
+ layer_impl->SetVertexOpacity(vertex_opacity_);
+ }
+}
+
+} // namespace cc
diff --git a/chromium/cc/layers/ui_resource_layer.h b/chromium/cc/layers/ui_resource_layer.h
new file mode 100644
index 00000000000..69721a30faa
--- /dev/null
+++ b/chromium/cc/layers/ui_resource_layer.h
@@ -0,0 +1,73 @@
+// 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_LAYERS_UI_RESOURCE_LAYER_H_
+#define CC_LAYERS_UI_RESOURCE_LAYER_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "cc/base/cc_export.h"
+#include "cc/layers/layer.h"
+#include "cc/resources/ui_resource_client.h"
+#include "ui/gfx/rect.h"
+
+namespace cc {
+
+class LayerTreeHost;
+class ScopedUIResource;
+
+class CC_EXPORT UIResourceLayer : public Layer {
+ public:
+ static scoped_refptr<UIResourceLayer> Create();
+
+ virtual bool DrawsContent() const OVERRIDE;
+
+ virtual void PushPropertiesTo(LayerImpl* layer) OVERRIDE;
+
+ virtual void SetLayerTreeHost(LayerTreeHost* host) OVERRIDE;
+
+ void SetBitmap(const SkBitmap& skbitmap);
+
+ // An alternative way of setting the resource to allow for sharing.
+ void SetUIResourceId(UIResourceId resource_id);
+
+ // Sets a UV transform to be used at draw time. Defaults to (0, 0) and (1, 1).
+ void SetUV(gfx::PointF top_left, gfx::PointF bottom_right);
+
+ // Sets an opacity value per vertex. It will be multiplied by the layer
+ // opacity value.
+ void SetVertexOpacity(float bottom_left,
+ float top_left,
+ float top_right,
+ float bottom_right);
+
+ class UIResourceHolder {
+ public:
+ virtual UIResourceId id() = 0;
+ virtual ~UIResourceHolder();
+ };
+
+ protected:
+ UIResourceLayer();
+ virtual ~UIResourceLayer();
+
+ scoped_ptr<UIResourceHolder> ui_resource_holder_;
+ SkBitmap bitmap_;
+
+ gfx::PointF uv_top_left_;
+ gfx::PointF uv_bottom_right_;
+ float vertex_opacity_[4];
+
+ private:
+ virtual scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl)
+ OVERRIDE;
+ void RecreateUIResourceHolder();
+
+
+
+ DISALLOW_COPY_AND_ASSIGN(UIResourceLayer);
+};
+
+} // namespace cc
+
+#endif // CC_LAYERS_UI_RESOURCE_LAYER_H_
diff --git a/chromium/cc/layers/ui_resource_layer_impl.cc b/chromium/cc/layers/ui_resource_layer_impl.cc
new file mode 100644
index 00000000000..2c9a28681ce
--- /dev/null
+++ b/chromium/cc/layers/ui_resource_layer_impl.cc
@@ -0,0 +1,157 @@
+// 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/ui_resource_layer_impl.h"
+
+#include "base/strings/stringprintf.h"
+#include "base/values.h"
+#include "cc/base/math_util.h"
+#include "cc/layers/quad_sink.h"
+#include "cc/quads/texture_draw_quad.h"
+#include "cc/trees/layer_tree_impl.h"
+#include "ui/gfx/rect_f.h"
+
+namespace cc {
+
+UIResourceLayerImpl::UIResourceLayerImpl(LayerTreeImpl* tree_impl, int id)
+ : LayerImpl(tree_impl, id),
+ ui_resource_id_(0),
+ uv_top_left_(0.f, 0.f),
+ uv_bottom_right_(1.f, 1.f) {
+ vertex_opacity_[0] = 1.0f;
+ vertex_opacity_[1] = 1.0f;
+ vertex_opacity_[2] = 1.0f;
+ vertex_opacity_[3] = 1.0f;
+}
+
+UIResourceLayerImpl::~UIResourceLayerImpl() {}
+
+scoped_ptr<LayerImpl> UIResourceLayerImpl::CreateLayerImpl(
+ LayerTreeImpl* tree_impl) {
+ return UIResourceLayerImpl::Create(tree_impl, id()).PassAs<LayerImpl>();
+}
+
+void UIResourceLayerImpl::PushPropertiesTo(LayerImpl* layer) {
+ LayerImpl::PushPropertiesTo(layer);
+ UIResourceLayerImpl* layer_impl = static_cast<UIResourceLayerImpl*>(layer);
+
+ layer_impl->SetUIResourceId(ui_resource_id_);
+ layer_impl->SetImageBounds(image_bounds_);
+ layer_impl->SetUV(uv_top_left_, uv_bottom_right_);
+ layer_impl->SetVertexOpacity(vertex_opacity_);
+}
+
+void UIResourceLayerImpl::SetUIResourceId(UIResourceId uid) {
+ if (uid == ui_resource_id_)
+ return;
+ ui_resource_id_ = uid;
+ NoteLayerPropertyChanged();
+}
+
+void UIResourceLayerImpl::SetImageBounds(gfx::Size image_bounds) {
+ // This check imposes an ordering on the call sequence. An UIResource must
+ // exist before SetImageBounds can be called.
+ DCHECK(ui_resource_id_);
+
+ if (image_bounds_ == image_bounds)
+ return;
+
+ image_bounds_ = image_bounds;
+
+ NoteLayerPropertyChanged();
+}
+
+void UIResourceLayerImpl::SetUV(gfx::PointF top_left,
+ gfx::PointF bottom_right) {
+ if (uv_top_left_ == top_left && uv_bottom_right_ == bottom_right)
+ return;
+ uv_top_left_ = top_left;
+ uv_bottom_right_ = bottom_right;
+ NoteLayerPropertyChanged();
+}
+
+void UIResourceLayerImpl::SetVertexOpacity(const float vertex_opacity[4]) {
+ if (vertex_opacity_[0] == vertex_opacity[0] &&
+ vertex_opacity_[1] == vertex_opacity[1] &&
+ vertex_opacity_[2] == vertex_opacity[2] &&
+ vertex_opacity_[3] == vertex_opacity[3])
+ return;
+ vertex_opacity_[0] = vertex_opacity[0];
+ vertex_opacity_[1] = vertex_opacity[1];
+ vertex_opacity_[2] = vertex_opacity[2];
+ vertex_opacity_[3] = vertex_opacity[3];
+ NoteLayerPropertyChanged();
+}
+
+bool UIResourceLayerImpl::WillDraw(DrawMode draw_mode,
+ ResourceProvider* resource_provider) {
+ if (!ui_resource_id_ || draw_mode == DRAW_MODE_RESOURCELESS_SOFTWARE)
+ return false;
+ return LayerImpl::WillDraw(draw_mode, resource_provider);
+}
+
+void UIResourceLayerImpl::AppendQuads(QuadSink* quad_sink,
+ AppendQuadsData* append_quads_data) {
+ SharedQuadState* shared_quad_state =
+ quad_sink->UseSharedQuadState(CreateSharedQuadState());
+ AppendDebugBorderQuad(quad_sink, shared_quad_state, append_quads_data);
+
+ if (!ui_resource_id_)
+ return;
+
+ ResourceProvider::ResourceId resource =
+ layer_tree_impl()->ResourceIdForUIResource(ui_resource_id_);
+
+ if (!resource)
+ return;
+
+ static const bool flipped = false;
+ static const bool premultiplied_alpha = true;
+
+ DCHECK(!bounds().IsEmpty());
+
+ gfx::Rect quad_rect(bounds());
+
+ bool opaque = layer_tree_impl()->IsUIResourceOpaque(ui_resource_id_) ||
+ contents_opaque();
+ gfx::Rect opaque_rect(opaque ? quad_rect : gfx::Rect());
+ scoped_ptr<TextureDrawQuad> quad;
+
+ quad = TextureDrawQuad::Create();
+ quad->SetNew(shared_quad_state,
+ quad_rect,
+ opaque_rect,
+ resource,
+ premultiplied_alpha,
+ uv_top_left_,
+ uv_bottom_right_,
+ SK_ColorTRANSPARENT,
+ vertex_opacity_,
+ flipped);
+ quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data);
+}
+
+const char* UIResourceLayerImpl::LayerTypeAsString() const {
+ return "cc::UIResourceLayerImpl";
+}
+
+base::DictionaryValue* UIResourceLayerImpl::LayerTreeAsJson() const {
+ base::DictionaryValue* result = LayerImpl::LayerTreeAsJson();
+
+ result->Set("ImageBounds", MathUtil::AsValue(image_bounds_).release());
+
+ base::ListValue* list = new base::ListValue;
+ list->AppendDouble(vertex_opacity_[0]);
+ list->AppendDouble(vertex_opacity_[1]);
+ list->AppendDouble(vertex_opacity_[2]);
+ list->AppendDouble(vertex_opacity_[3]);
+ result->Set("VertexOpacity", list);
+
+ result->Set("UVTopLeft", MathUtil::AsValue(uv_top_left_).release());
+ result->Set("UVBottomRight", MathUtil::AsValue(uv_bottom_right_).release());
+
+ return result;
+}
+
+} // namespace cc
diff --git a/chromium/cc/layers/ui_resource_layer_impl.h b/chromium/cc/layers/ui_resource_layer_impl.h
new file mode 100644
index 00000000000..7f20050e99b
--- /dev/null
+++ b/chromium/cc/layers/ui_resource_layer_impl.h
@@ -0,0 +1,73 @@
+// 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_LAYERS_UI_RESOURCE_LAYER_IMPL_H_
+#define CC_LAYERS_UI_RESOURCE_LAYER_IMPL_H_
+
+#include <string>
+
+#include "cc/base/cc_export.h"
+#include "cc/layers/layer_impl.h"
+#include "cc/resources/resource_provider.h"
+#include "cc/resources/ui_resource_client.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/size.h"
+
+namespace base {
+class DictionaryValue;
+}
+
+namespace cc {
+
+class CC_EXPORT UIResourceLayerImpl : public LayerImpl {
+ public:
+ static scoped_ptr<UIResourceLayerImpl> Create(LayerTreeImpl* tree_impl,
+ int id) {
+ return make_scoped_ptr(new UIResourceLayerImpl(tree_impl, id));
+ }
+ virtual ~UIResourceLayerImpl();
+
+ void SetUIResourceId(UIResourceId uid);
+
+ void SetImageBounds(gfx::Size image_bounds);
+
+ // Sets a UV transform to be used at draw time. Defaults to (0, 0) and (1, 1).
+ void SetUV(gfx::PointF top_left, gfx::PointF bottom_right);
+
+ // Sets an opacity value per vertex. It will be multiplied by the layer
+ // opacity value.
+ void SetVertexOpacity(const float vertex_opacity[4]);
+
+ virtual scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl)
+ OVERRIDE;
+ virtual void PushPropertiesTo(LayerImpl* layer) OVERRIDE;
+
+ virtual bool WillDraw(DrawMode draw_mode,
+ ResourceProvider* resource_provider) OVERRIDE;
+ virtual void AppendQuads(QuadSink* quad_sink,
+ AppendQuadsData* append_quads_data) OVERRIDE;
+
+ virtual base::DictionaryValue* LayerTreeAsJson() const OVERRIDE;
+
+ protected:
+ UIResourceLayerImpl(LayerTreeImpl* tree_impl, int id);
+
+ // The size of the resource bitmap in pixels.
+ gfx::Size image_bounds_;
+
+ UIResourceId ui_resource_id_;
+
+ gfx::PointF uv_top_left_;
+ gfx::PointF uv_bottom_right_;
+ float vertex_opacity_[4];
+
+ private:
+ virtual const char* LayerTypeAsString() const OVERRIDE;
+
+ DISALLOW_COPY_AND_ASSIGN(UIResourceLayerImpl);
+};
+
+} // namespace cc
+
+#endif // CC_LAYERS_UI_RESOURCE_LAYER_IMPL_H_
diff --git a/chromium/cc/layers/ui_resource_layer_impl_unittest.cc b/chromium/cc/layers/ui_resource_layer_impl_unittest.cc
new file mode 100644
index 00000000000..4a2a1164182
--- /dev/null
+++ b/chromium/cc/layers/ui_resource_layer_impl_unittest.cc
@@ -0,0 +1,152 @@
+// 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/append_quads_data.h"
+#include "cc/layers/ui_resource_layer_impl.h"
+#include "cc/resources/ui_resource_bitmap.h"
+#include "cc/resources/ui_resource_client.h"
+#include "cc/test/fake_impl_proxy.h"
+#include "cc/test/fake_layer_tree_host_impl.h"
+#include "cc/test/fake_ui_resource_layer_tree_host_impl.h"
+#include "cc/test/layer_test_common.h"
+#include "cc/test/mock_quad_culler.h"
+#include "cc/trees/single_thread_proxy.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/transform.h"
+
+namespace cc {
+namespace {
+
+scoped_ptr<UIResourceLayerImpl> GenerateUIResourceLayer(
+ FakeUIResourceLayerTreeHostImpl* host_impl,
+ gfx::Size bitmap_size,
+ gfx::Size layer_size,
+ bool opaque,
+ UIResourceId uid) {
+ gfx::Rect visible_content_rect(layer_size);
+ scoped_ptr<UIResourceLayerImpl> layer =
+ UIResourceLayerImpl::Create(host_impl->active_tree(), 1);
+ layer->draw_properties().visible_content_rect = visible_content_rect;
+ layer->SetBounds(layer_size);
+ layer->SetContentBounds(layer_size);
+ layer->CreateRenderSurface();
+ layer->draw_properties().render_target = layer.get();
+
+ SkBitmap skbitmap;
+ skbitmap.setConfig(SkBitmap::kARGB_8888_Config,
+ bitmap_size.width(),
+ bitmap_size.height(),
+ 0,
+ opaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
+ skbitmap.allocPixels();
+ skbitmap.setImmutable();
+ UIResourceBitmap bitmap(skbitmap);
+
+ host_impl->CreateUIResource(uid, bitmap);
+ layer->SetUIResourceId(uid);
+
+ return layer.Pass();
+}
+
+void QuadSizeTest(scoped_ptr<UIResourceLayerImpl> layer,
+ size_t expected_quad_size) {
+ MockQuadCuller quad_culler;
+ AppendQuadsData data;
+ layer->AppendQuads(&quad_culler, &data);
+
+ // Verify quad rects
+ const QuadList& quads = quad_culler.quad_list();
+ EXPECT_EQ(expected_quad_size, quads.size());
+}
+
+TEST(UIResourceLayerImplTest, VerifyDrawQuads) {
+ FakeImplProxy proxy;
+ FakeUIResourceLayerTreeHostImpl host_impl(&proxy);
+ // Make sure we're appending quads when there are valid values.
+ gfx::Size bitmap_size(100, 100);
+ gfx::Size layer_size(100, 100);;
+ size_t expected_quad_size = 1;
+ bool opaque = true;
+ UIResourceId uid = 1;
+ scoped_ptr<UIResourceLayerImpl> layer = GenerateUIResourceLayer(&host_impl,
+ bitmap_size,
+ layer_size,
+ opaque,
+ uid);
+ QuadSizeTest(layer.Pass(), expected_quad_size);
+
+ // Make sure we're not appending quads when there are invalid values.
+ expected_quad_size = 0;
+ uid = 0;
+ layer = GenerateUIResourceLayer(&host_impl,
+ bitmap_size,
+ layer_size,
+ opaque,
+ uid);
+ QuadSizeTest(layer.Pass(), expected_quad_size);
+}
+
+void OpaqueBoundsTest(scoped_ptr<UIResourceLayerImpl> layer,
+ gfx::Rect expected_opaque_bounds) {
+ MockQuadCuller quad_culler;
+ AppendQuadsData data;
+ layer->AppendQuads(&quad_culler, &data);
+
+ // Verify quad rects
+ const QuadList& quads = quad_culler.quad_list();
+ EXPECT_GE(quads.size(), (size_t)0);
+ gfx::Rect opaque_rect = quads.at(0)->opaque_rect;
+ EXPECT_EQ(expected_opaque_bounds, opaque_rect);
+}
+
+TEST(UIResourceLayerImplTest, VerifySetOpaqueOnSkBitmap) {
+ FakeImplProxy proxy;
+ FakeUIResourceLayerTreeHostImpl host_impl(&proxy);
+
+ gfx::Size bitmap_size(100, 100);
+ gfx::Size layer_size(100, 100);;
+ bool opaque = false;
+ UIResourceId uid = 1;
+ scoped_ptr<UIResourceLayerImpl> layer = GenerateUIResourceLayer(&host_impl,
+ bitmap_size,
+ layer_size,
+ opaque,
+ uid);
+ gfx::Rect expected_opaque_bounds;
+ OpaqueBoundsTest(layer.Pass(), expected_opaque_bounds);
+
+ opaque = true;
+ layer = GenerateUIResourceLayer(&host_impl,
+ bitmap_size,
+ layer_size,
+ opaque,
+ uid);
+ expected_opaque_bounds = gfx::Rect(layer->bounds());
+ OpaqueBoundsTest(layer.Pass(), expected_opaque_bounds);
+}
+
+TEST(UIResourceLayerImplTest, VerifySetOpaqueOnLayer) {
+ FakeImplProxy proxy;
+ FakeUIResourceLayerTreeHostImpl host_impl(&proxy);
+
+ gfx::Size bitmap_size(100, 100);
+ gfx::Size layer_size(100, 100);
+ bool skbitmap_opaque = false;
+ UIResourceId uid = 1;
+ scoped_ptr<UIResourceLayerImpl> layer = GenerateUIResourceLayer(
+ &host_impl, bitmap_size, layer_size, skbitmap_opaque, uid);
+ layer->SetContentsOpaque(false);
+ gfx::Rect expected_opaque_bounds;
+ OpaqueBoundsTest(layer.Pass(), expected_opaque_bounds);
+
+ layer = GenerateUIResourceLayer(
+ &host_impl, bitmap_size, layer_size, skbitmap_opaque, uid);
+ layer->SetContentsOpaque(true);
+ expected_opaque_bounds = gfx::Rect(layer->bounds());
+ OpaqueBoundsTest(layer.Pass(), expected_opaque_bounds);
+}
+
+} // namespace
+} // namespace cc
diff --git a/chromium/cc/layers/ui_resource_layer_unittest.cc b/chromium/cc/layers/ui_resource_layer_unittest.cc
new file mode 100644
index 00000000000..48dbdf58f71
--- /dev/null
+++ b/chromium/cc/layers/ui_resource_layer_unittest.cc
@@ -0,0 +1,114 @@
+// 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/ui_resource_layer.h"
+
+#include "cc/debug/overdraw_metrics.h"
+#include "cc/resources/prioritized_resource_manager.h"
+#include "cc/resources/resource_provider.h"
+#include "cc/resources/resource_update_queue.h"
+#include "cc/resources/scoped_ui_resource.h"
+#include "cc/scheduler/texture_uploader.h"
+#include "cc/test/fake_layer_tree_host.h"
+#include "cc/test/fake_layer_tree_host_client.h"
+#include "cc/test/fake_output_surface.h"
+#include "cc/test/fake_output_surface_client.h"
+#include "cc/test/geometry_test_utils.h"
+#include "cc/trees/layer_tree_host.h"
+#include "cc/trees/occlusion_tracker.h"
+#include "cc/trees/single_thread_proxy.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+
+using ::testing::Mock;
+using ::testing::_;
+using ::testing::AtLeast;
+using ::testing::AnyNumber;
+
+namespace cc {
+namespace {
+
+class UIResourceLayerTest : public testing::Test {
+ public:
+ UIResourceLayerTest() : fake_client_(FakeLayerTreeHostClient::DIRECT_3D) {}
+
+ protected:
+ virtual void SetUp() {
+ layer_tree_host_ = FakeLayerTreeHost::Create();
+ layer_tree_host_->InitializeSingleThreaded(&fake_client_);
+ }
+
+ virtual void TearDown() {
+ Mock::VerifyAndClearExpectations(layer_tree_host_.get());
+ }
+
+ scoped_ptr<FakeLayerTreeHost> layer_tree_host_;
+ FakeLayerTreeHostClient fake_client_;
+};
+
+TEST_F(UIResourceLayerTest, SetBitmap) {
+ scoped_refptr<UIResourceLayer> test_layer = UIResourceLayer::Create();
+ ASSERT_TRUE(test_layer.get());
+ test_layer->SetIsDrawable(true);
+ test_layer->SetBounds(gfx::Size(100, 100));
+
+ layer_tree_host_->SetRootLayer(test_layer);
+ Mock::VerifyAndClearExpectations(layer_tree_host_.get());
+ EXPECT_EQ(test_layer->layer_tree_host(), layer_tree_host_.get());
+
+ layer_tree_host_->InitializeOutputSurfaceIfNeeded();
+
+ ResourceUpdateQueue queue;
+ OcclusionTracker occlusion_tracker(gfx::Rect(), false);
+ test_layer->SavePaintProperties();
+ test_layer->Update(&queue, &occlusion_tracker);
+
+ EXPECT_FALSE(test_layer->DrawsContent());
+
+ SkBitmap bitmap;
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config, 10, 10);
+ bitmap.allocPixels();
+ bitmap.setImmutable();
+
+ test_layer->SetBitmap(bitmap);
+ test_layer->Update(&queue, &occlusion_tracker);
+
+ EXPECT_TRUE(test_layer->DrawsContent());
+}
+
+TEST_F(UIResourceLayerTest, SetUIResourceId) {
+ scoped_refptr<UIResourceLayer> test_layer = UIResourceLayer::Create();
+ ASSERT_TRUE(test_layer.get());
+ test_layer->SetIsDrawable(true);
+ test_layer->SetBounds(gfx::Size(100, 100));
+
+ layer_tree_host_->SetRootLayer(test_layer);
+ Mock::VerifyAndClearExpectations(layer_tree_host_.get());
+ EXPECT_EQ(test_layer->layer_tree_host(), layer_tree_host_.get());
+
+ layer_tree_host_->InitializeOutputSurfaceIfNeeded();
+
+ ResourceUpdateQueue queue;
+ OcclusionTracker occlusion_tracker(gfx::Rect(), false);
+ test_layer->SavePaintProperties();
+ test_layer->Update(&queue, &occlusion_tracker);
+
+ EXPECT_FALSE(test_layer->DrawsContent());
+
+ SkBitmap bitmap;
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config, 10, 10);
+ bitmap.allocPixels();
+ bitmap.setImmutable();
+
+ scoped_ptr<ScopedUIResource> resource = ScopedUIResource::Create(
+ layer_tree_host_.get(), UIResourceBitmap(bitmap));
+ test_layer->SetUIResourceId(resource->id());
+ test_layer->Update(&queue, &occlusion_tracker);
+
+ EXPECT_TRUE(test_layer->DrawsContent());
+}
+
+} // namespace
+} // namespace cc
diff --git a/chromium/cc/layers/video_layer_impl.cc b/chromium/cc/layers/video_layer_impl.cc
index 28e470e7c3b..314fed624ca 100644
--- a/chromium/cc/layers/video_layer_impl.cc
+++ b/chromium/cc/layers/video_layer_impl.cc
@@ -18,9 +18,9 @@
#include "cc/trees/proxy.h"
#include "media/base/video_frame.h"
-#if defined(GOOGLE_TV)
+#if defined(VIDEO_HOLE)
#include "cc/quads/solid_color_draw_quad.h"
-#endif
+#endif // defined(VIDEO_HOLE)
namespace cc {
@@ -214,16 +214,16 @@ void VideoLayerImpl::AppendQuads(QuadSink* quad_sink,
DCHECK_EQ(frame_resources_.size(), 1u);
if (frame_resources_.size() < 1u)
break;
- gfx::Transform transform(
- provider_client_impl_->stream_texture_matrix());
- transform.Scale(tex_width_scale, tex_height_scale);
+ gfx::Transform scale;
+ scale.Scale(tex_width_scale, tex_height_scale);
scoped_ptr<StreamVideoDrawQuad> stream_video_quad =
StreamVideoDrawQuad::Create();
- stream_video_quad->SetNew(shared_quad_state,
- quad_rect,
- opaque_rect,
- frame_resources_[0],
- transform);
+ stream_video_quad->SetNew(
+ shared_quad_state,
+ quad_rect,
+ opaque_rect,
+ frame_resources_[0],
+ scale * provider_client_impl_->stream_texture_matrix());
quad_sink->Append(stream_video_quad.PassAs<DrawQuad>(),
append_quads_data);
break;
@@ -245,7 +245,7 @@ void VideoLayerImpl::AppendQuads(QuadSink* quad_sink,
append_quads_data);
break;
}
-#if defined(GOOGLE_TV)
+#if defined(VIDEO_HOLE)
// This block and other blocks wrapped around #if defined(GOOGLE_TV) is not
// maintained by the general compositor team. Please contact the following
// people instead:
@@ -266,7 +266,7 @@ void VideoLayerImpl::AppendQuads(QuadSink* quad_sink,
append_quads_data);
break;
}
-#endif
+#endif // defined(VIDEO_HOLE)
case VideoFrameExternalResources::NONE:
NOTIMPLEMENTED();
break;
diff --git a/chromium/cc/output/begin_frame_args.cc b/chromium/cc/output/begin_frame_args.cc
index d7da76c3bcb..92901afb1f3 100644
--- a/chromium/cc/output/begin_frame_args.cc
+++ b/chromium/cc/output/begin_frame_args.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "cc/output/begin_frame_args.h"
+#include "ui/gfx/frame_time.h"
namespace cc {
@@ -29,20 +30,20 @@ BeginFrameArgs BeginFrameArgs::Create(base::TimeTicks frame_time,
BeginFrameArgs BeginFrameArgs::CreateForSynchronousCompositor() {
// For WebView/SynchronousCompositor, we always want to draw immediately,
// so we set the deadline to 0 and guess that the interval is 16 milliseconds.
- return BeginFrameArgs(base::TimeTicks::Now(),
+ return BeginFrameArgs(gfx::FrameTime::Now(),
base::TimeTicks(),
DefaultInterval());
}
BeginFrameArgs BeginFrameArgs::CreateForTesting() {
- base::TimeTicks now = base::TimeTicks::Now();
+ base::TimeTicks now = gfx::FrameTime::Now();
return BeginFrameArgs(now,
now + (DefaultInterval() / 2),
DefaultInterval());
}
BeginFrameArgs BeginFrameArgs::CreateExpiredForTesting() {
- base::TimeTicks now = base::TimeTicks::Now();
+ base::TimeTicks now = gfx::FrameTime::Now();
return BeginFrameArgs(now,
now - DefaultInterval(),
DefaultInterval());
diff --git a/chromium/cc/output/context_provider.cc b/chromium/cc/output/context_provider.cc
index 7f46f7ccc67..11b4bc5d889 100644
--- a/chromium/cc/output/context_provider.cc
+++ b/chromium/cc/output/context_provider.cc
@@ -9,22 +9,32 @@
namespace cc {
ContextProvider::Capabilities::Capabilities()
- : bind_uniform_location(false),
- discard_backbuffer(false),
- egl_image_external(false),
+ : egl_image_external(false),
fast_npot_mo8_textures(false),
iosurface(false),
map_image(false),
- map_sub(false),
post_sub_buffer(false),
- set_visibility(false),
- shallow_flush(false),
- swapbuffers_complete_callback(false),
texture_format_bgra8888(false),
+ texture_format_etc1(false),
texture_rectangle(false),
texture_storage(false),
texture_usage(false),
discard_framebuffer(false),
max_transfer_buffer_usage_bytes(std::numeric_limits<size_t>::max()) {}
+ContextProvider::Capabilities::Capabilities(
+ const gpu::Capabilities& gpu_capabilities)
+ : egl_image_external(gpu_capabilities.egl_image_external),
+ fast_npot_mo8_textures(gpu_capabilities.fast_npot_mo8_textures),
+ iosurface(gpu_capabilities.iosurface),
+ map_image(gpu_capabilities.map_image),
+ post_sub_buffer(gpu_capabilities.post_sub_buffer),
+ texture_format_bgra8888(gpu_capabilities.texture_format_bgra8888),
+ texture_format_etc1(gpu_capabilities.texture_format_etc1),
+ texture_rectangle(gpu_capabilities.texture_rectangle),
+ texture_storage(gpu_capabilities.texture_storage),
+ texture_usage(gpu_capabilities.texture_usage),
+ discard_framebuffer(gpu_capabilities.discard_framebuffer),
+ max_transfer_buffer_usage_bytes(std::numeric_limits<size_t>::max()) {}
+
} // namespace cc
diff --git a/chromium/cc/output/context_provider.h b/chromium/cc/output/context_provider.h
index c873b58c8d6..0b6d48232c6 100644
--- a/chromium/cc/output/context_provider.h
+++ b/chromium/cc/output/context_provider.h
@@ -8,9 +8,15 @@
#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "cc/base/cc_export.h"
+#include "gpu/command_buffer/common/capabilities.h"
class GrContext;
-namespace WebKit { class WebGraphicsContext3D; }
+
+namespace blink { class WebGraphicsContext3D; }
+namespace gpu {
+class ContextSupport;
+namespace gles2 { class GLES2Interface; }
+}
namespace cc {
struct ManagedMemoryPolicy;
@@ -23,33 +29,38 @@ class ContextProvider : public base::RefCountedThreadSafe<ContextProvider> {
// from the same thread.
virtual bool BindToCurrentThread() = 0;
- virtual WebKit::WebGraphicsContext3D* Context3d() = 0;
+ virtual blink::WebGraphicsContext3D* Context3d() = 0;
+ virtual gpu::gles2::GLES2Interface* ContextGL() = 0;
+ virtual gpu::ContextSupport* ContextSupport() = 0;
virtual class GrContext* GrContext() = 0;
+ virtual void MakeGrContextCurrent() = 0;
struct Capabilities {
- bool bind_uniform_location;
- bool discard_backbuffer;
- bool egl_image_external;
- bool fast_npot_mo8_textures;
- bool iosurface;
- bool map_image;
- bool map_sub;
- bool post_sub_buffer;
- bool set_visibility;
- bool shallow_flush;
- bool swapbuffers_complete_callback;
- bool texture_format_bgra8888;
- bool texture_rectangle;
- bool texture_storage;
- bool texture_usage;
- bool discard_framebuffer;
+ bool egl_image_external : 1;
+ bool fast_npot_mo8_textures : 1;
+ bool iosurface : 1;
+ bool map_image : 1;
+ bool post_sub_buffer : 1;
+ bool texture_format_bgra8888 : 1;
+ bool texture_format_etc1 : 1;
+ bool texture_rectangle : 1;
+ bool texture_storage : 1;
+ bool texture_usage : 1;
+ bool discard_framebuffer : 1;
size_t max_transfer_buffer_usage_bytes;
CC_EXPORT Capabilities();
+
+ // TODO(boliu): Compose a gpu::Capabilities instead and remove this
+ // constructor.
+ explicit CC_EXPORT Capabilities(const gpu::Capabilities& gpu_capabilities);
};
// Returns the capabilities of the currently bound 3d context.
virtual Capabilities ContextCapabilities() = 0;
+ // Checks if the context is currently known to be lost.
+ virtual bool IsContextLost() = 0;
+
// Ask the provider to check if the contexts are valid or lost. If they are,
// this should invalidate the provider so that it can be replaced with a new
// one.
@@ -67,17 +78,10 @@ class ContextProvider : public base::RefCountedThreadSafe<ContextProvider> {
virtual void SetLostContextCallback(
const LostContextCallback& lost_context_callback) = 0;
- // Sets a callback to be called when swap buffers completes. This should be
- // called from the same thread that the context is bound to.
- typedef base::Closure SwapBuffersCompleteCallback;
- virtual void SetSwapBuffersCompleteCallback(
- const SwapBuffersCompleteCallback& swap_buffers_complete_callback) = 0;
-
// Sets a callback to be called when the memory policy changes. This should be
// called from the same thread that the context is bound to.
- typedef base::Callback<void(
- const cc::ManagedMemoryPolicy& policy,
- bool discard_backbuffer_when_not_visible)> MemoryPolicyChangedCallback;
+ typedef base::Callback<void(const ManagedMemoryPolicy& policy)>
+ MemoryPolicyChangedCallback;
virtual void SetMemoryPolicyChangedCallback(
const MemoryPolicyChangedCallback& memory_policy_changed_callback) = 0;
diff --git a/chromium/cc/output/copy_output_request.cc b/chromium/cc/output/copy_output_request.cc
index 6163d5d3c60..50173d5853d 100644
--- a/chromium/cc/output/copy_output_request.cc
+++ b/chromium/cc/output/copy_output_request.cc
@@ -14,6 +14,19 @@
namespace cc {
+// static
+scoped_ptr<CopyOutputRequest> CopyOutputRequest::CreateRelayRequest(
+ const CopyOutputRequest& original_request,
+ const CopyOutputRequestCallback& result_callback) {
+ scoped_ptr<CopyOutputRequest> relay = CreateRequest(result_callback);
+ relay->force_bitmap_result_ = original_request.force_bitmap_result_;
+ relay->has_area_ = original_request.has_area_;
+ relay->area_ = original_request.area_;
+ relay->has_texture_mailbox_ = original_request.has_texture_mailbox_;
+ relay->texture_mailbox_ = original_request.texture_mailbox_;
+ return relay.Pass();
+}
+
CopyOutputRequest::CopyOutputRequest() {}
CopyOutputRequest::CopyOutputRequest(
@@ -21,8 +34,8 @@ CopyOutputRequest::CopyOutputRequest(
const CopyOutputRequestCallback& result_callback)
: force_bitmap_result_(force_bitmap_result),
has_area_(false),
- result_callback_(result_callback) {
-}
+ has_texture_mailbox_(false),
+ result_callback_(result_callback) {}
CopyOutputRequest::~CopyOutputRequest() {
if (!result_callback_.is_null())
@@ -50,4 +63,12 @@ void CopyOutputRequest::SendTextureResult(
size, texture_mailbox, release_callback.Pass()));
}
+void CopyOutputRequest::SetTextureMailbox(
+ const TextureMailbox& texture_mailbox) {
+ DCHECK(!force_bitmap_result_);
+ DCHECK(texture_mailbox.IsTexture());
+ has_texture_mailbox_ = true;
+ texture_mailbox_ = texture_mailbox;
+}
+
} // namespace cc
diff --git a/chromium/cc/output/copy_output_request.h b/chromium/cc/output/copy_output_request.h
index c4a92481dbc..4b74b419fca 100644
--- a/chromium/cc/output/copy_output_request.h
+++ b/chromium/cc/output/copy_output_request.h
@@ -8,6 +8,7 @@
#include "base/callback.h"
#include "base/memory/scoped_ptr.h"
#include "cc/base/cc_export.h"
+#include "cc/resources/texture_mailbox.h"
#include "ui/gfx/rect.h"
class SkBitmap;
@@ -15,7 +16,6 @@ class SkBitmap;
namespace cc {
class CopyOutputResult;
class SingleReleaseCallback;
-class TextureMailbox;
class CC_EXPORT CopyOutputRequest {
public:
@@ -35,13 +35,7 @@ class CC_EXPORT CopyOutputRequest {
}
static scoped_ptr<CopyOutputRequest> CreateRelayRequest(
const CopyOutputRequest& original_request,
- const CopyOutputRequestCallback& result_callback) {
- scoped_ptr<CopyOutputRequest> relay = CreateRequest(result_callback);
- relay->force_bitmap_result_ = original_request.force_bitmap_result_;
- relay->has_area_ = original_request.has_area_;
- relay->area_ = original_request.area_;
- return relay.Pass();
- }
+ const CopyOutputRequestCallback& result_callback);
~CopyOutputRequest();
@@ -59,6 +53,13 @@ class CC_EXPORT CopyOutputRequest {
bool has_area() const { return has_area_; }
gfx::Rect area() const { return area_; }
+ // By default copy requests create a new TextureMailbox to return contents
+ // in. This allows a client to provide a TextureMailbox, and the compositor
+ // will place the result inside the TextureMailbox.
+ void SetTextureMailbox(const TextureMailbox& texture_mailbox);
+ bool has_texture_mailbox() const { return has_texture_mailbox_; }
+ const TextureMailbox& texture_mailbox() const { return texture_mailbox_; }
+
void SendEmptyResult();
void SendBitmapResult(scoped_ptr<SkBitmap> bitmap);
void SendTextureResult(gfx::Size size,
@@ -67,19 +68,16 @@ class CC_EXPORT CopyOutputRequest {
void SendResult(scoped_ptr<CopyOutputResult> result);
- bool Equals(const CopyOutputRequest& other) const {
- return result_callback_.Equals(other.result_callback_) &&
- force_bitmap_result_ == other.force_bitmap_result_;
- }
-
private:
CopyOutputRequest();
- explicit CopyOutputRequest(bool force_bitmap_result,
- const CopyOutputRequestCallback& result_callback);
+ CopyOutputRequest(bool force_bitmap_result,
+ const CopyOutputRequestCallback& result_callback);
bool force_bitmap_result_;
bool has_area_;
+ bool has_texture_mailbox_;
gfx::Rect area_;
+ TextureMailbox texture_mailbox_;
CopyOutputRequestCallback result_callback_;
};
diff --git a/chromium/cc/output/delegating_renderer.cc b/chromium/cc/output/delegating_renderer.cc
index 1b4021fbbc0..1b5716160fa 100644
--- a/chromium/cc/output/delegating_renderer.cc
+++ b/chromium/cc/output/delegating_renderer.cc
@@ -22,11 +22,13 @@
#include "cc/quads/tile_draw_quad.h"
#include "cc/quads/yuv_video_draw_quad.h"
#include "cc/resources/resource_provider.h"
+#include "gpu/command_buffer/client/context_support.h"
+#include "gpu/command_buffer/common/gpu_memory_allocation.h"
#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/khronos/GLES2/gl2ext.h"
-using WebKit::WebGraphicsContext3D;
+using blink::WebGraphicsContext3D;
namespace cc {
@@ -61,22 +63,16 @@ bool DelegatingRenderer::Initialize() {
capabilities_.using_offscreen_context3d = false;
if (!output_surface_->context_provider()) {
- // TODO(danakj): Make software compositing work.
+ capabilities_.using_shared_memory_resources = true;
+ capabilities_.using_map_image = settings_->use_map_image;
return true;
}
- WebGraphicsContext3D* context3d =
- output_surface_->context_provider()->Context3d();
-
- if (!context3d->makeContextCurrent())
- return false;
-
const ContextProvider::Capabilities& caps =
output_surface_->context_provider()->ContextCapabilities();
DCHECK(!caps.iosurface || caps.texture_rectangle);
- capabilities_.using_set_visibility = caps.set_visibility;
capabilities_.using_egl_image = caps.egl_image_external;
capabilities_.using_map_image = settings_->use_map_image && caps.map_image;
@@ -101,16 +97,16 @@ static ResourceProvider::ResourceId AppendToArray(
void DelegatingRenderer::DrawFrame(RenderPassList* render_passes_in_draw_order,
ContextProvider* offscreen_context_provider,
float device_scale_factor,
- bool allow_partial_swap) {
+ gfx::Rect device_viewport_rect,
+ gfx::Rect device_clip_rect,
+ bool allow_partial_swap,
+ bool disable_picture_quad_image_filtering) {
TRACE_EVENT0("cc", "DelegatingRenderer::DrawFrame");
- DCHECK(!frame_for_swap_buffers_.delegated_frame_data);
-
- frame_for_swap_buffers_.metadata = client_->MakeCompositorFrameMetadata();
+ DCHECK(!delegated_frame_data_);
- frame_for_swap_buffers_.delegated_frame_data =
- make_scoped_ptr(new DelegatedFrameData);
- DelegatedFrameData& out_data = *frame_for_swap_buffers_.delegated_frame_data;
+ delegated_frame_data_ = make_scoped_ptr(new DelegatedFrameData);
+ DelegatedFrameData& out_data = *delegated_frame_data_;
// Move the render passes and resources into the |out_frame|.
out_data.render_pass_list.swap(*render_passes_in_draw_order);
@@ -126,11 +122,12 @@ void DelegatingRenderer::DrawFrame(RenderPassList* render_passes_in_draw_order,
resource_provider_->PrepareSendToParent(resources, &out_data.resource_list);
}
-void DelegatingRenderer::SwapBuffers() {
+void DelegatingRenderer::SwapBuffers(const CompositorFrameMetadata& metadata) {
TRACE_EVENT0("cc", "DelegatingRenderer::SwapBuffers");
-
- output_surface_->SwapBuffers(&frame_for_swap_buffers_);
- frame_for_swap_buffers_.delegated_frame_data.reset();
+ CompositorFrame compositor_frame;
+ compositor_frame.metadata = metadata;
+ compositor_frame.delegated_frame_data = delegated_frame_data_.Pass();
+ output_surface_->SwapBuffers(&compositor_frame);
}
void DelegatingRenderer::GetFramebufferPixels(void* pixels, gfx::Rect rect) {
@@ -146,8 +143,7 @@ bool DelegatingRenderer::IsContextLost() {
ContextProvider* context_provider = output_surface_->context_provider();
if (!context_provider)
return false;
- return context_provider->Context3d()->getGraphicsResetStatusARB() !=
- GL_NO_ERROR;
+ return context_provider->IsContextLost();
}
void DelegatingRenderer::SetVisible(bool visible) {
@@ -162,13 +158,11 @@ void DelegatingRenderer::SetVisible(bool visible) {
if (context_provider)
context_provider->Context3d()->flush();
}
- if (capabilities_.using_set_visibility) {
- // We loop visibility to the GPU process, since that's what manages memory.
- // That will allow it to feed us with memory allocations that we can act
- // upon.
- DCHECK(context_provider);
- context_provider->Context3d()->setVisibilityCHROMIUM(visible);
- }
+ // We loop visibility to the GPU process, since that's what manages memory.
+ // That will allow it to feed us with memory allocations that we can act
+ // upon.
+ DCHECK(context_provider);
+ context_provider->ContextSupport()->SetSurfaceVisible(visible);
}
void DelegatingRenderer::SendManagedMemoryStats(size_t bytes_visible,
@@ -180,16 +174,13 @@ void DelegatingRenderer::SendManagedMemoryStats(size_t bytes_visible,
NOTIMPLEMENTED();
return;
}
- WebKit::WebGraphicsManagedMemoryStats stats;
- stats.bytesVisible = bytes_visible;
- stats.bytesVisibleAndNearby = bytes_visible_and_nearby;
- stats.bytesAllocated = bytes_allocated;
- stats.backbufferRequested = false;
- context_provider->Context3d()->sendManagedMemoryStatsCHROMIUM(&stats);
-}
+ gpu::ManagedMemoryStats stats;
+ stats.bytes_required = bytes_visible;
+ stats.bytes_nice_to_have = bytes_visible_and_nearby;
+ stats.bytes_allocated = bytes_allocated;
+ stats.backbuffer_requested = false;
-void DelegatingRenderer::SetDiscardBackBufferWhenNotVisible(bool discard) {
- // Nothing to do, we don't have a back buffer.
+ context_provider->ContextSupport()->SendManagedMemoryStats(stats);
}
} // namespace cc
diff --git a/chromium/cc/output/delegating_renderer.h b/chromium/cc/output/delegating_renderer.h
index 57a2418c452..c18bfa7d7ac 100644
--- a/chromium/cc/output/delegating_renderer.h
+++ b/chromium/cc/output/delegating_renderer.h
@@ -31,11 +31,14 @@ class CC_EXPORT DelegatingRenderer : public Renderer {
virtual void DrawFrame(RenderPassList* render_passes_in_draw_order,
ContextProvider* offscreen_context_provider,
float device_scale_factor,
- bool allow_partial_swap) OVERRIDE;
+ gfx::Rect device_viewport_rect,
+ gfx::Rect device_clip_rect,
+ bool allow_partial_swap,
+ bool disable_picture_quad_image_filtering) OVERRIDE;
virtual void Finish() OVERRIDE {}
- virtual void SwapBuffers() OVERRIDE;
+ virtual void SwapBuffers(const CompositorFrameMetadata& metadata) OVERRIDE;
virtual void ReceiveSwapBuffersAck(const CompositorFrameAck&) OVERRIDE;
virtual void GetFramebufferPixels(void* pixels, gfx::Rect rect) OVERRIDE;
@@ -48,8 +51,6 @@ class CC_EXPORT DelegatingRenderer : public Renderer {
size_t bytes_visible_and_nearby,
size_t bytes_allocated) OVERRIDE;
- virtual void SetDiscardBackBufferWhenNotVisible(bool discard) OVERRIDE;
-
private:
DelegatingRenderer(RendererClient* client,
const LayerTreeSettings* settings,
@@ -60,7 +61,7 @@ class CC_EXPORT DelegatingRenderer : public Renderer {
OutputSurface* output_surface_;
ResourceProvider* resource_provider_;
RendererCapabilities capabilities_;
- CompositorFrame frame_for_swap_buffers_;
+ scoped_ptr<DelegatedFrameData> delegated_frame_data_;
bool visible_;
DISALLOW_COPY_AND_ASSIGN(DelegatingRenderer);
diff --git a/chromium/cc/output/direct_renderer.cc b/chromium/cc/output/direct_renderer.cc
index aad41ed293f..84788c5d13d 100644
--- a/chromium/cc/output/direct_renderer.cc
+++ b/chromium/cc/output/direct_renderer.cc
@@ -28,14 +28,14 @@ static gfx::Transform OrthoProjectionMatrix(float left,
gfx::Transform proj;
if (!delta_x || !delta_y)
return proj;
- proj.matrix().setDouble(0, 0, 2.0f / delta_x);
- proj.matrix().setDouble(0, 3, -(right + left) / delta_x);
- proj.matrix().setDouble(1, 1, 2.0f / delta_y);
- proj.matrix().setDouble(1, 3, -(top + bottom) / delta_y);
+ proj.matrix().set(0, 0, 2.0f / delta_x);
+ proj.matrix().set(0, 3, -(right + left) / delta_x);
+ proj.matrix().set(1, 1, 2.0f / delta_y);
+ proj.matrix().set(1, 3, -(top + bottom) / delta_y);
// Z component of vertices is always set to zero as we don't use the depth
// buffer while drawing.
- proj.matrix().setDouble(2, 2, 0);
+ proj.matrix().set(2, 2, 0);
return proj;
}
@@ -148,35 +148,32 @@ void DirectRenderer::DecideRenderPassAllocationsForFrame(
if (!resource_provider_)
return;
- base::hash_map<RenderPass::Id, const RenderPass*> render_passes_in_frame;
+ base::hash_map<RenderPass::Id, gfx::Size> render_passes_in_frame;
for (size_t i = 0; i < render_passes_in_draw_order.size(); ++i)
- render_passes_in_frame.insert(std::pair<RenderPass::Id, const RenderPass*>(
- render_passes_in_draw_order[i]->id, render_passes_in_draw_order[i]));
+ render_passes_in_frame.insert(std::pair<RenderPass::Id, gfx::Size>(
+ render_passes_in_draw_order[i]->id,
+ RenderPassTextureSize(render_passes_in_draw_order[i])));
std::vector<RenderPass::Id> passes_to_delete;
- base::ScopedPtrHashMap<RenderPass::Id, CachedResource>::const_iterator
+ base::ScopedPtrHashMap<RenderPass::Id, ScopedResource>::const_iterator
pass_iter;
for (pass_iter = render_pass_textures_.begin();
pass_iter != render_pass_textures_.end();
++pass_iter) {
- base::hash_map<RenderPass::Id, const RenderPass*>::const_iterator it =
+ base::hash_map<RenderPass::Id, gfx::Size>::const_iterator it =
render_passes_in_frame.find(pass_iter->first);
if (it == render_passes_in_frame.end()) {
passes_to_delete.push_back(pass_iter->first);
continue;
}
- const RenderPass* render_pass_in_frame = it->second;
- gfx::Size required_size = RenderPassTextureSize(render_pass_in_frame);
- ResourceFormat required_format =
- RenderPassTextureFormat(render_pass_in_frame);
- CachedResource* texture = pass_iter->second;
+ gfx::Size required_size = it->second;
+ ScopedResource* texture = pass_iter->second;
DCHECK(texture);
bool size_appropriate = texture->size().width() >= required_size.width() &&
texture->size().height() >= required_size.height();
- if (texture->id() &&
- (!size_appropriate || texture->format() != required_format))
+ if (texture->id() && !size_appropriate)
texture->Free();
}
@@ -187,8 +184,8 @@ void DirectRenderer::DecideRenderPassAllocationsForFrame(
for (size_t i = 0; i < render_passes_in_draw_order.size(); ++i) {
if (!render_pass_textures_.contains(render_passes_in_draw_order[i]->id)) {
- scoped_ptr<CachedResource> texture =
- CachedResource::Create(resource_provider_);
+ scoped_ptr<ScopedResource> texture =
+ ScopedResource::Create(resource_provider_);
render_pass_textures_.set(render_passes_in_draw_order[i]->id,
texture.Pass());
}
@@ -198,7 +195,10 @@ void DirectRenderer::DecideRenderPassAllocationsForFrame(
void DirectRenderer::DrawFrame(RenderPassList* render_passes_in_draw_order,
ContextProvider* offscreen_context_provider,
float device_scale_factor,
- bool allow_partial_swap) {
+ gfx::Rect device_viewport_rect,
+ gfx::Rect device_clip_rect,
+ bool allow_partial_swap,
+ bool disable_picture_quad_image_filtering) {
TRACE_EVENT0("cc", "DirectRenderer::DrawFrame");
UMA_HISTOGRAM_COUNTS("Renderer4.renderPassCount",
render_passes_in_draw_order->size());
@@ -212,16 +212,19 @@ void DirectRenderer::DrawFrame(RenderPassList* render_passes_in_draw_order,
Capabilities().using_partial_swap && allow_partial_swap
? root_render_pass->damage_rect
: root_render_pass->output_rect;
- frame.root_damage_rect.Intersect(gfx::Rect(client_->DeviceViewport().size()));
+ frame.root_damage_rect.Intersect(gfx::Rect(device_viewport_rect.size()));
+ frame.device_viewport_rect = device_viewport_rect;
+ frame.device_clip_rect = device_clip_rect;
frame.offscreen_context_provider = offscreen_context_provider;
+ frame.disable_picture_quad_image_filtering =
+ disable_picture_quad_image_filtering;
EnsureBackbuffer();
// Only reshape when we know we are going to draw. Otherwise, the reshape
// can leave the window at the wrong size if we never draw and the proper
// viewport size is never set.
- output_surface_->Reshape(client_->DeviceViewport().size(),
- device_scale_factor);
+ output_surface_->Reshape(device_viewport_rect.size(), device_scale_factor);
BeginDrawingFrame(&frame);
for (size_t i = 0; i < render_passes_in_draw_order->size(); ++i) {
@@ -269,11 +272,12 @@ bool DirectRenderer::NeedDeviceClip(const DrawingFrame* frame) const {
if (frame->current_render_pass != frame->root_render_pass)
return false;
- return !client_->DeviceClip().Contains(client_->DeviceViewport());
+ return !frame->device_clip_rect.Contains(frame->device_viewport_rect);
}
-gfx::Rect DirectRenderer::DeviceClipRect(const DrawingFrame* frame) const {
- gfx::Rect device_clip_rect = client_->DeviceClip();
+gfx::Rect DirectRenderer::DeviceClipRectInWindowSpace(const DrawingFrame* frame)
+ const {
+ gfx::Rect device_clip_rect = frame->device_clip_rect;
if (FlippedFramebuffer())
device_clip_rect.set_y(current_surface_size_.height() -
device_clip_rect.bottom());
@@ -287,7 +291,7 @@ void DirectRenderer::SetScissorStateForQuad(const DrawingFrame* frame,
return;
}
if (NeedDeviceClip(frame)) {
- SetScissorTestRect(DeviceClipRect(frame));
+ SetScissorTestRect(DeviceClipRectInWindowSpace(frame));
return;
}
@@ -317,7 +321,7 @@ void DirectRenderer::SetScissorTestRectInDrawSpace(const DrawingFrame* frame,
gfx::RectF draw_space_rect) {
gfx::Rect window_space_rect = MoveFromDrawToWindowSpace(draw_space_rect);
if (NeedDeviceClip(frame))
- window_space_rect.Intersect(DeviceClipRect(frame));
+ window_space_rect.Intersect(DeviceClipRectInWindowSpace(frame));
SetScissorTestRect(window_space_rect);
}
@@ -335,7 +339,7 @@ void DirectRenderer::DrawRenderPass(DrawingFrame* frame,
gfx::RectF render_pass_scissor;
bool draw_rect_covers_full_surface = true;
if (frame->current_render_pass == frame->root_render_pass &&
- !client_->DeviceViewport().Contains(
+ !frame->device_viewport_rect.Contains(
gfx::Rect(output_surface_->SurfaceSize())))
draw_rect_covers_full_surface = false;
@@ -349,7 +353,7 @@ void DirectRenderer::DrawRenderPass(DrawingFrame* frame,
if (frame->current_render_pass != frame->root_render_pass ||
settings_->should_clear_root_render_pass) {
if (NeedDeviceClip(frame)) {
- SetScissorTestRect(DeviceClipRect(frame));
+ SetScissorTestRect(DeviceClipRectInWindowSpace(frame));
draw_rect_covers_full_surface = false;
} else if (!using_scissor_as_optimization) {
EnsureScissorTestDisabled();
@@ -381,12 +385,6 @@ void DirectRenderer::DrawRenderPass(DrawingFrame* frame,
DoDrawQuad(frame, *it);
}
FinishDrawingQuadList();
-
- CachedResource* texture = render_pass_textures_.get(render_pass->id);
- if (texture) {
- texture->set_is_complete(
- !render_pass->has_occlusion_from_outside_target_surface);
- }
}
bool DirectRenderer::UseRenderPass(DrawingFrame* frame,
@@ -398,36 +396,29 @@ bool DirectRenderer::UseRenderPass(DrawingFrame* frame,
BindFramebufferToOutputSurface(frame);
InitializeViewport(frame,
render_pass->output_rect,
- client_->DeviceViewport(),
+ frame->device_viewport_rect,
output_surface_->SurfaceSize());
return true;
}
- if (!resource_provider_)
- return false;
-
- CachedResource* texture = render_pass_textures_.get(render_pass->id);
+ ScopedResource* texture = render_pass_textures_.get(render_pass->id);
DCHECK(texture);
gfx::Size size = RenderPassTextureSize(render_pass);
size.Enlarge(enlarge_pass_texture_amount_.x(),
enlarge_pass_texture_amount_.y());
- if (!texture->id() &&
- !texture->Allocate(size,
- ResourceProvider::TextureUsageFramebuffer,
- RenderPassTextureFormat(render_pass)))
- return false;
+ if (!texture->id())
+ texture->Allocate(
+ size, ResourceProvider::TextureUsageFramebuffer, RGBA_8888);
+ DCHECK(texture->id());
return BindFramebufferToTexture(frame, texture, render_pass->output_rect);
}
-bool DirectRenderer::HaveCachedResourcesForRenderPassId(RenderPass::Id id)
+bool DirectRenderer::HasAllocatedResourcesForTesting(RenderPass::Id id)
const {
- if (!settings_->cache_render_pass_contents)
- return false;
-
- CachedResource* texture = render_pass_textures_.get(id);
- return texture && texture->id() && texture->is_complete();
+ ScopedResource* texture = render_pass_textures_.get(id);
+ return texture && texture->id();
}
// static
@@ -435,10 +426,4 @@ gfx::Size DirectRenderer::RenderPassTextureSize(const RenderPass* render_pass) {
return render_pass->output_rect.size();
}
-// static
-ResourceFormat DirectRenderer::RenderPassTextureFormat(
- const RenderPass* render_pass) {
- return RGBA_8888;
-}
-
} // namespace cc
diff --git a/chromium/cc/output/direct_renderer.h b/chromium/cc/output/direct_renderer.h
index e5ee83c87bd..5c4dc7e23f4 100644
--- a/chromium/cc/output/direct_renderer.h
+++ b/chromium/cc/output/direct_renderer.h
@@ -29,12 +29,15 @@ class CC_EXPORT DirectRenderer : public Renderer {
virtual bool CanReadPixels() const OVERRIDE;
virtual void DecideRenderPassAllocationsForFrame(
const RenderPassList& render_passes_in_draw_order) OVERRIDE;
- virtual bool HaveCachedResourcesForRenderPassId(RenderPass::Id id) const
+ virtual bool HasAllocatedResourcesForTesting(RenderPass::Id id) const
OVERRIDE;
virtual void DrawFrame(RenderPassList* render_passes_in_draw_order,
ContextProvider* offscreen_context_provider,
float device_scale_factor,
- bool allow_partial_swap) OVERRIDE;
+ gfx::Rect device_viewport_rect,
+ gfx::Rect device_clip_rect,
+ bool allow_partial_swap,
+ bool disable_picture_quad_image_filtering) OVERRIDE;
struct CC_EXPORT DrawingFrame {
DrawingFrame();
@@ -45,11 +48,15 @@ class CC_EXPORT DirectRenderer : public Renderer {
const ScopedResource* current_texture;
gfx::RectF root_damage_rect;
+ gfx::Rect device_viewport_rect;
+ gfx::Rect device_clip_rect;
gfx::Transform projection_matrix;
gfx::Transform window_matrix;
ContextProvider* offscreen_context_provider;
+
+ bool disable_picture_quad_image_filtering;
};
void SetEnlargePassTextureAmountForTesting(gfx::Vector2d amount);
@@ -60,28 +67,6 @@ class CC_EXPORT DirectRenderer : public Renderer {
OutputSurface* output_surface,
ResourceProvider* resource_provider);
- class CachedResource : public ScopedResource {
- public:
- static scoped_ptr<CachedResource> Create(
- ResourceProvider* resource_provider) {
- return make_scoped_ptr(new CachedResource(resource_provider));
- }
- virtual ~CachedResource() {}
-
- bool is_complete() const { return is_complete_; }
- void set_is_complete(bool is_complete) { is_complete_ = is_complete; }
-
- protected:
- explicit CachedResource(ResourceProvider* resource_provider)
- : ScopedResource(resource_provider),
- is_complete_(false) {}
-
- private:
- bool is_complete_;
-
- DISALLOW_COPY_AND_ASSIGN(CachedResource);
- };
-
static gfx::RectF QuadVertexRect();
static void QuadRectTransform(gfx::Transform* quad_rect_transform,
const gfx::Transform& quad_transform,
@@ -93,7 +78,7 @@ class CC_EXPORT DirectRenderer : public Renderer {
gfx::Rect MoveFromDrawToWindowSpace(const gfx::RectF& draw_rect) const;
bool NeedDeviceClip(const DrawingFrame* frame) const;
- gfx::Rect DeviceClipRect(const DrawingFrame* frame) const;
+ gfx::Rect DeviceClipRectInWindowSpace(const DrawingFrame* frame) const;
static gfx::RectF ComputeScissorRectForRenderPass(const DrawingFrame* frame);
void SetScissorStateForQuad(const DrawingFrame* frame, const DrawQuad& quad);
void SetScissorStateForQuadWithRenderPassScissor(
@@ -105,7 +90,6 @@ class CC_EXPORT DirectRenderer : public Renderer {
gfx::RectF draw_space_rect);
static gfx::Size RenderPassTextureSize(const RenderPass* render_pass);
- static ResourceFormat RenderPassTextureFormat(const RenderPass* render_pass);
void DrawRenderPass(DrawingFrame* frame,
const RenderPass* render_pass,
@@ -136,7 +120,7 @@ class CC_EXPORT DirectRenderer : public Renderer {
DrawingFrame* frame,
scoped_ptr<CopyOutputRequest> request) = 0;
- base::ScopedPtrHashMap<RenderPass::Id, CachedResource> render_pass_textures_;
+ base::ScopedPtrHashMap<RenderPass::Id, ScopedResource> render_pass_textures_;
OutputSurface* output_surface_;
ResourceProvider* resource_provider_;
diff --git a/chromium/cc/output/filter_operation.cc b/chromium/cc/output/filter_operation.cc
index f4e3dde0ce5..50f111fc2d6 100644
--- a/chromium/cc/output/filter_operation.cc
+++ b/chromium/cc/output/filter_operation.cc
@@ -8,6 +8,7 @@
#include "cc/base/math_util.h"
#include "cc/output/filter_operation.h"
#include "third_party/skia/include/core/SkMath.h"
+#include "ui/gfx/animation/tween.h"
namespace cc {
@@ -21,6 +22,8 @@ bool FilterOperation::operator==(const FilterOperation& other) const {
drop_shadow_offset_ == other.drop_shadow_offset_ &&
drop_shadow_color_ == other.drop_shadow_color_;
}
+ if (type_ == REFERENCE)
+ return image_filter_.get() == other.image_filter_.get();
return amount_ == other.amount_;
}
@@ -32,6 +35,7 @@ FilterOperation::FilterOperation(FilterType type, float amount)
zoom_inset_(0) {
DCHECK_NE(type_, DROP_SHADOW);
DCHECK_NE(type_, COLOR_MATRIX);
+ DCHECK_NE(type_, REFERENCE);
memset(matrix_, 0, sizeof(matrix_));
}
@@ -68,50 +72,30 @@ FilterOperation::FilterOperation(FilterType type, float amount, int inset)
memset(matrix_, 0, sizeof(matrix_));
}
-// TODO(ajuma): Define a version of gfx::Tween::ValueBetween for floats, and use
-// that instead.
-static float BlendFloats(float from, float to, double progress) {
- return from * (1.0 - progress) + to * progress;
+FilterOperation::FilterOperation(
+ FilterType type,
+ const skia::RefPtr<SkImageFilter>& image_filter)
+ : type_(type),
+ amount_(0),
+ drop_shadow_offset_(0, 0),
+ drop_shadow_color_(0),
+ image_filter_(image_filter),
+ zoom_inset_(0) {
+ DCHECK_EQ(type_, REFERENCE);
+ memset(matrix_, 0, sizeof(matrix_));
}
-static int BlendInts(int from, int to, double progress) {
- return static_cast<int>(
- MathUtil::Round(from * (1.0 - progress) + to * progress));
+FilterOperation::FilterOperation(const FilterOperation& other)
+ : type_(other.type_),
+ amount_(other.amount_),
+ drop_shadow_offset_(other.drop_shadow_offset_),
+ drop_shadow_color_(other.drop_shadow_color_),
+ image_filter_(other.image_filter_),
+ zoom_inset_(other.zoom_inset_) {
+ memcpy(matrix_, other.matrix_, sizeof(matrix_));
}
-static uint8_t BlendColorComponents(uint8_t from,
- uint8_t to,
- uint8_t from_alpha,
- uint8_t to_alpha,
- uint8_t blended_alpha,
- double progress) {
- // Since progress can be outside [0, 1], blending can produce a value outside
- // [0, 255].
- int blended_premultiplied = BlendInts(SkMulDiv255Round(from, from_alpha),
- SkMulDiv255Round(to, to_alpha),
- progress);
- int blended = static_cast<int>(
- MathUtil::Round(blended_premultiplied * 255.f / blended_alpha));
- return static_cast<uint8_t>(MathUtil::ClampToRange(blended, 0, 255));
-}
-
-static SkColor BlendSkColors(SkColor from, SkColor to, double progress) {
- int from_a = SkColorGetA(from);
- int to_a = SkColorGetA(to);
- int blended_a = BlendInts(from_a, to_a, progress);
- if (blended_a <= 0)
- return SkColorSetARGB(0, 0, 0, 0);
- blended_a = std::min(blended_a, 255);
-
- // TODO(ajuma): Use SkFourByteInterp once http://crbug.com/260369 is fixed.
- uint8_t blended_r = BlendColorComponents(
- SkColorGetR(from), SkColorGetR(to), from_a, to_a, blended_a, progress);
- uint8_t blended_g = BlendColorComponents(
- SkColorGetG(from), SkColorGetG(to), from_a, to_a, blended_a, progress);
- uint8_t blended_b = BlendColorComponents(
- SkColorGetB(from), SkColorGetB(to), from_a, to_a, blended_a, progress);
-
- return SkColorSetARGB(blended_a, blended_r, blended_g, blended_b);
+FilterOperation::~FilterOperation() {
}
static FilterOperation CreateNoOpFilter(FilterOperation::FilterType type) {
@@ -147,6 +131,9 @@ static FilterOperation CreateNoOpFilter(FilterOperation::FilterType type) {
return FilterOperation::CreateZoomFilter(1.f, 0);
case FilterOperation::SATURATING_BRIGHTNESS:
return FilterOperation::CreateSaturatingBrightnessFilter(0.f);
+ case FilterOperation::REFERENCE:
+ return FilterOperation::CreateReferenceFilter(
+ skia::RefPtr<SkImageFilter>());
}
NOTREACHED();
return FilterOperation::CreateEmptyFilter();
@@ -172,6 +159,7 @@ static float ClampAmountForFilterType(float amount,
case FilterOperation::SATURATING_BRIGHTNESS:
return amount;
case FilterOperation::COLOR_MATRIX:
+ case FilterOperation::REFERENCE:
NOTREACHED();
return amount;
}
@@ -197,22 +185,34 @@ FilterOperation FilterOperation::Blend(const FilterOperation* from,
DCHECK(to_op.type() != FilterOperation::COLOR_MATRIX);
blended_filter.set_type(to_op.type());
+ if (to_op.type() == FilterOperation::REFERENCE) {
+ if (progress > 0.5)
+ blended_filter.set_image_filter(to_op.image_filter());
+ else
+ blended_filter.set_image_filter(from_op.image_filter());
+ return blended_filter;
+ }
+
blended_filter.set_amount(ClampAmountForFilterType(
- BlendFloats(from_op.amount(), to_op.amount(), progress), to_op.type()));
+ gfx::Tween::FloatValueBetween(progress, from_op.amount(), to_op.amount()),
+ to_op.type()));
if (to_op.type() == FilterOperation::DROP_SHADOW) {
- gfx::Point blended_offset(BlendInts(from_op.drop_shadow_offset().x(),
- to_op.drop_shadow_offset().x(),
- progress),
- BlendInts(from_op.drop_shadow_offset().y(),
- to_op.drop_shadow_offset().y(),
- progress));
+ gfx::Point blended_offset(
+ gfx::Tween::LinearIntValueBetween(progress,
+ from_op.drop_shadow_offset().x(),
+ to_op.drop_shadow_offset().x()),
+ gfx::Tween::LinearIntValueBetween(progress,
+ from_op.drop_shadow_offset().y(),
+ to_op.drop_shadow_offset().y()));
blended_filter.set_drop_shadow_offset(blended_offset);
- blended_filter.set_drop_shadow_color(BlendSkColors(
- from_op.drop_shadow_color(), to_op.drop_shadow_color(), progress));
+ blended_filter.set_drop_shadow_color(gfx::Tween::ColorValueBetween(
+ progress, from_op.drop_shadow_color(), to_op.drop_shadow_color()));
} else if (to_op.type() == FilterOperation::ZOOM) {
- blended_filter.set_zoom_inset(std::max(
- BlendInts(from_op.zoom_inset(), to_op.zoom_inset(), progress), 0));
+ blended_filter.set_zoom_inset(
+ std::max(gfx::Tween::LinearIntValueBetween(
+ from_op.zoom_inset(), to_op.zoom_inset(), progress),
+ 0));
}
return blended_filter;
@@ -250,6 +250,18 @@ scoped_ptr<base::Value> FilterOperation::AsValue() const {
value->SetDouble("amount", amount_);
value->SetDouble("inset", zoom_inset_);
break;
+ case FilterOperation::REFERENCE: {
+ int count_inputs = 0;
+ bool can_filter_image_gpu = false;
+ if (image_filter_) {
+ count_inputs = image_filter_->countInputs();
+ can_filter_image_gpu = image_filter_->canFilterImageGPU();
+ }
+ value->SetBoolean("is_null", !image_filter_);
+ value->SetInteger("count_inputs", count_inputs);
+ value->SetBoolean("can_filter_image_gpu", can_filter_image_gpu);
+ break;
+ }
}
return value.PassAs<base::Value>();
}
diff --git a/chromium/cc/output/filter_operation.h b/chromium/cc/output/filter_operation.h
index f56176213b1..f5c6a8264fa 100644
--- a/chromium/cc/output/filter_operation.h
+++ b/chromium/cc/output/filter_operation.h
@@ -8,7 +8,9 @@
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "cc/base/cc_export.h"
+#include "skia/ext/refptr.h"
#include "third_party/skia/include/core/SkColor.h"
+#include "third_party/skia/include/core/SkImageFilter.h"
#include "third_party/skia/include/core/SkScalar.h"
#include "ui/gfx/point.h"
@@ -33,13 +35,19 @@ class CC_EXPORT FilterOperation {
DROP_SHADOW,
COLOR_MATRIX,
ZOOM,
+ REFERENCE,
SATURATING_BRIGHTNESS, // Not used in CSS/SVG.
};
+ FilterOperation(const FilterOperation& other);
+
+ ~FilterOperation();
+
FilterType type() const { return type_; }
float amount() const {
DCHECK_NE(type_, COLOR_MATRIX);
+ DCHECK_NE(type_, REFERENCE);
return amount_;
}
@@ -53,6 +61,11 @@ class CC_EXPORT FilterOperation {
return drop_shadow_color_;
}
+ skia::RefPtr<SkImageFilter> image_filter() const {
+ DCHECK_EQ(type_, REFERENCE);
+ return image_filter_;
+ }
+
const SkScalar* matrix() const {
DCHECK_EQ(type_, COLOR_MATRIX);
return matrix_;
@@ -113,6 +126,11 @@ class CC_EXPORT FilterOperation {
return FilterOperation(ZOOM, amount, inset);
}
+ static FilterOperation CreateReferenceFilter(
+ const skia::RefPtr<SkImageFilter>& image_filter) {
+ return FilterOperation(REFERENCE, image_filter);
+ }
+
static FilterOperation CreateSaturatingBrightnessFilter(float amount) {
return FilterOperation(SATURATING_BRIGHTNESS, amount);
}
@@ -132,6 +150,7 @@ class CC_EXPORT FilterOperation {
void set_amount(float amount) {
DCHECK_NE(type_, COLOR_MATRIX);
+ DCHECK_NE(type_, REFERENCE);
amount_ = amount;
}
@@ -145,6 +164,11 @@ class CC_EXPORT FilterOperation {
drop_shadow_color_ = color;
}
+ void set_image_filter(const skia::RefPtr<SkImageFilter>& image_filter) {
+ DCHECK_EQ(type_, REFERENCE);
+ image_filter_ = image_filter;
+ }
+
void set_matrix(const SkScalar matrix[20]) {
DCHECK_EQ(type_, COLOR_MATRIX);
for (unsigned i = 0; i < 20; ++i)
@@ -180,10 +204,14 @@ class CC_EXPORT FilterOperation {
FilterOperation(FilterType type, float amount, int inset);
+ FilterOperation(FilterType type,
+ const skia::RefPtr<SkImageFilter>& image_filter);
+
FilterType type_;
float amount_;
gfx::Point drop_shadow_offset_;
SkColor drop_shadow_color_;
+ skia::RefPtr<SkImageFilter> image_filter_;
SkScalar matrix_[20];
int zoom_inset_;
};
diff --git a/chromium/cc/output/filter_operations.cc b/chromium/cc/output/filter_operations.cc
index e526f5c419b..21d222e94bf 100644
--- a/chromium/cc/output/filter_operations.cc
+++ b/chromium/cc/output/filter_operations.cc
@@ -59,7 +59,10 @@ void FilterOperations::GetOutsets(int* top,
int* left) const {
*top = *right = *bottom = *left = 0;
for (size_t i = 0; i < operations_.size(); ++i) {
- const FilterOperation op = operations_[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());
@@ -80,11 +83,14 @@ void FilterOperations::GetOutsets(int* top,
bool FilterOperations::HasFilterThatMovesPixels() const {
for (size_t i = 0; i < operations_.size(); ++i) {
- const FilterOperation op = operations_[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:
+ case FilterOperation::REFERENCE:
return true;
case FilterOperation::OPACITY:
case FilterOperation::COLOR_MATRIX:
@@ -104,12 +110,15 @@ bool FilterOperations::HasFilterThatMovesPixels() const {
bool FilterOperations::HasFilterThatAffectsOpacity() const {
for (size_t i = 0; i < operations_.size(); ++i) {
- const FilterOperation op = operations_[i];
+ const FilterOperation& op = operations_[i];
+ // TODO(ajuma): Make this smarter for reference filters. Once SkImageFilter
+ // can report affectsOpacity(), call that.
switch (op.type()) {
case FilterOperation::OPACITY:
case FilterOperation::BLUR:
case FilterOperation::DROP_SHADOW:
case FilterOperation::ZOOM:
+ case FilterOperation::REFERENCE:
return true;
case FilterOperation::COLOR_MATRIX: {
const SkScalar* matrix = op.matrix();
@@ -135,36 +144,53 @@ bool FilterOperations::HasFilterThatAffectsOpacity() const {
return false;
}
+bool FilterOperations::HasReferenceFilter() const {
+ for (size_t i = 0; i < operations_.size(); ++i) {
+ if (operations_[i].type() == FilterOperation::REFERENCE)
+ return true;
+ }
+ return false;
+}
+
FilterOperations FilterOperations::Blend(const FilterOperations& from,
double progress) const {
- FilterOperations blended_filters;
- if (from.size() == 0) {
- for (size_t i = 0; i < size(); i++)
- blended_filters.Append(FilterOperation::Blend(NULL, &at(i), progress));
- return blended_filters;
- }
+ if (HasReferenceFilter() || from.HasReferenceFilter())
+ return *this;
- if (size() == 0) {
- for (size_t i = 0; i < from.size(); i++) {
- blended_filters.Append(
- FilterOperation::Blend(&from.at(i), NULL, progress));
- }
- return blended_filters;
+ bool from_is_longer = from.size() > size();
+
+ size_t shorter_size, longer_size;
+ if (size() == from.size()) {
+ shorter_size = longer_size = size();
+ } else if (from_is_longer) {
+ longer_size = from.size();
+ shorter_size = size();
+ } else {
+ longer_size = size();
+ shorter_size = from.size();
}
- if (from.size() != size())
- return *this;
-
- for (size_t i = 0; i < size(); i++) {
+ for (size_t i = 0; i < shorter_size; i++) {
if (from.at(i).type() != at(i).type())
return *this;
}
- for (size_t i = 0; i < size(); i++) {
+ FilterOperations blended_filters;
+ for (size_t i = 0; i < shorter_size; i++) {
blended_filters.Append(
FilterOperation::Blend(&from.at(i), &at(i), progress));
}
+ if (from_is_longer) {
+ for (size_t i = shorter_size; i < longer_size; i++) {
+ blended_filters.Append(
+ FilterOperation::Blend(&from.at(i), NULL, progress));
+ }
+ } else {
+ for (size_t i = shorter_size; i < longer_size; i++)
+ blended_filters.Append(FilterOperation::Blend(NULL, &at(i), progress));
+ }
+
return blended_filters;
}
diff --git a/chromium/cc/output/filter_operations.h b/chromium/cc/output/filter_operations.h
index aa8d58dd8d2..66f586573ba 100644
--- a/chromium/cc/output/filter_operations.h
+++ b/chromium/cc/output/filter_operations.h
@@ -44,6 +44,7 @@ class CC_EXPORT FilterOperations {
void GetOutsets(int* top, int* right, int* bottom, int* left) const;
bool HasFilterThatMovesPixels() const;
bool HasFilterThatAffectsOpacity() const;
+ bool HasReferenceFilter() const;
size_t size() const {
return operations_.size();
@@ -55,18 +56,18 @@ class CC_EXPORT FilterOperations {
}
// If |from| is of the same size as this, where in each position, the filter
- // in |from| is of the same type as the filter in this, returns a
- // FilterOperations formed by linearly interpolating at each position a
- // |progress| fraction of the way from the filter in |from|
- // to the filter in this. If either |from| or this is an empty sequence,
- // it is treated as a sequence of the same length as the other sequence,
- // where the filter at each position is a no-op filter of the same type
- // as the filter in that position in the other sequence. Otherwise, if
- // both |from| and this are non-empty sequences but are either of different
- // lengths or if there is a type mismatch at some position, returns a copy
- // of this.
+ // in |from| is of the same type as the filter in this, and if this doesn't
+ // contain any reference filters, returns a FilterOperations formed by
+ // linearly interpolating at each position a |progress| fraction of the way
+ // from the filter in |from| to the filter in this. If |from| and this are of
+ // different lengths, they are treated as having the same length by padding
+ // the shorter sequence with no-op filters of the same type as the filters in
+ // the corresponding positions in the longer sequence. If either sequence has
+ // a reference filter or if there is a type mismatch at some position, returns
+ // a copy of this.
FilterOperations Blend(const FilterOperations& from, double progress) const;
+
scoped_ptr<base::Value> AsValue() const;
private:
diff --git a/chromium/cc/output/filter_operations_unittest.cc b/chromium/cc/output/filter_operations_unittest.cc
index dbf3736ccb0..329601fd726 100644
--- a/chromium/cc/output/filter_operations_unittest.cc
+++ b/chromium/cc/output/filter_operations_unittest.cc
@@ -3,7 +3,9 @@
// found in the LICENSE file.
#include "cc/output/filter_operations.h"
+#include "skia/ext/refptr.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/effects/SkBlurImageFilter.h"
#include "ui/gfx/point.h"
namespace cc {
@@ -410,6 +412,11 @@ TEST(FilterOperationsTest, BlendDropShadowFilters) {
gfx::Point(-2, -4), 0.f, SkColorSetARGB(0, 0, 0, 0));
EXPECT_EQ(expected, blended);
+ blended = FilterOperation::Blend(&from, &to, 0.25);
+ expected = FilterOperation::CreateDropShadowFilter(
+ gfx::Point(1, 1), 3.f, SkColorSetARGB(24, 32, 64, 128));
+ EXPECT_EQ(expected, blended);
+
blended = FilterOperation::Blend(&from, &to, 0.75);
expected = FilterOperation::CreateDropShadowFilter(
gfx::Point(2, 4), 5.f, SkColorSetARGB(42, 30, 61, 121));
@@ -497,6 +504,45 @@ TEST(FilterOperationsTest, BlendSaturatingBrightnessWithNull) {
EXPECT_EQ(expected, blended);
}
+TEST(FilterOperationsTest, BlendReferenceFilters) {
+ skia::RefPtr<SkImageFilter> from_filter = skia::AdoptRef(
+ new SkBlurImageFilter(1.f, 1.f));
+ skia::RefPtr<SkImageFilter> to_filter = skia::AdoptRef(
+ new SkBlurImageFilter(2.f, 2.f));
+ FilterOperation from = FilterOperation::CreateReferenceFilter(from_filter);
+ FilterOperation to = FilterOperation::CreateReferenceFilter(to_filter);
+
+ FilterOperation blended = FilterOperation::Blend(&from, &to, -0.75);
+ EXPECT_EQ(from, blended);
+
+ blended = FilterOperation::Blend(&from, &to, 0.5);
+ EXPECT_EQ(from, blended);
+
+ blended = FilterOperation::Blend(&from, &to, 0.6);
+ EXPECT_EQ(to, blended);
+
+ blended = FilterOperation::Blend(&from, &to, 1.5);
+ EXPECT_EQ(to, blended);
+}
+
+TEST(FilterOperationsTest, BlendReferenceWithNull) {
+ skia::RefPtr<SkImageFilter> image_filter = skia::AdoptRef(
+ new SkBlurImageFilter(1.f, 1.f));
+ FilterOperation filter = FilterOperation::CreateReferenceFilter(image_filter);
+ FilterOperation null_filter =
+ FilterOperation::CreateReferenceFilter(skia::RefPtr<SkImageFilter>());
+
+ FilterOperation blended = FilterOperation::Blend(&filter, NULL, 0.25);
+ EXPECT_EQ(filter, blended);
+ blended = FilterOperation::Blend(&filter, NULL, 0.75);
+ EXPECT_EQ(null_filter, blended);
+
+ blended = FilterOperation::Blend(NULL, &filter, 0.25);
+ EXPECT_EQ(null_filter, blended);
+ blended = FilterOperation::Blend(NULL, &filter, 0.75);
+ EXPECT_EQ(filter, blended);
+}
+
// Tests blending non-empty sequences that have the same length and matching
// operations.
TEST(FilterOperationsTest, BlendMatchingSequences) {
@@ -598,8 +644,7 @@ TEST(FilterOperationsTest, BlendEmptySequences) {
EXPECT_EQ(blended, empty);
}
-// Tests blending non-empty sequences that either have different lengths or
-// have non-matching operations.
+// Tests blending non-empty sequences that have non-matching operations.
TEST(FilterOperationsTest, BlendNonMatchingSequences) {
FilterOperations from;
FilterOperations to;
@@ -607,6 +652,7 @@ TEST(FilterOperationsTest, BlendNonMatchingSequences) {
from.Append(FilterOperation::CreateSaturateFilter(3.f));
from.Append(FilterOperation::CreateBlurFilter(2.f));
to.Append(FilterOperation::CreateSaturateFilter(4.f));
+ to.Append(FilterOperation::CreateHueRotateFilter(0.5f));
FilterOperations blended = to.Blend(from, -0.75);
EXPECT_EQ(to, blended);
@@ -614,8 +660,37 @@ TEST(FilterOperationsTest, BlendNonMatchingSequences) {
EXPECT_EQ(to, blended);
blended = to.Blend(from, 1.5);
EXPECT_EQ(to, blended);
+}
- to.Append(FilterOperation::CreateHueRotateFilter(0.5f));
+// Tests blending non-empty sequences of different sizes.
+TEST(FilterOperationsTest, BlendRaggedSequences) {
+ FilterOperations from;
+ FilterOperations to;
+
+ from.Append(FilterOperation::CreateSaturateFilter(3.f));
+ from.Append(FilterOperation::CreateBlurFilter(2.f));
+ to.Append(FilterOperation::CreateSaturateFilter(4.f));
+
+ FilterOperations blended = to.Blend(from, -0.75);
+ FilterOperations expected;
+ expected.Append(FilterOperation::CreateSaturateFilter(2.25f));
+ expected.Append(FilterOperation::CreateBlurFilter(3.5f));
+ EXPECT_EQ(expected, blended);
+
+ blended = to.Blend(from, 0.75);
+ expected.Clear();
+ expected.Append(FilterOperation::CreateSaturateFilter(3.75f));
+ expected.Append(FilterOperation::CreateBlurFilter(0.5f));
+ EXPECT_EQ(expected, blended);
+
+ blended = to.Blend(from, 1.5);
+ expected.Clear();
+ expected.Append(FilterOperation::CreateSaturateFilter(4.5f));
+ expected.Append(FilterOperation::CreateBlurFilter(0.f));
+ EXPECT_EQ(expected, blended);
+
+ from.Append(FilterOperation::CreateOpacityFilter(1.f));
+ to.Append(FilterOperation::CreateOpacityFilter(1.f));
blended = to.Blend(from, -0.75);
EXPECT_EQ(to, blended);
blended = to.Blend(from, 0.75);
diff --git a/chromium/cc/output/geometry_binding.cc b/chromium/cc/output/geometry_binding.cc
index 3b177c2fe20..bf87b1e8900 100644
--- a/chromium/cc/output/geometry_binding.cc
+++ b/chromium/cc/output/geometry_binding.cc
@@ -5,17 +5,15 @@
#include "cc/output/geometry_binding.h"
#include "cc/output/gl_renderer.h" // For the GLC() macro.
-#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "ui/gfx/rect_f.h"
namespace cc {
-GeometryBinding::GeometryBinding(WebKit::WebGraphicsContext3D* context,
+GeometryBinding::GeometryBinding(gpu::gles2::GLES2Interface* gl,
const gfx::RectF& quad_vertex_rect)
- : context_(context),
- quad_vertices_vbo_(0),
- quad_elements_vbo_(0) {
+ : gl_(gl), quad_vertices_vbo_(0), quad_elements_vbo_(0) {
struct Vertex {
float a_position[3];
float a_texCoord[2];
@@ -29,9 +27,8 @@ GeometryBinding::GeometryBinding(WebKit::WebGraphicsContext3D* context,
uint16 data[6];
};
- COMPILE_ASSERT(
- sizeof(Quad) == 24 * sizeof(float), // NOLINT(runtime/sizeof)
- struct_is_densely_packed);
+ COMPILE_ASSERT(sizeof(Quad) == 24 * sizeof(float), // NOLINT(runtime/sizeof)
+ struct_is_densely_packed);
COMPILE_ASSERT(
sizeof(QuadIndex) == 6 * sizeof(uint16_t), // NOLINT(runtime/sizeof)
struct_is_densely_packed);
@@ -39,84 +36,80 @@ GeometryBinding::GeometryBinding(WebKit::WebGraphicsContext3D* context,
Quad quad_list[8];
QuadIndex quad_index_list[8];
for (int i = 0; i < 8; i++) {
- Vertex v0 = { { quad_vertex_rect.x(), quad_vertex_rect.bottom(), 0.0f, },
- { 0.0f, 1.0f, },
- i * 4.0f + 0.0f };
- Vertex v1 = { { quad_vertex_rect.x(), quad_vertex_rect.y(), 0.0f, },
- { 0.0f, 0.0f, },
- i * 4.0f + 1.0f };
- Vertex v2 = { { quad_vertex_rect.right(), quad_vertex_rect.y(), 0.0f, },
- { 1.0f, .0f, },
- i * 4.0f + 2.0f };
- Vertex v3 = { { quad_vertex_rect.right(),
- quad_vertex_rect.bottom(),
- 0.0f, },
- { 1.0f, 1.0f, },
- i * 4.0f + 3.0f };
- Quad x = { v0, v1, v2, v3 };
+ Vertex v0 = {{quad_vertex_rect.x(), quad_vertex_rect.bottom(), 0.0f, },
+ {0.0f, 1.0f, }, i * 4.0f + 0.0f};
+ Vertex v1 = {{quad_vertex_rect.x(), quad_vertex_rect.y(), 0.0f, },
+ {0.0f, 0.0f, }, i * 4.0f + 1.0f};
+ Vertex v2 = {{quad_vertex_rect.right(), quad_vertex_rect.y(), 0.0f, },
+ {1.0f, .0f, }, i * 4.0f + 2.0f};
+ Vertex v3 = {{quad_vertex_rect.right(), quad_vertex_rect.bottom(), 0.0f, },
+ {1.0f, 1.0f, }, i * 4.0f + 3.0f};
+ Quad x = {v0, v1, v2, v3};
quad_list[i] = x;
- QuadIndex y = { { static_cast<uint16>(0 + 4 * i),
- static_cast<uint16>(1 + 4 * i),
- static_cast<uint16>(2 + 4 * i),
- static_cast<uint16>(3 + 4 * i),
- static_cast<uint16>(0 + 4 * i),
- static_cast<uint16>(2 + 4 * i) } };
+ QuadIndex y = {
+ {static_cast<uint16>(0 + 4 * i), static_cast<uint16>(1 + 4 * i),
+ static_cast<uint16>(2 + 4 * i), static_cast<uint16>(3 + 4 * i),
+ static_cast<uint16>(0 + 4 * i), static_cast<uint16>(2 + 4 * i)}};
quad_index_list[i] = y;
}
- GLC(context_, quad_vertices_vbo_ = context_->createBuffer());
- GLC(context_, quad_elements_vbo_ = context_->createBuffer());
- GLC(context_, context_->bindBuffer(GL_ARRAY_BUFFER, quad_vertices_vbo_));
- GLC(context_,
- context_->bufferData(
+ gl_->GenBuffers(1, &quad_vertices_vbo_);
+ gl_->GenBuffers(1, &quad_elements_vbo_);
+ GLC(gl_, gl_->BindBuffer(GL_ARRAY_BUFFER, quad_vertices_vbo_));
+ GLC(gl_,
+ gl_->BufferData(
GL_ARRAY_BUFFER, sizeof(quad_list), quad_list, GL_STATIC_DRAW));
- GLC(context_,
- context_->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, quad_elements_vbo_));
- GLC(context_,
- context_->bufferData(GL_ELEMENT_ARRAY_BUFFER,
- sizeof(quad_index_list),
- quad_index_list,
- GL_STATIC_DRAW));
+ GLC(gl_, gl_->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, quad_elements_vbo_));
+ GLC(gl_,
+ gl_->BufferData(GL_ELEMENT_ARRAY_BUFFER,
+ sizeof(quad_index_list),
+ quad_index_list,
+ GL_STATIC_DRAW));
}
GeometryBinding::~GeometryBinding() {
- GLC(context_, context_->deleteBuffer(quad_vertices_vbo_));
- GLC(context_, context_->deleteBuffer(quad_elements_vbo_));
+ gl_->DeleteBuffers(1, &quad_vertices_vbo_);
+ gl_->DeleteBuffers(1, &quad_elements_vbo_);
}
void GeometryBinding::PrepareForDraw() {
- GLC(context_,
- context_->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, quad_elements_vbo_));
+ GLC(gl_, gl_->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, quad_elements_vbo_));
+
+ GLC(gl_, gl_->BindBuffer(GL_ARRAY_BUFFER, quad_vertices_vbo_));
+ // OpenGL defines the last parameter to VertexAttribPointer as type
+ // "const GLvoid*" even though it is actually an offset into the buffer
+ // object's data store and not a pointer to the client's address space.
+ const void* offsets[3] = {
+ 0, reinterpret_cast<const void*>(
+ 3 * sizeof(float)), // NOLINT(runtime/sizeof)
+ reinterpret_cast<const void*>(5 *
+ sizeof(float)), // NOLINT(runtime/sizeof)
+ };
- GLC(context_, context_->bindBuffer(GL_ARRAY_BUFFER, quad_vertices_vbo_));
- GLC(context_,
- context_->vertexAttribPointer(
- PositionAttribLocation(),
- 3,
- GL_FLOAT,
- false,
- 6 * sizeof(float), // NOLINT(runtime/sizeof)
- 0));
- GLC(context_,
- context_->vertexAttribPointer(
- TexCoordAttribLocation(),
- 2,
- GL_FLOAT,
- false,
- 6 * sizeof(float), // NOLINT(runtime/sizeof)
- 3 * sizeof(float))); // NOLINT(runtime/sizeof)
- GLC(context_,
- context_->vertexAttribPointer(
- TriangleIndexAttribLocation(),
- 1,
- GL_FLOAT,
- false,
- 6 * sizeof(float), // NOLINT(runtime/sizeof)
- 5 * sizeof(float))); // NOLINT(runtime/sizeof)
- GLC(context_, context_->enableVertexAttribArray(PositionAttribLocation()));
- GLC(context_, context_->enableVertexAttribArray(TexCoordAttribLocation()));
- GLC(context_,
- context_->enableVertexAttribArray(TriangleIndexAttribLocation()));
+ GLC(gl_,
+ gl_->VertexAttribPointer(PositionAttribLocation(),
+ 3,
+ GL_FLOAT,
+ false,
+ 6 * sizeof(float), // NOLINT(runtime/sizeof)
+ offsets[0]));
+ GLC(gl_,
+ gl_->VertexAttribPointer(TexCoordAttribLocation(),
+ 2,
+ GL_FLOAT,
+ false,
+ 6 * sizeof(float), // NOLINT(runtime/sizeof)
+ offsets[1]));
+ GLC(gl_,
+ gl_->VertexAttribPointer(TriangleIndexAttribLocation(),
+ 1,
+ GL_FLOAT,
+ false,
+ 6 * sizeof(float), // NOLINT(runtime/sizeof)
+ offsets[2]));
+ GLC(gl_, gl_->EnableVertexAttribArray(PositionAttribLocation()));
+ GLC(gl_, gl_->EnableVertexAttribArray(TexCoordAttribLocation()));
+ GLC(gl_, gl_->EnableVertexAttribArray(TriangleIndexAttribLocation()));
}
} // namespace cc
diff --git a/chromium/cc/output/geometry_binding.h b/chromium/cc/output/geometry_binding.h
index 2318b27ecff..cfa21efd1fc 100644
--- a/chromium/cc/output/geometry_binding.h
+++ b/chromium/cc/output/geometry_binding.h
@@ -6,16 +6,22 @@
#define CC_OUTPUT_GEOMETRY_BINDING_H_
#include "base/basictypes.h"
+#include "third_party/khronos/GLES2/gl2.h"
-namespace gfx { class RectF; }
-
-namespace WebKit { class WebGraphicsContext3D; }
+namespace gfx {
+class RectF;
+}
+namespace gpu {
+namespace gles2 {
+class GLES2Interface;
+}
+}
namespace cc {
class GeometryBinding {
public:
- GeometryBinding(WebKit::WebGraphicsContext3D* context,
+ GeometryBinding(gpu::gles2::GLES2Interface* gl,
const gfx::RectF& quad_vertex_rect);
~GeometryBinding();
@@ -29,10 +35,10 @@ class GeometryBinding {
static int TriangleIndexAttribLocation() { return 2; }
private:
- WebKit::WebGraphicsContext3D* context_;
+ gpu::gles2::GLES2Interface* gl_;
- unsigned quad_vertices_vbo_;
- unsigned quad_elements_vbo_;
+ GLuint quad_vertices_vbo_;
+ GLuint quad_elements_vbo_;
DISALLOW_COPY_AND_ASSIGN(GeometryBinding);
};
diff --git a/chromium/cc/output/gl_renderer.cc b/chromium/cc/output/gl_renderer.cc
index f4b1e575d39..f0e32f43083 100644
--- a/chromium/cc/output/gl_renderer.cc
+++ b/chromium/cc/output/gl_renderer.cc
@@ -16,6 +16,7 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "build/build_config.h"
+#include "cc/base/util.h"
#include "cc/base/math_util.h"
#include "cc/layers/video_layer_impl.h"
#include "cc/output/compositor_frame.h"
@@ -32,12 +33,14 @@
#include "cc/quads/texture_draw_quad.h"
#include "cc/resources/layer_quad.h"
#include "cc/resources/scoped_resource.h"
-#include "cc/resources/sync_point_helper.h"
#include "cc/resources/texture_mailbox_deleter.h"
#include "cc/trees/damage_tracker.h"
#include "cc/trees/proxy.h"
#include "cc/trees/single_thread_proxy.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/common/gpu_memory_allocation.h"
#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/khronos/GLES2/gl2ext.h"
@@ -53,7 +56,8 @@
#include "ui/gfx/quad_f.h"
#include "ui/gfx/rect_conversions.h"
-using WebKit::WebGraphicsContext3D;
+using blink::WebGraphicsContext3D;
+using gpu::gles2::GLES2Interface;
namespace cc {
@@ -71,6 +75,7 @@ class SimpleSwapFence : public ResourceProvider::Fence {
SimpleSwapFence() : has_passed_(false) {}
virtual bool HasPassed() OVERRIDE { return has_passed_; }
void SetHasPassed() { has_passed_ = true; }
+
private:
virtual ~SimpleSwapFence() {}
bool has_passed_;
@@ -89,7 +94,7 @@ bool NeedsIOSurfaceReadbackWorkaround() {
Float4 UVTransform(const TextureDrawQuad* quad) {
gfx::PointF uv0 = quad->uv_top_left;
gfx::PointF uv1 = quad->uv_bottom_right;
- Float4 xform = { { uv0.x(), uv0.y(), uv1.x() - uv0.x(), uv1.y() - uv0.y() } };
+ Float4 xform = {{uv0.x(), uv0.y(), uv1.x() - uv0.x(), uv1.y() - uv0.y()}};
if (quad->flipped) {
xform.data[1] = 1.0f - xform.data[1];
xform.data[3] = -xform.data[3];
@@ -101,15 +106,26 @@ Float4 PremultipliedColor(SkColor color) {
const float factor = 1.0f / 255.0f;
const float alpha = SkColorGetA(color) * factor;
- Float4 result = { {
- SkColorGetR(color) * factor * alpha,
- SkColorGetG(color) * factor * alpha,
- SkColorGetB(color) * factor * alpha,
- alpha
- } };
+ Float4 result = {
+ {SkColorGetR(color) * factor * alpha, SkColorGetG(color) * factor * alpha,
+ SkColorGetB(color) * factor * alpha, alpha}};
return result;
}
+SamplerType SamplerTypeFromTextureTarget(GLenum target) {
+ switch (target) {
+ case GL_TEXTURE_2D:
+ return SamplerType2D;
+ case GL_TEXTURE_RECTANGLE_ARB:
+ return SamplerType2DRect;
+ case GL_TEXTURE_EXTERNAL_OES:
+ return SamplerTypeExternalOES;
+ default:
+ NOTREACHED();
+ return SamplerType2D;
+ }
+}
+
// Smallest unit that impact anti-aliasing output. We use this to
// determine when anti-aliasing is unnecessary.
const float kAntiAliasingEpsilon = 1.0f / 1024.0f;
@@ -133,23 +149,13 @@ scoped_ptr<GLRenderer> GLRenderer::Create(
OutputSurface* output_surface,
ResourceProvider* resource_provider,
TextureMailboxDeleter* texture_mailbox_deleter,
- int highp_threshold_min,
- bool use_skia_gpu_backend) {
- scoped_ptr<GLRenderer> renderer(new GLRenderer(client,
- settings,
- output_surface,
- resource_provider,
- texture_mailbox_deleter,
- highp_threshold_min));
- if (!renderer->Initialize())
- return scoped_ptr<GLRenderer>();
- if (use_skia_gpu_backend) {
- renderer->InitializeGrContext();
- DCHECK(renderer->CanUseSkiaGPUBackend())
- << "Requested Skia GPU backend, but can't use it.";
- }
-
- return renderer.Pass();
+ int highp_threshold_min) {
+ return make_scoped_ptr(new GLRenderer(client,
+ settings,
+ output_surface,
+ resource_provider,
+ texture_mailbox_deleter,
+ highp_threshold_min));
}
GLRenderer::GLRenderer(RendererClient* client,
@@ -162,32 +168,27 @@ GLRenderer::GLRenderer(RendererClient* client,
offscreen_framebuffer_id_(0),
shared_geometry_quad_(gfx::RectF(-0.5f, -0.5f, 1.0f, 1.0f)),
context_(output_surface->context_provider()->Context3d()),
+ gl_(output_surface->context_provider()->ContextGL()),
+ context_support_(output_surface->context_provider()->ContextSupport()),
texture_mailbox_deleter_(texture_mailbox_deleter),
is_backbuffer_discarded_(false),
- discard_backbuffer_when_not_visible_(false),
- is_using_bind_uniform_(false),
visible_(true),
is_scissor_enabled_(false),
+ scissor_rect_needs_reset_(true),
stencil_shadow_(false),
blend_shadow_(false),
highp_threshold_min_(highp_threshold_min),
highp_threshold_cache_(0),
on_demand_tile_raster_resource_id_(0) {
DCHECK(context_);
-}
-
-bool GLRenderer::Initialize() {
- if (!context_->makeContextCurrent())
- return false;
+ DCHECK(context_support_);
ContextProvider::Capabilities context_caps =
- output_surface_->context_provider()->ContextCapabilities();
+ output_surface_->context_provider()->ContextCapabilities();
capabilities_.using_partial_swap =
settings_->partial_swap_enabled && context_caps.post_sub_buffer;
- capabilities_.using_set_visibility = context_caps.set_visibility;
-
DCHECK(!context_caps.iosurface || context_caps.texture_rectangle);
capabilities_.using_egl_image = context_caps.egl_image_external;
@@ -207,29 +208,9 @@ bool GLRenderer::Initialize() {
capabilities_.using_map_image =
settings_->use_map_image && context_caps.map_image;
- capabilities_.using_discard_framebuffer =
- context_caps.discard_framebuffer;
-
- is_using_bind_uniform_ = context_caps.bind_uniform_location;
+ capabilities_.using_discard_framebuffer = context_caps.discard_framebuffer;
- if (!InitializeSharedObjects())
- return false;
-
- // Make sure the viewport and context gets initialized, even if it is to zero.
- ViewportChanged();
- return true;
-}
-
-void GLRenderer::InitializeGrContext() {
- skia::RefPtr<GrGLInterface> interface = skia::AdoptRef(
- context_->createGrGLInterface());
- if (!interface)
- return;
-
- gr_context_ = skia::AdoptRef(GrContext::Create(
- kOpenGL_GrBackend,
- reinterpret_cast<GrBackendContext>(interface.get())));
- ReinitializeGrCanvas();
+ InitializeSharedObjects();
}
GLRenderer::~GLRenderer() {
@@ -248,11 +229,11 @@ const RendererCapabilities& GLRenderer::Capabilities() const {
WebGraphicsContext3D* GLRenderer::Context() { return context_; }
-void GLRenderer::DebugGLCall(WebGraphicsContext3D* context,
+void GLRenderer::DebugGLCall(GLES2Interface* gl,
const char* command,
const char* file,
int line) {
- unsigned error = context->getError();
+ GLuint error = gl->GetError();
if (error != GL_NO_ERROR)
LOG(ERROR) << "GL command failed: File: " << file << "\n\tLine " << line
<< "\n\tcommand: " << command << ", error "
@@ -266,30 +247,22 @@ void GLRenderer::SetVisible(bool visible) {
EnforceMemoryPolicy();
- // TODO(jamesr): Replace setVisibilityCHROMIUM() with an extension to
- // explicitly manage front/backbuffers
- // crbug.com/116049
- if (capabilities_.using_set_visibility)
- context_->setVisibilityCHROMIUM(visible);
+ context_support_->SetSurfaceVisible(visible);
}
void GLRenderer::SendManagedMemoryStats(size_t bytes_visible,
size_t bytes_visible_and_nearby,
size_t bytes_allocated) {
- WebKit::WebGraphicsManagedMemoryStats stats;
- stats.bytesVisible = bytes_visible;
- stats.bytesVisibleAndNearby = bytes_visible_and_nearby;
- stats.bytesAllocated = bytes_allocated;
- stats.backbufferRequested = !is_backbuffer_discarded_;
- context_->sendManagedMemoryStatsCHROMIUM(&stats);
+ gpu::ManagedMemoryStats stats;
+ stats.bytes_required = bytes_visible;
+ stats.bytes_nice_to_have = bytes_visible_and_nearby;
+ stats.bytes_allocated = bytes_allocated;
+ stats.backbuffer_requested = !is_backbuffer_discarded_;
+ context_support_->SendManagedMemoryStats(stats);
}
void GLRenderer::ReleaseRenderPassTextures() { render_pass_textures_.clear(); }
-void GLRenderer::ViewportChanged() {
- ReinitializeGrCanvas();
-}
-
void GLRenderer::DiscardPixels(bool has_external_stencil_test,
bool draw_rect_covers_full_surface) {
if (has_external_stencil_test || !draw_rect_covers_full_surface ||
@@ -300,7 +273,7 @@ void GLRenderer::DiscardPixels(bool has_external_stencil_test,
output_surface_->capabilities().uses_default_gl_framebuffer;
GLenum attachments[] = {static_cast<GLenum>(
using_default_framebuffer ? GL_COLOR_EXT : GL_COLOR_ATTACHMENT0_EXT)};
- context_->discardFramebufferEXT(
+ gl_->DiscardFramebufferEXT(
GL_FRAMEBUFFER, arraysize(attachments), attachments);
}
@@ -316,9 +289,9 @@ void GLRenderer::ClearFramebuffer(DrawingFrame* frame,
// On DEBUG builds, opaque render passes are cleared to blue to easily see
// regions that were not drawn on the screen.
if (frame->current_render_pass->has_transparent_background)
- GLC(context_, context_->clearColor(0, 0, 0, 0));
+ GLC(gl_, gl_->ClearColor(0, 0, 0, 0));
else
- GLC(context_, context_->clearColor(0, 0, 1, 1));
+ GLC(gl_, gl_->ClearColor(0, 0, 1, 1));
bool always_clear = false;
#ifndef NDEBUG
@@ -326,30 +299,25 @@ void GLRenderer::ClearFramebuffer(DrawingFrame* frame,
#endif
if (always_clear || frame->current_render_pass->has_transparent_background) {
GLbitfield clear_bits = GL_COLOR_BUFFER_BIT;
- // Only the Skia GPU backend uses the stencil buffer. No need to clear it
- // otherwise.
- if (always_clear || CanUseSkiaGPUBackend()) {
- GLC(context_, context_->clearStencil(0));
+ if (always_clear)
clear_bits |= GL_STENCIL_BUFFER_BIT;
- }
- context_->clear(clear_bits);
+ gl_->Clear(clear_bits);
}
}
void GLRenderer::BeginDrawingFrame(DrawingFrame* frame) {
- if (client_->DeviceViewport().IsEmpty())
+ if (frame->device_viewport_rect.IsEmpty())
return;
- TRACE_EVENT0("cc", "GLRenderer::DrawLayers");
-
- MakeContextCurrent();
+ TRACE_EVENT0("cc", "GLRenderer::BeginDrawingFrame");
+ // TODO(enne): Do we need to reinitialize all of this state per frame?
ReinitializeGLState();
}
void GLRenderer::DoNoOp() {
- GLC(context_, context_->bindFramebuffer(GL_FRAMEBUFFER, 0));
- GLC(context_, context_->flush());
+ GLC(gl_, gl_->BindFramebuffer(GL_FRAMEBUFFER, 0));
+ GLC(gl_, gl_->Flush());
}
void GLRenderer::DoDrawQuad(DrawingFrame* frame, const DrawQuad* quad) {
@@ -404,12 +372,12 @@ void GLRenderer::DrawCheckerboardQuad(const DrawingFrame* frame,
SetUseProgram(program->program());
SkColor color = quad->color;
- GLC(Context(),
- Context()->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));
+ GLC(gl_,
+ 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 checkerboard_width = 16;
float frequency = 1.0f / checkerboard_width;
@@ -419,16 +387,16 @@ void GLRenderer::DrawCheckerboardQuad(const DrawingFrame* frame,
float tex_offset_y = tile_rect.y() % checkerboard_width;
float tex_scale_x = tile_rect.width();
float tex_scale_y = tile_rect.height();
- GLC(Context(),
- Context()->uniform4f(program->fragment_shader().tex_transform_location(),
- tex_offset_x,
- tex_offset_y,
- tex_scale_x,
- tex_scale_y));
+ GLC(gl_,
+ gl_->Uniform4f(program->fragment_shader().tex_transform_location(),
+ tex_offset_x,
+ tex_offset_y,
+ tex_scale_x,
+ tex_scale_y));
- GLC(Context(),
- Context()->uniform1f(program->fragment_shader().frequency_location(),
- frequency));
+ GLC(gl_,
+ gl_->Uniform1f(program->fragment_shader().frequency_location(),
+ frequency));
SetShaderOpacity(quad->opacity(),
program->fragment_shader().alpha_location());
@@ -456,66 +424,25 @@ void GLRenderer::DrawDebugBorderQuad(const DrawingFrame* frame,
render_matrix.Scale(layer_rect.width(), layer_rect.height());
GLRenderer::ToGLMatrix(&gl_matrix[0],
frame->projection_matrix * render_matrix);
- GLC(Context(),
- Context()->uniformMatrix4fv(
+ GLC(gl_,
+ gl_->UniformMatrix4fv(
program->vertex_shader().matrix_location(), 1, false, &gl_matrix[0]));
SkColor color = quad->color;
float alpha = SkColorGetA(color) * (1.0f / 255.0f);
- GLC(Context(),
- Context()->uniform4f(program->fragment_shader().color_location(),
- (SkColorGetR(color) * (1.0f / 255.0f)) * alpha,
- (SkColorGetG(color) * (1.0f / 255.0f)) * alpha,
- (SkColorGetB(color) * (1.0f / 255.0f)) * alpha,
- alpha));
+ GLC(gl_,
+ gl_->Uniform4f(program->fragment_shader().color_location(),
+ (SkColorGetR(color) * (1.0f / 255.0f)) * alpha,
+ (SkColorGetG(color) * (1.0f / 255.0f)) * alpha,
+ (SkColorGetB(color) * (1.0f / 255.0f)) * alpha,
+ alpha));
- GLC(Context(), Context()->lineWidth(quad->width));
+ GLC(gl_, gl_->LineWidth(quad->width));
// The indices for the line are stored in the same array as the triangle
// indices.
- GLC(Context(),
- Context()->drawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_SHORT, 0));
-}
-
-static inline SkBitmap ApplyFilters(GLRenderer* renderer,
- ContextProvider* offscreen_contexts,
- const FilterOperations& filters,
- ScopedResource* source_texture_resource) {
- if (filters.IsEmpty())
- return SkBitmap();
-
- if (!offscreen_contexts || !offscreen_contexts->GrContext())
- return SkBitmap();
-
- ResourceProvider::ScopedWriteLockGL lock(renderer->resource_provider(),
- source_texture_resource->id());
-
- // Flush the compositor context to ensure that textures there are available
- // in the shared context. Do this after locking/creating the compositor
- // texture.
- renderer->resource_provider()->Flush();
-
- // Make sure skia uses the correct GL context.
- offscreen_contexts->Context3d()->makeContextCurrent();
-
- SkBitmap source =
- RenderSurfaceFilters::Apply(filters,
- lock.texture_id(),
- source_texture_resource->size(),
- offscreen_contexts->GrContext());
-
- // Flush skia context so that all the rendered stuff appears on the
- // texture.
- offscreen_contexts->GrContext()->flush();
-
- // Flush the GL context so rendering results from this context are
- // visible in the compositor's context.
- offscreen_contexts->Context3d()->flush();
-
- // Use the compositor's GL context again.
- renderer->Context()->makeContextCurrent();
- return source;
+ GLC(gl_, gl_->DrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_SHORT, 0));
}
static SkBitmap ApplyImageFilter(GLRenderer* renderer,
@@ -538,7 +465,7 @@ static SkBitmap ApplyImageFilter(GLRenderer* renderer,
renderer->resource_provider()->Flush();
// Make sure skia uses the correct GL context.
- offscreen_contexts->Context3d()->makeContextCurrent();
+ offscreen_contexts->MakeGrContextCurrent();
// Wrap the source texture in a Ganesh platform texture.
GrBackendTextureDesc backend_texture_description;
@@ -552,13 +479,17 @@ static SkBitmap ApplyImageFilter(GLRenderer* renderer,
skia::AdoptRef(offscreen_contexts->GrContext()->wrapBackendTexture(
backend_texture_description));
+ SkImageInfo info = {
+ source_texture_resource->size().width(),
+ source_texture_resource->size().height(),
+ kPMColor_SkColorType,
+ kPremul_SkAlphaType
+ };
// Place the platform texture inside an SkBitmap.
SkBitmap source;
- source.setConfig(SkBitmap::kARGB_8888_Config,
- source_texture_resource->size().width(),
- source_texture_resource->size().height());
+ source.setConfig(info);
skia::RefPtr<SkGrPixelRef> pixel_ref =
- skia::AdoptRef(new SkGrPixelRef(texture.get()));
+ skia::AdoptRef(new SkGrPixelRef(info, texture.get()));
source.setPixelRef(pixel_ref.get());
// Create a scratch texture for backing store.
@@ -597,17 +528,140 @@ static SkBitmap ApplyImageFilter(GLRenderer* renderer,
// visible in the compositor's context.
offscreen_contexts->Context3d()->flush();
- // Use the compositor's GL context again.
- renderer->Context()->makeContextCurrent();
+ return device.accessBitmap(false);
+}
+
+static SkBitmap ApplyBlendModeWithBackdrop(
+ GLRenderer* renderer,
+ ContextProvider* offscreen_contexts,
+ SkBitmap source_bitmap_with_filters,
+ ScopedResource* source_texture_resource,
+ ScopedResource* background_texture_resource,
+ SkXfermode::Mode blend_mode) {
+ if (!offscreen_contexts || !offscreen_contexts->GrContext())
+ return source_bitmap_with_filters;
+
+ DCHECK(background_texture_resource);
+ DCHECK(source_texture_resource);
+
+ gfx::Size source_size = source_texture_resource->size();
+ gfx::Size background_size = background_texture_resource->size();
+
+ DCHECK_LE(background_size.width(), source_size.width());
+ DCHECK_LE(background_size.height(), source_size.height());
+
+ int source_texture_with_filters_id;
+ scoped_ptr<ResourceProvider::ScopedReadLockGL> lock;
+ if (source_bitmap_with_filters.getTexture()) {
+ DCHECK_EQ(source_size.width(), source_bitmap_with_filters.width());
+ DCHECK_EQ(source_size.height(), source_bitmap_with_filters.height());
+ GrTexture* texture =
+ reinterpret_cast<GrTexture*>(source_bitmap_with_filters.getTexture());
+ source_texture_with_filters_id = texture->getTextureHandle();
+ } else {
+ lock.reset(new ResourceProvider::ScopedReadLockGL(
+ renderer->resource_provider(), source_texture_resource->id()));
+ source_texture_with_filters_id = lock->texture_id();
+ }
+
+ ResourceProvider::ScopedReadLockGL lock_background(
+ renderer->resource_provider(), background_texture_resource->id());
+
+ // Flush the compositor context to ensure that textures there are available
+ // in the shared context. Do this after locking/creating the compositor
+ // texture.
+ renderer->resource_provider()->Flush();
+
+ // Make sure skia uses the correct GL context.
+ offscreen_contexts->MakeGrContextCurrent();
+
+ // Wrap the source texture in a Ganesh platform texture.
+ GrBackendTextureDesc backend_texture_description;
+ backend_texture_description.fConfig = kSkia8888_GrPixelConfig;
+ backend_texture_description.fOrigin = kBottomLeft_GrSurfaceOrigin;
+
+ backend_texture_description.fWidth = source_size.width();
+ backend_texture_description.fHeight = source_size.height();
+ backend_texture_description.fTextureHandle = source_texture_with_filters_id;
+ skia::RefPtr<GrTexture> source_texture =
+ skia::AdoptRef(offscreen_contexts->GrContext()->wrapBackendTexture(
+ backend_texture_description));
+
+ backend_texture_description.fWidth = background_size.width();
+ backend_texture_description.fHeight = background_size.height();
+ backend_texture_description.fTextureHandle = lock_background.texture_id();
+ skia::RefPtr<GrTexture> background_texture =
+ skia::AdoptRef(offscreen_contexts->GrContext()->wrapBackendTexture(
+ backend_texture_description));
+
+ SkImageInfo source_info = {
+ source_size.width(),
+ source_size.height(),
+ kPMColor_SkColorType,
+ kPremul_SkAlphaType
+ };
+ // Place the platform texture inside an SkBitmap.
+ SkBitmap source;
+ source.setConfig(source_info);
+ skia::RefPtr<SkGrPixelRef> source_pixel_ref =
+ skia::AdoptRef(new SkGrPixelRef(source_info, source_texture.get()));
+ source.setPixelRef(source_pixel_ref.get());
+
+ SkImageInfo background_info = {
+ background_size.width(),
+ background_size.height(),
+ kPMColor_SkColorType,
+ kPremul_SkAlphaType
+ };
+
+ SkBitmap background;
+ background.setConfig(background_info);
+ skia::RefPtr<SkGrPixelRef> background_pixel_ref =
+ skia::AdoptRef(new SkGrPixelRef(
+ background_info, background_texture.get()));
+ background.setPixelRef(background_pixel_ref.get());
+
+ // Create a scratch texture for backing store.
+ GrTextureDesc desc;
+ desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
+ desc.fSampleCnt = 0;
+ desc.fWidth = source.width();
+ desc.fHeight = source.height();
+ desc.fConfig = kSkia8888_GrPixelConfig;
+ desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
+ GrAutoScratchTexture scratch_texture(
+ offscreen_contexts->GrContext(), desc, GrContext::kExact_ScratchTexMatch);
+ skia::RefPtr<GrTexture> backing_store =
+ skia::AdoptRef(scratch_texture.detach());
+
+ // Create a device and canvas using that backing store.
+ SkGpuDevice device(offscreen_contexts->GrContext(), backing_store.get());
+ SkCanvas canvas(&device);
+
+ // Draw the source bitmap through the filter to the canvas.
+ canvas.clear(SK_ColorTRANSPARENT);
+ canvas.drawSprite(background, 0, 0);
+ SkPaint paint;
+ paint.setXfermodeMode(blend_mode);
+ canvas.drawSprite(source, 0, 0, &paint);
+
+ // Flush skia context so that all the rendered stuff appears on the
+ // texture.
+ offscreen_contexts->GrContext()->flush();
+
+ // Flush the GL context so rendering results from this context are
+ // visible in the compositor's context.
+ offscreen_contexts->Context3d()->flush();
return device.accessBitmap(false);
}
-scoped_ptr<ScopedResource> GLRenderer::DrawBackgroundFilters(
+scoped_ptr<ScopedResource> GLRenderer::GetBackgroundWithFilters(
DrawingFrame* frame,
const RenderPassDrawQuad* quad,
const gfx::Transform& contents_device_transform,
- const gfx::Transform& contents_device_transform_inverse) {
+ const gfx::Transform& contents_device_transform_inverse,
+ bool* background_changed) {
// This method draws a background filter, which applies a filter to any pixels
// behind the quad and seen through its background. The algorithm works as
// follows:
@@ -631,61 +685,74 @@ scoped_ptr<ScopedResource> GLRenderer::DrawBackgroundFilters(
// TODO(danakj): When this algorithm changes, update
// LayerTreeHost::PrioritizeTextures() accordingly.
- FilterOperations filters =
- RenderSurfaceFilters::Optimize(quad->background_filters);
- DCHECK(!filters.IsEmpty());
-
// 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 scoped_ptr<ScopedResource>();
+ bool apply_background_filters =
+ !frame->current_render_pass->has_transparent_background;
DCHECK(!frame->current_texture);
+ // TODO(ajuma): Add support for reference filters once
+ // FilterOperations::GetOutsets supports reference filters.
+ if (apply_background_filters && quad->background_filters.HasReferenceFilter())
+ apply_background_filters = false;
+
// TODO(danakj): Do a single readback for both the surface and replica and
// cache the filtered results (once filter textures are not reused).
gfx::Rect window_rect = gfx::ToEnclosingRect(MathUtil::MapClippedRect(
contents_device_transform, SharedGeometryQuad().BoundingBox()));
int top, right, bottom, left;
- filters.GetOutsets(&top, &right, &bottom, &left);
+ quad->background_filters.GetOutsets(&top, &right, &bottom, &left);
window_rect.Inset(-left, -top, -right, -bottom);
window_rect.Intersect(
MoveFromDrawToWindowSpace(frame->current_render_pass->output_rect));
scoped_ptr<ScopedResource> device_background_texture =
- ScopedResource::create(resource_provider_);
- if (!device_background_texture->Allocate(window_rect.size(),
- ResourceProvider::TextureUsageAny,
- RGBA_8888)) {
- return scoped_ptr<ScopedResource>();
- } else {
+ ScopedResource::Create(resource_provider_);
+ // The TextureUsageFramebuffer hint makes ResourceProvider avoid immutable
+ // storage allocation (texStorage2DEXT) for this texture. copyTexImage2D fails
+ // when called on a texture having immutable storage.
+ device_background_texture->Allocate(
+ window_rect.size(), ResourceProvider::TextureUsageFramebuffer, RGBA_8888);
+ {
ResourceProvider::ScopedWriteLockGL lock(resource_provider_,
device_background_texture->id());
- GetFramebufferTexture(lock.texture_id(),
- device_background_texture->format(),
- window_rect);
+ GetFramebufferTexture(
+ lock.texture_id(), device_background_texture->format(), window_rect);
}
- SkBitmap filtered_device_background =
- ApplyFilters(this,
- frame->offscreen_context_provider,
- filters,
- device_background_texture.get());
- if (!filtered_device_background.getTexture())
- return scoped_ptr<ScopedResource>();
+ skia::RefPtr<SkImageFilter> filter = RenderSurfaceFilters::BuildImageFilter(
+ quad->background_filters, device_background_texture->size());
+
+ SkBitmap filtered_device_background;
+ if (apply_background_filters) {
+ filtered_device_background =
+ ApplyImageFilter(this,
+ frame->offscreen_context_provider,
+ quad->rect.origin(),
+ filter.get(),
+ device_background_texture.get());
+ }
+ *background_changed = (filtered_device_background.getTexture() != NULL);
- GrTexture* texture =
- reinterpret_cast<GrTexture*>(filtered_device_background.getTexture());
- int filtered_device_background_texture_id = texture->getTextureHandle();
+ int filtered_device_background_texture_id = 0;
+ scoped_ptr<ResourceProvider::ScopedReadLockGL> lock;
+ if (filtered_device_background.getTexture()) {
+ GrTexture* texture =
+ reinterpret_cast<GrTexture*>(filtered_device_background.getTexture());
+ filtered_device_background_texture_id = texture->getTextureHandle();
+ } else {
+ lock.reset(new ResourceProvider::ScopedReadLockGL(
+ resource_provider_, device_background_texture->id()));
+ filtered_device_background_texture_id = lock->texture_id();
+ }
scoped_ptr<ScopedResource> background_texture =
- ScopedResource::create(resource_provider_);
- if (!background_texture->Allocate(quad->rect.size(),
- ResourceProvider::TextureUsageFramebuffer,
- RGBA_8888))
- return scoped_ptr<ScopedResource>();
+ ScopedResource::Create(resource_provider_);
+ background_texture->Allocate(
+ quad->rect.size(), ResourceProvider::TextureUsageFramebuffer, RGBA_8888);
const RenderPass* target_render_pass = frame->current_render_pass;
bool using_background_texture =
@@ -704,8 +771,8 @@ scoped_ptr<ScopedResource> GLRenderer::DrawBackgroundFilters(
contents_device_transform_inverse);
#ifndef NDEBUG
- GLC(Context(), Context()->clearColor(0, 0, 1, 1));
- Context()->clear(GL_COLOR_BUFFER_BIT);
+ GLC(gl_, gl_->ClearColor(0, 0, 1, 1));
+ gl_->Clear(GL_COLOR_BUFFER_BIT);
#endif
// The filtered_deveice_background_texture is oriented the same as the frame
@@ -732,7 +799,7 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame,
const RenderPassDrawQuad* quad) {
SetBlendEnabled(quad->ShouldDrawWithBlending());
- CachedResource* contents_texture =
+ ScopedResource* contents_texture =
render_pass_textures_.get(quad->render_pass_id);
if (!contents_texture || !contents_texture->id())
return;
@@ -749,19 +816,24 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame,
if (!contents_device_transform.GetInverse(&contents_device_transform_inverse))
return;
+ bool need_background_texture =
+ quad->shared_quad_state->blend_mode != SkXfermode::kSrcOver_Mode ||
+ !quad->background_filters.IsEmpty();
+ bool background_changed = false;
scoped_ptr<ScopedResource> background_texture;
- if (!quad->background_filters.IsEmpty()) {
+ if (need_background_texture) {
// The pixels from the filtered background should completely replace the
// current pixel values.
bool disable_blending = blend_enabled();
if (disable_blending)
SetBlendEnabled(false);
- background_texture = DrawBackgroundFilters(
- frame,
- quad,
- contents_device_transform,
- contents_device_transform_inverse);
+ background_texture =
+ GetBackgroundWithFilters(frame,
+ quad,
+ contents_device_transform,
+ contents_device_transform_inverse,
+ &background_changed);
if (disable_blending)
SetBlendEnabled(true);
@@ -772,45 +844,47 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame,
SkBitmap filter_bitmap;
SkScalar color_matrix[20];
bool use_color_matrix = false;
- if (quad->filter) {
- skia::RefPtr<SkColorFilter> cf;
+ // TODO(ajuma): Always use RenderSurfaceFilters::BuildImageFilter, not just
+ // when we have a reference filter.
+ if (!quad->filters.IsEmpty()) {
+ skia::RefPtr<SkImageFilter> filter = RenderSurfaceFilters::BuildImageFilter(
+ quad->filters, contents_texture->size());
+ if (filter) {
+ skia::RefPtr<SkColorFilter> cf;
+
+ {
+ SkColorFilter* colorfilter_rawptr = NULL;
+ filter->asColorFilter(&colorfilter_rawptr);
+ cf = skia::AdoptRef(colorfilter_rawptr);
+ }
- {
- SkColorFilter* colorfilter_rawptr = NULL;
- quad->filter->asColorFilter(&colorfilter_rawptr);
- cf = skia::AdoptRef(colorfilter_rawptr);
+ if (cf && cf->asColorMatrix(color_matrix) && !filter->getInput(0)) {
+ // We have a single color matrix as a filter; apply it locally
+ // in the compositor.
+ use_color_matrix = true;
+ } else {
+ filter_bitmap = ApplyImageFilter(this,
+ frame->offscreen_context_provider,
+ quad->rect.origin(),
+ filter.get(),
+ contents_texture);
+ }
}
+ }
- if (cf && cf->asColorMatrix(color_matrix) && !quad->filter->getInput(0)) {
- // We have a single color matrix as a filter; apply it locally
- // in the compositor.
- use_color_matrix = true;
- } else {
- filter_bitmap = ApplyImageFilter(this,
- frame->offscreen_context_provider,
- quad->rect.origin(),
- quad->filter.get(),
- contents_texture);
- }
- } else if (!quad->filters.IsEmpty()) {
- FilterOperations optimized_filters =
- RenderSurfaceFilters::Optimize(quad->filters);
-
- if ((optimized_filters.size() == 1) &&
- (optimized_filters.at(0).type() == FilterOperation::COLOR_MATRIX)) {
- memcpy(
- color_matrix, optimized_filters.at(0).matrix(), sizeof(color_matrix));
- use_color_matrix = true;
- } else {
- filter_bitmap = ApplyFilters(this,
+ if (quad->shared_quad_state->blend_mode != SkXfermode::kSrcOver_Mode &&
+ background_texture) {
+ filter_bitmap =
+ ApplyBlendModeWithBackdrop(this,
frame->offscreen_context_provider,
- optimized_filters,
- contents_texture);
- }
+ filter_bitmap,
+ contents_texture,
+ background_texture.get(),
+ quad->shared_quad_state->blend_mode);
}
- // Draw the background texture if there is one.
- if (background_texture) {
+ // Draw the background texture if it has some filters applied.
+ if (background_texture && background_changed) {
DCHECK(background_texture->size() == quad->rect.size());
ResourceProvider::ScopedReadLockGL lock(resource_provider_,
background_texture->id());
@@ -834,10 +908,10 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame,
LayerQuad device_layer_edges(device_quad);
// Use anti-aliasing programs only when necessary.
- bool use_aa = !clipped &&
- (!device_quad.IsRectilinear() ||
- !gfx::IsNearestRectWithinDistance(device_quad.BoundingBox(),
- kAntiAliasingEpsilon));
+ bool use_aa =
+ !clipped && (!device_quad.IsRectilinear() ||
+ !gfx::IsNearestRectWithinDistance(device_quad.BoundingBox(),
+ kAntiAliasingEpsilon));
if (use_aa) {
device_layer_bounds.InflateAntiAliasingDistance();
device_layer_edges.InflateAntiAliasingDistance();
@@ -854,22 +928,24 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame,
// TODO(danakj): use the background_texture and blend the background in with
// this draw instead of having a separate copy of the background texture.
- scoped_ptr<ResourceProvider::ScopedReadLockGL> contents_resource_lock;
+ scoped_ptr<ResourceProvider::ScopedSamplerGL> contents_resource_lock;
if (filter_bitmap.getTexture()) {
GrTexture* texture =
reinterpret_cast<GrTexture*>(filter_bitmap.getTexture());
- DCHECK_EQ(GL_TEXTURE0, ResourceProvider::GetActiveTextureUnit(Context()));
- Context()->bindTexture(GL_TEXTURE_2D, texture->getTextureHandle());
+ DCHECK_EQ(GL_TEXTURE0, ResourceProvider::GetActiveTextureUnit(gl_));
+ gl_->BindTexture(GL_TEXTURE_2D, texture->getTextureHandle());
} else {
- contents_resource_lock = make_scoped_ptr(
- new ResourceProvider::ScopedSamplerGL(resource_provider_,
- contents_texture->id(),
- GL_TEXTURE_2D,
- GL_LINEAR));
+ contents_resource_lock =
+ make_scoped_ptr(new ResourceProvider::ScopedSamplerGL(
+ resource_provider_, contents_texture->id(), GL_LINEAR));
+ DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
+ contents_resource_lock->target());
}
TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired(
- context_, &highp_threshold_cache_, highp_threshold_min_,
+ gl_,
+ &highp_threshold_cache_,
+ highp_threshold_min_,
quad->shared_quad_state->visible_content_rect.bottom_right());
int shader_quad_location = -1;
@@ -888,8 +964,7 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame,
const RenderPassMaskProgramAA* program =
GetRenderPassMaskProgramAA(tex_coord_precision);
SetUseProgram(program->program());
- GLC(Context(),
- Context()->uniform1i(program->fragment_shader().sampler_location(), 0));
+ GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0));
shader_quad_location = program->vertex_shader().quad_location();
shader_edge_location = program->vertex_shader().edge_location();
@@ -908,8 +983,7 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame,
const RenderPassMaskProgram* program =
GetRenderPassMaskProgram(tex_coord_precision);
SetUseProgram(program->program());
- GLC(Context(),
- Context()->uniform1i(program->fragment_shader().sampler_location(), 0));
+ GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0));
shader_mask_sampler_location =
program->fragment_shader().mask_sampler_location();
@@ -925,8 +999,7 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame,
const RenderPassProgramAA* program =
GetRenderPassProgramAA(tex_coord_precision);
SetUseProgram(program->program());
- GLC(Context(),
- Context()->uniform1i(program->fragment_shader().sampler_location(), 0));
+ GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0));
shader_quad_location = program->vertex_shader().quad_location();
shader_edge_location = program->vertex_shader().edge_location();
@@ -939,8 +1012,7 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame,
const RenderPassMaskColorMatrixProgramAA* program =
GetRenderPassMaskColorMatrixProgramAA(tex_coord_precision);
SetUseProgram(program->program());
- GLC(Context(),
- Context()->uniform1i(program->fragment_shader().sampler_location(), 0));
+ GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0));
shader_matrix_location = program->vertex_shader().matrix_location();
shader_quad_location = program->vertex_shader().quad_location();
@@ -963,8 +1035,7 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame,
const RenderPassColorMatrixProgramAA* program =
GetRenderPassColorMatrixProgramAA(tex_coord_precision);
SetUseProgram(program->program());
- GLC(Context(),
- Context()->uniform1i(program->fragment_shader().sampler_location(), 0));
+ GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0));
shader_matrix_location = program->vertex_shader().matrix_location();
shader_quad_location = program->vertex_shader().quad_location();
@@ -981,8 +1052,7 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame,
const RenderPassMaskColorMatrixProgram* program =
GetRenderPassMaskColorMatrixProgram(tex_coord_precision);
SetUseProgram(program->program());
- GLC(Context(),
- Context()->uniform1i(program->fragment_shader().sampler_location(), 0));
+ GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0));
shader_matrix_location = program->vertex_shader().matrix_location();
shader_tex_transform_location =
@@ -1002,8 +1072,7 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame,
const RenderPassColorMatrixProgram* program =
GetRenderPassColorMatrixProgram(tex_coord_precision);
SetUseProgram(program->program());
- GLC(Context(),
- Context()->uniform1i(program->fragment_shader().sampler_location(), 0));
+ GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0));
shader_matrix_location = program->vertex_shader().matrix_location();
shader_tex_transform_location =
@@ -1017,8 +1086,7 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame,
const RenderPassProgram* program =
GetRenderPassProgram(tex_coord_precision);
SetUseProgram(program->program());
- GLC(Context(),
- Context()->uniform1i(program->fragment_shader().sampler_location(), 0));
+ GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0));
shader_matrix_location = program->vertex_shader().matrix_location();
shader_alpha_location = program->fragment_shader().alpha_location();
@@ -1036,17 +1104,18 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame,
// Flip the content vertically in the shader, as the RenderPass input
// texture is already oriented the same way as the framebuffer, but the
// projection transform does a flip.
- GLC(Context(), Context()->uniform4f(shader_tex_transform_location,
- 0.0f,
- tex_scale_y,
- tex_scale_x,
- -tex_scale_y));
-
- scoped_ptr<ResourceProvider::ScopedReadLockGL> shader_mask_sampler_lock;
+ GLC(gl_,
+ gl_->Uniform4f(shader_tex_transform_location,
+ 0.0f,
+ tex_scale_y,
+ tex_scale_x,
+ -tex_scale_y));
+
+ scoped_ptr<ResourceProvider::ScopedSamplerGL> shader_mask_sampler_lock;
if (shader_mask_sampler_location != -1) {
DCHECK_NE(shader_mask_tex_coord_scale_location, 1);
DCHECK_NE(shader_mask_tex_coord_offset_location, 1);
- GLC(Context(), Context()->uniform1i(shader_mask_sampler_location, 1));
+ GLC(gl_, gl_->Uniform1i(shader_mask_sampler_location, 1));
float mask_tex_scale_x = quad->mask_uv_rect.width() / tex_scale_x;
float mask_tex_scale_y = quad->mask_uv_rect.height() / tex_scale_y;
@@ -1054,38 +1123,36 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame,
// Mask textures are oriented vertically flipped relative to the framebuffer
// and the RenderPass contents texture, so we flip the tex coords from the
// RenderPass texture to find the mask texture coords.
- GLC(Context(),
- Context()->uniform2f(shader_mask_tex_coord_offset_location,
- quad->mask_uv_rect.x(),
- quad->mask_uv_rect.y() + mask_tex_scale_y));
- GLC(Context(),
- Context()->uniform2f(shader_mask_tex_coord_scale_location,
- mask_tex_scale_x,
- -mask_tex_scale_y));
+ GLC(gl_,
+ gl_->Uniform2f(shader_mask_tex_coord_offset_location,
+ quad->mask_uv_rect.x(),
+ quad->mask_uv_rect.y() + quad->mask_uv_rect.height()));
+ GLC(gl_,
+ gl_->Uniform2f(shader_mask_tex_coord_scale_location,
+ mask_tex_scale_x,
+ -mask_tex_scale_y));
shader_mask_sampler_lock = make_scoped_ptr(
new ResourceProvider::ScopedSamplerGL(resource_provider_,
quad->mask_resource_id,
- GL_TEXTURE_2D,
GL_TEXTURE1,
GL_LINEAR));
+ DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
+ shader_mask_sampler_lock->target());
}
if (shader_edge_location != -1) {
float edge[24];
device_layer_edges.ToFloatArray(edge);
device_layer_bounds.ToFloatArray(&edge[12]);
- GLC(Context(), Context()->uniform3fv(shader_edge_location, 8, edge));
+ GLC(gl_, gl_->Uniform3fv(shader_edge_location, 8, edge));
}
if (shader_viewport_location != -1) {
- float viewport[4] = {
- static_cast<float>(viewport_.x()),
- static_cast<float>(viewport_.y()),
- static_cast<float>(viewport_.width()),
- static_cast<float>(viewport_.height()),
- };
- GLC(Context(),
- Context()->uniform4fv(shader_viewport_location, 1, viewport));
+ float viewport[4] = {static_cast<float>(viewport_.x()),
+ static_cast<float>(viewport_.y()),
+ static_cast<float>(viewport_.width()),
+ static_cast<float>(viewport_.height()), };
+ GLC(gl_, gl_->Uniform4fv(shader_viewport_location, 1, viewport));
}
if (shader_color_matrix_location != -1) {
@@ -1094,9 +1161,8 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame,
for (int j = 0; j < 4; ++j)
matrix[i * 4 + j] = SkScalarToFloat(color_matrix[j * 5 + i]);
}
- GLC(Context(),
- Context()->uniformMatrix4fv(
- shader_color_matrix_location, 1, false, matrix));
+ GLC(gl_,
+ gl_->UniformMatrix4fv(shader_color_matrix_location, 1, false, matrix));
}
static const float kScale = 1.0f / 255.0f;
if (shader_color_offset_location != -1) {
@@ -1104,8 +1170,7 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame,
for (int i = 0; i < 4; ++i)
offset[i] = SkScalarToFloat(color_matrix[i * 5 + 4]) * kScale;
- GLC(Context(),
- Context()->uniform4fv(shader_color_offset_location, 1, offset));
+ GLC(gl_, gl_->Uniform4fv(shader_color_offset_location, 1, offset));
}
// Map device space quad to surface space. contents_device_transform has no 3d
@@ -1122,7 +1187,7 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame,
// Flush the compositor context before the filter bitmap goes out of
// scope, so the draw gets processed before the filter texture gets deleted.
if (filter_bitmap.getTexture())
- context_->flush();
+ GLC(gl_, gl_->Flush());
}
struct SolidColorProgramUniforms {
@@ -1134,7 +1199,7 @@ struct SolidColorProgramUniforms {
unsigned color_location;
};
-template<class T>
+template <class T>
static void SolidColorUniformLocation(T program,
SolidColorProgramUniforms* uniforms) {
uniforms->program = program->program();
@@ -1158,7 +1223,8 @@ bool GLRenderer::SetupQuadForAntialiasing(
device_transform, gfx::QuadF(quad->visibleContentRect()), &clipped);
bool is_axis_aligned_in_target = device_layer_quad.IsRectilinear();
- bool is_nearest_rect_within_epsilon = is_axis_aligned_in_target &&
+ bool is_nearest_rect_within_epsilon =
+ is_axis_aligned_in_target &&
gfx::IsNearestRectWithinDistance(device_layer_quad.BoundingBox(),
kAntiAliasingEpsilon);
// AAing clipped quads is not supported by the code yet.
@@ -1217,8 +1283,7 @@ bool GLRenderer::SetupQuadForAntialiasing(
// Map device space quad to local space. device_transform has no 3d
// component since it was flattened, so we don't need to project. We should
// have already checked that the transform was uninvertible above.
- gfx::Transform inverse_device_transform(
- gfx::Transform::kSkipInitialization);
+ gfx::Transform inverse_device_transform(gfx::Transform::kSkipInitialization);
bool did_invert = device_transform.GetInverse(&inverse_device_transform);
DCHECK(did_invert);
*local_quad = MathUtil::MapQuad(
@@ -1262,22 +1327,19 @@ void GLRenderer::DrawSolidColorQuad(const DrawingFrame* frame,
SolidColorUniformLocation(GetSolidColorProgram(), &uniforms);
SetUseProgram(uniforms.program);
- GLC(Context(),
- Context()->uniform4f(uniforms.color_location,
- (SkColorGetR(color) * (1.0f / 255.0f)) * alpha,
- (SkColorGetG(color) * (1.0f / 255.0f)) * alpha,
- (SkColorGetB(color) * (1.0f / 255.0f)) * alpha,
- alpha));
+ GLC(gl_,
+ gl_->Uniform4f(uniforms.color_location,
+ (SkColorGetR(color) * (1.0f / 255.0f)) * alpha,
+ (SkColorGetG(color) * (1.0f / 255.0f)) * alpha,
+ (SkColorGetB(color) * (1.0f / 255.0f)) * alpha,
+ alpha));
if (use_aa) {
- float viewport[4] = {
- static_cast<float>(viewport_.x()),
- static_cast<float>(viewport_.y()),
- static_cast<float>(viewport_.width()),
- static_cast<float>(viewport_.height()),
- };
- GLC(Context(),
- Context()->uniform4fv(uniforms.viewport_location, 1, viewport));
- GLC(Context(), Context()->uniform3fv(uniforms.edge_location, 8, edge));
+ float viewport[4] = {static_cast<float>(viewport_.x()),
+ static_cast<float>(viewport_.y()),
+ static_cast<float>(viewport_.width()),
+ static_cast<float>(viewport_.height()), };
+ GLC(gl_, gl_->Uniform4fv(uniforms.viewport_location, 1, viewport));
+ GLC(gl_, gl_->Uniform3fv(uniforms.edge_location, 8, edge));
}
// Enable blending when the quad properties require it or if we decided
@@ -1293,11 +1355,11 @@ void GLRenderer::DrawSolidColorQuad(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 centered_rect(gfx::PointF(-0.5f * tile_rect.width(),
- -0.5f * tile_rect.height()),
- tile_rect.size());
- DrawQuadGeometry(frame, quad->quadTransform(),
- centered_rect, uniforms.matrix_location);
+ gfx::RectF centered_rect(
+ gfx::PointF(-0.5f * tile_rect.width(), -0.5f * tile_rect.height()),
+ tile_rect.size());
+ DrawQuadGeometry(
+ frame, quad->quadTransform(), centered_rect, uniforms.matrix_location);
}
struct TileProgramUniforms {
@@ -1352,16 +1414,16 @@ void GLRenderer::DrawContentQuad(const DrawingFrame* frame,
// is mapped to the unit square by the vertex shader and mapped
// back to normalized texture coordinates by the fragment shader
// after being clamped to 0-1 range.
- float tex_clamp_x = std::min(
- 0.5f, 0.5f * clamp_tex_rect.width() - kAntiAliasingEpsilon);
- float tex_clamp_y = std::min(
- 0.5f, 0.5f * clamp_tex_rect.height() - kAntiAliasingEpsilon);
- float geom_clamp_x = std::min(
- tex_clamp_x * tex_to_geom_scale_x,
- 0.5f * clamp_geom_rect.width() - kAntiAliasingEpsilon);
- float geom_clamp_y = std::min(
- tex_clamp_y * tex_to_geom_scale_y,
- 0.5f * clamp_geom_rect.height() - kAntiAliasingEpsilon);
+ float tex_clamp_x =
+ std::min(0.5f, 0.5f * clamp_tex_rect.width() - kAntiAliasingEpsilon);
+ float tex_clamp_y =
+ std::min(0.5f, 0.5f * clamp_tex_rect.height() - kAntiAliasingEpsilon);
+ float geom_clamp_x =
+ std::min(tex_clamp_x * tex_to_geom_scale_x,
+ 0.5f * clamp_geom_rect.width() - kAntiAliasingEpsilon);
+ float geom_clamp_y =
+ std::min(tex_clamp_y * tex_to_geom_scale_y,
+ 0.5f * clamp_geom_rect.height() - kAntiAliasingEpsilon);
clamp_geom_rect.Inset(geom_clamp_x, geom_clamp_y, geom_clamp_x, geom_clamp_y);
clamp_tex_rect.Inset(tex_clamp_x, tex_clamp_y, tex_clamp_x, tex_clamp_y);
@@ -1373,15 +1435,7 @@ void GLRenderer::DrawContentQuad(const DrawingFrame* frame,
float vertex_tex_scale_y = tile_rect.height() / clamp_geom_rect.height();
TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired(
- context_, &highp_threshold_cache_, highp_threshold_min_,
- quad->texture_size);
-
- // Map to normalized texture coordinates.
- gfx::Size texture_size = quad->texture_size;
- float fragment_tex_translate_x = clamp_tex_rect.x() / texture_size.width();
- float fragment_tex_translate_y = clamp_tex_rect.y() / texture_size.height();
- float fragment_tex_scale_x = clamp_tex_rect.width() / texture_size.width();
- float fragment_tex_scale_y = clamp_tex_rect.height() / texture_size.height();
+ gl_, &highp_threshold_cache_, highp_threshold_min_, quad->texture_size);
gfx::Transform device_transform =
frame->window_matrix * frame->projection_matrix * quad->quadTransform();
@@ -1391,69 +1445,88 @@ void GLRenderer::DrawContentQuad(const DrawingFrame* frame,
gfx::QuadF local_quad = gfx::QuadF(gfx::RectF(tile_rect));
float edge[24];
- bool use_aa = settings_->allow_antialiasing && SetupQuadForAntialiasing(
- device_transform, quad, &local_quad, edge);
+ bool use_aa =
+ settings_->allow_antialiasing &&
+ SetupQuadForAntialiasing(device_transform, quad, &local_quad, edge);
+
+ bool scaled = (tex_to_geom_scale_x != 1.f || tex_to_geom_scale_y != 1.f);
+ GLenum filter = (use_aa || scaled ||
+ !quad->quadTransform().IsIdentityOrIntegerTranslation())
+ ? GL_LINEAR
+ : GL_NEAREST;
+ ResourceProvider::ScopedSamplerGL quad_resource_lock(
+ resource_provider_, resource_id, filter);
+ SamplerType sampler =
+ SamplerTypeFromTextureTarget(quad_resource_lock.target());
+
+ float fragment_tex_translate_x = clamp_tex_rect.x();
+ float fragment_tex_translate_y = clamp_tex_rect.y();
+ float fragment_tex_scale_x = clamp_tex_rect.width();
+ float fragment_tex_scale_y = clamp_tex_rect.height();
+
+ // Map to normalized texture coordinates.
+ if (sampler != SamplerType2DRect) {
+ gfx::Size texture_size = quad->texture_size;
+ DCHECK(!texture_size.IsEmpty());
+ fragment_tex_translate_x /= texture_size.width();
+ fragment_tex_translate_y /= texture_size.height();
+ fragment_tex_scale_x /= texture_size.width();
+ fragment_tex_scale_y /= texture_size.height();
+ }
TileProgramUniforms uniforms;
if (use_aa) {
if (quad->swizzle_contents) {
- TileUniformLocation(GetTileProgramSwizzleAA(tex_coord_precision),
+ TileUniformLocation(GetTileProgramSwizzleAA(tex_coord_precision, sampler),
&uniforms);
} else {
- TileUniformLocation(GetTileProgramAA(tex_coord_precision), &uniforms);
+ TileUniformLocation(GetTileProgramAA(tex_coord_precision, sampler),
+ &uniforms);
}
} else {
if (quad->ShouldDrawWithBlending()) {
if (quad->swizzle_contents) {
- TileUniformLocation(GetTileProgramSwizzle(tex_coord_precision),
+ TileUniformLocation(GetTileProgramSwizzle(tex_coord_precision, sampler),
&uniforms);
} else {
- TileUniformLocation(GetTileProgram(tex_coord_precision), &uniforms);
+ TileUniformLocation(GetTileProgram(tex_coord_precision, sampler),
+ &uniforms);
}
} else {
if (quad->swizzle_contents) {
- TileUniformLocation(GetTileProgramSwizzleOpaque(tex_coord_precision),
- &uniforms);
+ TileUniformLocation(
+ GetTileProgramSwizzleOpaque(tex_coord_precision, sampler),
+ &uniforms);
} else {
- TileUniformLocation(GetTileProgramOpaque(tex_coord_precision),
+ TileUniformLocation(GetTileProgramOpaque(tex_coord_precision, sampler),
&uniforms);
}
}
}
SetUseProgram(uniforms.program);
- GLC(Context(), Context()->uniform1i(uniforms.sampler_location, 0));
- bool scaled = (tex_to_geom_scale_x != 1.f || tex_to_geom_scale_y != 1.f);
- GLenum filter = (use_aa || scaled ||
- !quad->quadTransform().IsIdentityOrIntegerTranslation())
- ? GL_LINEAR
- : GL_NEAREST;
- ResourceProvider::ScopedSamplerGL quad_resource_lock(
- resource_provider_, resource_id, GL_TEXTURE_2D, filter);
+ GLC(gl_, gl_->Uniform1i(uniforms.sampler_location, 0));
if (use_aa) {
- float viewport[4] = {
- static_cast<float>(viewport_.x()),
- static_cast<float>(viewport_.y()),
- static_cast<float>(viewport_.width()),
- static_cast<float>(viewport_.height()),
- };
- GLC(Context(),
- Context()->uniform4fv(uniforms.viewport_location, 1, viewport));
- GLC(Context(), Context()->uniform3fv(uniforms.edge_location, 8, edge));
-
- GLC(Context(),
- Context()->uniform4f(uniforms.vertex_tex_transform_location,
- vertex_tex_translate_x,
- vertex_tex_translate_y,
- vertex_tex_scale_x,
- vertex_tex_scale_y));
- GLC(Context(),
- Context()->uniform4f(uniforms.fragment_tex_transform_location,
- fragment_tex_translate_x,
- fragment_tex_translate_y,
- fragment_tex_scale_x,
- fragment_tex_scale_y));
+ float viewport[4] = {static_cast<float>(viewport_.x()),
+ static_cast<float>(viewport_.y()),
+ static_cast<float>(viewport_.width()),
+ static_cast<float>(viewport_.height()), };
+ GLC(gl_, gl_->Uniform4fv(uniforms.viewport_location, 1, viewport));
+ GLC(gl_, gl_->Uniform3fv(uniforms.edge_location, 8, edge));
+
+ GLC(gl_,
+ gl_->Uniform4f(uniforms.vertex_tex_transform_location,
+ vertex_tex_translate_x,
+ vertex_tex_translate_y,
+ vertex_tex_scale_x,
+ vertex_tex_scale_y));
+ GLC(gl_,
+ gl_->Uniform4f(uniforms.fragment_tex_transform_location,
+ fragment_tex_translate_x,
+ fragment_tex_translate_y,
+ fragment_tex_scale_x,
+ fragment_tex_scale_y));
} else {
// Move fragment shader transform to vertex shader. We can do this while
// still producing correct results as fragment_tex_transform_location
@@ -1466,12 +1539,12 @@ void GLRenderer::DrawContentQuad(const DrawingFrame* frame,
vertex_tex_translate_x += fragment_tex_translate_x;
vertex_tex_translate_y += fragment_tex_translate_y;
- GLC(Context(),
- Context()->uniform4f(uniforms.vertex_tex_transform_location,
- vertex_tex_translate_x,
- vertex_tex_translate_y,
- vertex_tex_scale_x,
- vertex_tex_scale_y));
+ GLC(gl_,
+ gl_->Uniform4f(uniforms.vertex_tex_transform_location,
+ vertex_tex_translate_x,
+ vertex_tex_translate_y,
+ vertex_tex_scale_x,
+ vertex_tex_scale_y));
}
// Enable blending when the quad properties require it or if we decided
@@ -1500,37 +1573,27 @@ void GLRenderer::DrawYUVVideoQuad(const DrawingFrame* frame,
SetBlendEnabled(quad->ShouldDrawWithBlending());
TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired(
- context_, &highp_threshold_cache_, highp_threshold_min_,
+ gl_,
+ &highp_threshold_cache_,
+ highp_threshold_min_,
quad->shared_quad_state->visible_content_rect.bottom_right());
bool use_alpha_plane = quad->a_plane_resource_id != 0;
ResourceProvider::ScopedSamplerGL y_plane_lock(
- resource_provider_,
- quad->y_plane_resource_id,
- GL_TEXTURE_2D,
- GL_TEXTURE1,
- GL_LINEAR);
+ resource_provider_, quad->y_plane_resource_id, GL_TEXTURE1, GL_LINEAR);
+ DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), y_plane_lock.target());
ResourceProvider::ScopedSamplerGL u_plane_lock(
- resource_provider_,
- quad->u_plane_resource_id,
- GL_TEXTURE_2D,
- GL_TEXTURE2,
- GL_LINEAR);
+ resource_provider_, quad->u_plane_resource_id, GL_TEXTURE2, GL_LINEAR);
+ DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), u_plane_lock.target());
ResourceProvider::ScopedSamplerGL v_plane_lock(
- resource_provider_,
- quad->v_plane_resource_id,
- GL_TEXTURE_2D,
- GL_TEXTURE3,
- GL_LINEAR);
+ resource_provider_, quad->v_plane_resource_id, GL_TEXTURE3, GL_LINEAR);
+ DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), v_plane_lock.target());
scoped_ptr<ResourceProvider::ScopedSamplerGL> a_plane_lock;
if (use_alpha_plane) {
a_plane_lock.reset(new ResourceProvider::ScopedSamplerGL(
- resource_provider_,
- quad->a_plane_resource_id,
- GL_TEXTURE_2D,
- GL_TEXTURE4,
- GL_LINEAR));
+ resource_provider_, quad->a_plane_resource_id, GL_TEXTURE4, GL_LINEAR));
+ DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), a_plane_lock->target());
}
int tex_scale_location = -1;
@@ -1569,26 +1632,22 @@ void GLRenderer::DrawYUVVideoQuad(const DrawingFrame* frame,
alpha_location = program->fragment_shader().alpha_location();
}
- GLC(Context(),
- Context()->uniform2f(tex_scale_location,
- quad->tex_scale.width(),
- quad->tex_scale.height()));
- GLC(Context(), Context()->uniform1i(y_texture_location, 1));
- GLC(Context(), Context()->uniform1i(u_texture_location, 2));
- GLC(Context(), Context()->uniform1i(v_texture_location, 3));
+ GLC(gl_,
+ gl_->Uniform2f(tex_scale_location,
+ quad->tex_scale.width(),
+ quad->tex_scale.height()));
+ GLC(gl_, gl_->Uniform1i(y_texture_location, 1));
+ GLC(gl_, gl_->Uniform1i(u_texture_location, 2));
+ GLC(gl_, gl_->Uniform1i(v_texture_location, 3));
if (use_alpha_plane)
- GLC(Context(), Context()->uniform1i(a_texture_location, 4));
+ GLC(gl_, gl_->Uniform1i(a_texture_location, 4));
// These values are magic numbers that are used in the transformation from YUV
// to RGB color values. They are taken from the following webpage:
// http://www.fourcc.org/fccyvrgb.php
- float yuv_to_rgb[9] = {
- 1.164f, 1.164f, 1.164f,
- 0.0f, -.391f, 2.018f,
- 1.596f, -.813f, 0.0f,
- };
- GLC(Context(),
- Context()->uniformMatrix3fv(yuv_matrix_location, 1, 0, yuv_to_rgb));
+ float yuv_to_rgb[9] = {1.164f, 1.164f, 1.164f, 0.0f, -.391f,
+ 2.018f, 1.596f, -.813f, 0.0f, };
+ GLC(gl_, gl_->UniformMatrix3fv(yuv_matrix_location, 1, 0, yuv_to_rgb));
// These values map to 16, 128, and 128 respectively, and are computed
// as a fraction over 256 (e.g. 16 / 256 = 0.0625).
@@ -1596,9 +1655,8 @@ void GLRenderer::DrawYUVVideoQuad(const DrawingFrame* frame,
// Y - 16 : Gives 16 values of head and footroom for overshooting
// U - 128 : Turns unsigned U into signed U [-128,127]
// V - 128 : Turns unsigned V into signed V [-128,127]
- float yuv_adjust[3] = { -0.0625f, -0.5f, -0.5f, };
- GLC(Context(), Context()->uniform3fv(yuv_adj_location, 1, yuv_adjust));
-
+ float yuv_adjust[3] = {-0.0625f, -0.5f, -0.5f, };
+ GLC(gl_, gl_->Uniform3fv(yuv_adj_location, 1, yuv_adjust));
SetShaderOpacity(quad->opacity(), alpha_location);
DrawQuadGeometry(frame, quad->quadTransform(), quad->rect, matrix_location);
@@ -1613,7 +1671,9 @@ void GLRenderer::DrawStreamVideoQuad(const DrawingFrame* frame,
DCHECK(capabilities_.using_egl_image);
TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired(
- context_, &highp_threshold_cache_, highp_threshold_min_,
+ gl_,
+ &highp_threshold_cache_,
+ highp_threshold_min_,
quad->shared_quad_state->visible_content_rect.bottom_right());
const VideoStreamTextureProgram* program =
@@ -1621,18 +1681,16 @@ void GLRenderer::DrawStreamVideoQuad(const DrawingFrame* frame,
SetUseProgram(program->program());
ToGLMatrix(&gl_matrix[0], quad->matrix);
- GLC(Context(),
- Context()->uniformMatrix4fv(
+ GLC(gl_,
+ gl_->UniformMatrix4fv(
program->vertex_shader().tex_matrix_location(), 1, false, gl_matrix));
ResourceProvider::ScopedReadLockGL lock(resource_provider_,
quad->resource_id);
- DCHECK_EQ(GL_TEXTURE0, ResourceProvider::GetActiveTextureUnit(Context()));
- GLC(Context(),
- Context()->bindTexture(GL_TEXTURE_EXTERNAL_OES, lock.texture_id()));
+ DCHECK_EQ(GL_TEXTURE0, ResourceProvider::GetActiveTextureUnit(gl_));
+ GLC(gl_, gl_->BindTexture(GL_TEXTURE_EXTERNAL_OES, lock.texture_id()));
- GLC(Context(),
- Context()->uniform1i(program->fragment_shader().sampler_location(), 0));
+ GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0));
SetShaderOpacity(quad->opacity(),
program->fragment_shader().alpha_location());
@@ -1642,85 +1700,36 @@ void GLRenderer::DrawStreamVideoQuad(const DrawingFrame* frame,
program->vertex_shader().matrix_location());
}
-void GLRenderer::DrawPictureQuadDirectToBackbuffer(
- const DrawingFrame* frame,
- const PictureDrawQuad* quad) {
- DCHECK(CanUseSkiaGPUBackend());
- DCHECK_EQ(quad->opacity(), 1.f) << "Need to composite to a bitmap or a "
- "render surface for non-1 opacity quads";
-
- // TODO(enne): This should be done more lazily / efficiently.
- gr_context_->resetContext();
-
- // Reset the canvas matrix to identity because the clip rect is in target
- // space.
- SkMatrix sk_identity;
- sk_identity.setIdentity();
- sk_canvas_->setMatrix(sk_identity);
-
- if (is_scissor_enabled_) {
- sk_canvas_->clipRect(gfx::RectToSkRect(scissor_rect_),
- SkRegion::kReplace_Op);
- } else {
- sk_canvas_->clipRect(gfx::RectToSkRect(client_->DeviceViewport()),
- SkRegion::kReplace_Op);
- }
-
- gfx::Transform contents_device_transform = frame->window_matrix *
- frame->projection_matrix * quad->quadTransform();
- contents_device_transform.Translate(quad->rect.x(),
- quad->rect.y());
- contents_device_transform.FlattenTo2d();
- SkMatrix sk_device_matrix;
- gfx::TransformToFlattenedSkMatrix(contents_device_transform,
- &sk_device_matrix);
- sk_canvas_->setMatrix(sk_device_matrix);
-
- quad->picture_pile->RasterDirect(
- sk_canvas_.get(), quad->content_rect, quad->contents_scale, NULL);
-
- // Flush any drawing buffers that have been deferred.
- sk_canvas_->flush();
-
- // TODO(enne): This should be done more lazily / efficiently.
- ReinitializeGLState();
-}
-
void GLRenderer::DrawPictureQuad(const DrawingFrame* frame,
const PictureDrawQuad* quad) {
- if (quad->can_draw_direct_to_backbuffer && CanUseSkiaGPUBackend()) {
- DrawPictureQuadDirectToBackbuffer(frame, quad);
- return;
- }
-
if (on_demand_tile_raster_bitmap_.width() != quad->texture_size.width() ||
on_demand_tile_raster_bitmap_.height() != quad->texture_size.height()) {
- on_demand_tile_raster_bitmap_.setConfig(
- SkBitmap::kARGB_8888_Config,
- quad->texture_size.width(),
- quad->texture_size.height());
+ on_demand_tile_raster_bitmap_.setConfig(SkBitmap::kARGB_8888_Config,
+ quad->texture_size.width(),
+ quad->texture_size.height());
on_demand_tile_raster_bitmap_.allocPixels();
if (on_demand_tile_raster_resource_id_)
resource_provider_->DeleteResource(on_demand_tile_raster_resource_id_);
- on_demand_tile_raster_resource_id_ = resource_provider_->CreateGLTexture(
- quad->texture_size,
- GL_TEXTURE_POOL_UNMANAGED_CHROMIUM,
- GL_CLAMP_TO_EDGE,
- ResourceProvider::TextureUsageAny,
- quad->texture_format);
+ on_demand_tile_raster_resource_id_ =
+ resource_provider_->CreateGLTexture(quad->texture_size,
+ GL_TEXTURE_2D,
+ GL_TEXTURE_POOL_UNMANAGED_CHROMIUM,
+ GL_CLAMP_TO_EDGE,
+ ResourceProvider::TextureUsageAny,
+ quad->texture_format);
}
SkBitmapDevice device(on_demand_tile_raster_bitmap_);
SkCanvas canvas(&device);
- quad->picture_pile->RasterToBitmap(&canvas, quad->content_rect,
- quad->contents_scale, NULL);
+ quad->picture_pile->RasterToBitmap(
+ &canvas, quad->content_rect, quad->contents_scale, NULL);
uint8_t* bitmap_pixels = NULL;
SkBitmap on_demand_tile_raster_bitmap_dest;
- SkBitmap::Config config = SkBitmapConfigFromFormat(quad->texture_format);
+ SkBitmap::Config config = SkBitmapConfig(quad->texture_format);
if (on_demand_tile_raster_bitmap_.getConfig() != config) {
on_demand_tile_raster_bitmap_.copyTo(&on_demand_tile_raster_bitmap_dest,
config);
@@ -1730,24 +1739,23 @@ void GLRenderer::DrawPictureQuad(const DrawingFrame* frame,
bitmap_pixels = reinterpret_cast<uint8_t*>(
on_demand_tile_raster_bitmap_dest.getPixels());
} else {
- bitmap_pixels = reinterpret_cast<uint8_t*>(
- on_demand_tile_raster_bitmap_.getPixels());
+ bitmap_pixels =
+ reinterpret_cast<uint8_t*>(on_demand_tile_raster_bitmap_.getPixels());
}
- resource_provider_->SetPixels(
- on_demand_tile_raster_resource_id_,
- bitmap_pixels,
- gfx::Rect(quad->texture_size),
- gfx::Rect(quad->texture_size),
- gfx::Vector2d());
+ resource_provider_->SetPixels(on_demand_tile_raster_resource_id_,
+ bitmap_pixels,
+ gfx::Rect(quad->texture_size),
+ gfx::Rect(quad->texture_size),
+ gfx::Vector2d());
DrawContentQuad(frame, quad, on_demand_tile_raster_resource_id_);
}
struct TextureProgramBinding {
template <class Program>
- void Set(Program* program, WebKit::WebGraphicsContext3D* context) {
- DCHECK(program && (program->initialized() || context->isContextLost()));
+ void Set(Program* program) {
+ DCHECK(program);
program_id = program->program();
sampler_location = program->fragment_shader().sampler_location();
matrix_location = program->vertex_shader().matrix_location();
@@ -1762,8 +1770,8 @@ struct TextureProgramBinding {
struct TexTransformTextureProgramBinding : TextureProgramBinding {
template <class Program>
- void Set(Program* program, WebKit::WebGraphicsContext3D* context) {
- TextureProgramBinding::Set(program, context);
+ void Set(Program* program) {
+ TextureProgramBinding::Set(program);
tex_transform_location = program->vertex_shader().tex_transform_location();
vertex_opacity_location =
program->vertex_shader().vertex_opacity_location();
@@ -1784,54 +1792,52 @@ void GLRenderer::FlushTextureQuadCache() {
SetUseProgram(draw_cache_.program_id);
// Bind the correct texture sampler location.
- GLC(Context(), Context()->uniform1i(draw_cache_.sampler_location, 0));
+ GLC(gl_, gl_->Uniform1i(draw_cache_.sampler_location, 0));
// Assume the current active textures is 0.
ResourceProvider::ScopedReadLockGL locked_quad(resource_provider_,
draw_cache_.resource_id);
- DCHECK_EQ(GL_TEXTURE0, ResourceProvider::GetActiveTextureUnit(Context()));
- GLC(Context(),
- Context()->bindTexture(GL_TEXTURE_2D, locked_quad.texture_id()));
+ DCHECK_EQ(GL_TEXTURE0, ResourceProvider::GetActiveTextureUnit(gl_));
+ GLC(gl_, gl_->BindTexture(GL_TEXTURE_2D, locked_quad.texture_id()));
- COMPILE_ASSERT(
- sizeof(Float4) == 4 * sizeof(float), // NOLINT(runtime/sizeof)
- struct_is_densely_packed);
+ COMPILE_ASSERT(sizeof(Float4) == 4 * sizeof(float), // NOLINT(runtime/sizeof)
+ struct_is_densely_packed);
COMPILE_ASSERT(
sizeof(Float16) == 16 * sizeof(float), // NOLINT(runtime/sizeof)
struct_is_densely_packed);
// Upload the tranforms for both points and uvs.
- GLC(context_,
- context_->uniformMatrix4fv(
+ GLC(gl_,
+ gl_->UniformMatrix4fv(
static_cast<int>(draw_cache_.matrix_location),
static_cast<int>(draw_cache_.matrix_data.size()),
false,
reinterpret_cast<float*>(&draw_cache_.matrix_data.front())));
- GLC(context_,
- context_->uniform4fv(
+ GLC(gl_,
+ gl_->Uniform4fv(
static_cast<int>(draw_cache_.uv_xform_location),
static_cast<int>(draw_cache_.uv_xform_data.size()),
reinterpret_cast<float*>(&draw_cache_.uv_xform_data.front())));
if (draw_cache_.background_color != SK_ColorTRANSPARENT) {
Float4 background_color = PremultipliedColor(draw_cache_.background_color);
- GLC(context_,
- context_->uniform4fv(
+ GLC(gl_,
+ gl_->Uniform4fv(
draw_cache_.background_color_location, 1, background_color.data));
}
- GLC(context_,
- context_->uniform1fv(
+ GLC(gl_,
+ gl_->Uniform1fv(
static_cast<int>(draw_cache_.vertex_opacity_location),
static_cast<int>(draw_cache_.vertex_opacity_data.size()),
static_cast<float*>(&draw_cache_.vertex_opacity_data.front())));
// Draw the quads!
- GLC(context_,
- context_->drawElements(GL_TRIANGLES,
- 6 * draw_cache_.matrix_data.size(),
- GL_UNSIGNED_SHORT,
- 0));
+ GLC(gl_,
+ gl_->DrawElements(GL_TRIANGLES,
+ 6 * draw_cache_.matrix_data.size(),
+ GL_UNSIGNED_SHORT,
+ 0));
// Clear the cache.
draw_cache_.program_id = 0;
@@ -1843,25 +1849,25 @@ void GLRenderer::FlushTextureQuadCache() {
void GLRenderer::EnqueueTextureQuad(const DrawingFrame* frame,
const TextureDrawQuad* quad) {
TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired(
- context_, &highp_threshold_cache_, highp_threshold_min_,
+ gl_,
+ &highp_threshold_cache_,
+ highp_threshold_min_,
quad->shared_quad_state->visible_content_rect.bottom_right());
// Choose the correct texture program binding
TexTransformTextureProgramBinding binding;
if (quad->premultiplied_alpha) {
if (quad->background_color == SK_ColorTRANSPARENT) {
- binding.Set(GetTextureProgram(tex_coord_precision), Context());
+ binding.Set(GetTextureProgram(tex_coord_precision));
} else {
- binding.Set(GetTextureBackgroundProgram(tex_coord_precision), Context());
+ binding.Set(GetTextureBackgroundProgram(tex_coord_precision));
}
} else {
if (quad->background_color == SK_ColorTRANSPARENT) {
- binding.Set(GetNonPremultipliedTextureProgram(tex_coord_precision),
- Context());
+ binding.Set(GetNonPremultipliedTextureProgram(tex_coord_precision));
} else {
binding.Set(
- GetNonPremultipliedTextureBackgroundProgram(tex_coord_precision),
- Context());
+ GetNonPremultipliedTextureBackgroundProgram(tex_coord_precision));
}
}
@@ -1910,54 +1916,52 @@ void GLRenderer::DrawIOSurfaceQuad(const DrawingFrame* frame,
SetBlendEnabled(quad->ShouldDrawWithBlending());
TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired(
- context_, &highp_threshold_cache_, highp_threshold_min_,
+ gl_,
+ &highp_threshold_cache_,
+ highp_threshold_min_,
quad->shared_quad_state->visible_content_rect.bottom_right());
TexTransformTextureProgramBinding binding;
- binding.Set(GetTextureIOSurfaceProgram(tex_coord_precision), Context());
+ binding.Set(GetTextureIOSurfaceProgram(tex_coord_precision));
SetUseProgram(binding.program_id);
- GLC(Context(), Context()->uniform1i(binding.sampler_location, 0));
+ GLC(gl_, gl_->Uniform1i(binding.sampler_location, 0));
if (quad->orientation == IOSurfaceDrawQuad::FLIPPED) {
- GLC(Context(),
- Context()->uniform4f(binding.tex_transform_location,
- 0,
- quad->io_surface_size.height(),
- quad->io_surface_size.width(),
- quad->io_surface_size.height() * -1.0f));
+ GLC(gl_,
+ gl_->Uniform4f(binding.tex_transform_location,
+ 0,
+ quad->io_surface_size.height(),
+ quad->io_surface_size.width(),
+ quad->io_surface_size.height() * -1.0f));
} else {
- GLC(Context(),
- Context()->uniform4f(binding.tex_transform_location,
- 0,
- 0,
- quad->io_surface_size.width(),
- quad->io_surface_size.height()));
+ GLC(gl_,
+ gl_->Uniform4f(binding.tex_transform_location,
+ 0,
+ 0,
+ quad->io_surface_size.width(),
+ quad->io_surface_size.height()));
}
- const float vertex_opacity[] = { quad->opacity(), quad->opacity(),
- quad->opacity(), quad->opacity() };
- GLC(Context(),
- Context()->uniform1fv(
- binding.vertex_opacity_location, 4, vertex_opacity));
+ const float vertex_opacity[] = {quad->opacity(), quad->opacity(),
+ quad->opacity(), quad->opacity()};
+ GLC(gl_, gl_->Uniform1fv(binding.vertex_opacity_location, 4, vertex_opacity));
ResourceProvider::ScopedReadLockGL lock(resource_provider_,
quad->io_surface_resource_id);
- DCHECK_EQ(GL_TEXTURE0, ResourceProvider::GetActiveTextureUnit(Context()));
- GLC(Context(),
- Context()->bindTexture(GL_TEXTURE_RECTANGLE_ARB,
- lock.texture_id()));
+ DCHECK_EQ(GL_TEXTURE0, ResourceProvider::GetActiveTextureUnit(gl_));
+ GLC(gl_, gl_->BindTexture(GL_TEXTURE_RECTANGLE_ARB, lock.texture_id()));
DrawQuadGeometry(
frame, quad->quadTransform(), quad->rect, binding.matrix_location);
- GLC(Context(), Context()->bindTexture(GL_TEXTURE_RECTANGLE_ARB, 0));
+ GLC(gl_, gl_->BindTexture(GL_TEXTURE_RECTANGLE_ARB, 0));
}
void GLRenderer::FinishDrawingFrame(DrawingFrame* frame) {
current_framebuffer_lock_.reset();
swap_buffer_rect_.Union(gfx::ToEnclosingRect(frame->root_damage_rect));
- GLC(context_, context_->disable(GL_BLEND));
+ GLC(gl_, gl_->Disable(GL_BLEND));
blend_shadow_ = false;
}
@@ -1970,7 +1974,7 @@ void GLRenderer::EnsureScissorTestEnabled() {
return;
FlushTextureQuadCache();
- GLC(context_, context_->enable(GL_SCISSOR_TEST));
+ GLC(gl_, gl_->Enable(GL_SCISSOR_TEST));
is_scissor_enabled_ = true;
}
@@ -1979,7 +1983,7 @@ void GLRenderer::EnsureScissorTestDisabled() {
return;
FlushTextureQuadCache();
- GLC(context_, context_->disable(GL_SCISSOR_TEST));
+ GLC(gl_, gl_->Disable(GL_SCISSOR_TEST));
is_scissor_enabled_ = false;
}
@@ -2009,12 +2013,12 @@ void GLRenderer::SetShaderQuadF(const gfx::QuadF& quad, int quad_location) {
gl_quad[5] = quad.p3().y();
gl_quad[6] = quad.p4().x();
gl_quad[7] = quad.p4().y();
- GLC(context_, context_->uniform2fv(quad_location, 4, gl_quad));
+ GLC(gl_, gl_->Uniform2fv(quad_location, 4, gl_quad));
}
void GLRenderer::SetShaderOpacity(float opacity, int alpha_location) {
if (alpha_location != -1)
- GLC(context_, context_->uniform1f(alpha_location, opacity));
+ GLC(gl_, gl_->Uniform1f(alpha_location, opacity));
}
void GLRenderer::SetStencilEnabled(bool enabled) {
@@ -2022,9 +2026,9 @@ void GLRenderer::SetStencilEnabled(bool enabled) {
return;
if (enabled)
- GLC(context_, context_->enable(GL_STENCIL_TEST));
+ GLC(gl_, gl_->Enable(GL_STENCIL_TEST));
else
- GLC(context_, context_->disable(GL_STENCIL_TEST));
+ GLC(gl_, gl_->Disable(GL_STENCIL_TEST));
stencil_shadow_ = enabled;
}
@@ -2033,16 +2037,16 @@ void GLRenderer::SetBlendEnabled(bool enabled) {
return;
if (enabled)
- GLC(context_, context_->enable(GL_BLEND));
+ GLC(gl_, gl_->Enable(GL_BLEND));
else
- GLC(context_, context_->disable(GL_BLEND));
+ GLC(gl_, gl_->Disable(GL_BLEND));
blend_shadow_ = enabled;
}
void GLRenderer::SetUseProgram(unsigned program) {
if (program == program_shadow_)
return;
- GLC(context_, context_->useProgram(program));
+ gl_->UseProgram(program);
program_shadow_ = program;
}
@@ -2054,10 +2058,9 @@ void GLRenderer::DrawQuadGeometry(const DrawingFrame* frame,
QuadRectTransform(&quad_rect_matrix, draw_transform, quad_rect);
static float gl_matrix[16];
ToGLMatrix(&gl_matrix[0], frame->projection_matrix * quad_rect_matrix);
- GLC(context_,
- context_->uniformMatrix4fv(matrix_location, 1, false, &gl_matrix[0]));
+ GLC(gl_, gl_->UniformMatrix4fv(matrix_location, 1, false, &gl_matrix[0]));
- GLC(context_, context_->drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0));
+ GLC(gl_, gl_->DrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0));
}
void GLRenderer::CopyTextureToFramebuffer(const DrawingFrame* frame,
@@ -2066,61 +2069,60 @@ void GLRenderer::CopyTextureToFramebuffer(const DrawingFrame* frame,
const gfx::Transform& draw_matrix,
bool flip_vertically) {
TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired(
- context_, &highp_threshold_cache_, highp_threshold_min_,
- rect.bottom_right());
+ gl_, &highp_threshold_cache_, highp_threshold_min_, rect.bottom_right());
const RenderPassProgram* program = GetRenderPassProgram(tex_coord_precision);
SetUseProgram(program->program());
- GLC(Context(), Context()->uniform1i(
- program->fragment_shader().sampler_location(), 0));
+ GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0));
if (flip_vertically) {
- GLC(Context(), Context()->uniform4f(
- program->vertex_shader().tex_transform_location(),
- 0.f,
- 1.f,
- 1.f,
- -1.f));
+ GLC(gl_,
+ gl_->Uniform4f(program->vertex_shader().tex_transform_location(),
+ 0.f,
+ 1.f,
+ 1.f,
+ -1.f));
} else {
- GLC(Context(), Context()->uniform4f(
- program->vertex_shader().tex_transform_location(),
- 0.f,
- 0.f,
- 1.f,
- 1.f));
+ GLC(gl_,
+ gl_->Uniform4f(program->vertex_shader().tex_transform_location(),
+ 0.f,
+ 0.f,
+ 1.f,
+ 1.f));
}
SetShaderOpacity(1.f, program->fragment_shader().alpha_location());
- DCHECK_EQ(GL_TEXTURE0, ResourceProvider::GetActiveTextureUnit(Context()));
- GLC(Context(), Context()->bindTexture(GL_TEXTURE_2D, texture_id));
+ DCHECK_EQ(GL_TEXTURE0, ResourceProvider::GetActiveTextureUnit(gl_));
+ GLC(gl_, gl_->BindTexture(GL_TEXTURE_2D, texture_id));
DrawQuadGeometry(
frame, draw_matrix, rect, program->vertex_shader().matrix_location());
}
void GLRenderer::Finish() {
- TRACE_EVENT0("cc", "GLRenderer::finish");
- context_->finish();
+ TRACE_EVENT0("cc", "GLRenderer::Finish");
+ GLC(gl_, gl_->Finish());
}
-void GLRenderer::SwapBuffers() {
- DCHECK(visible_);
+void GLRenderer::SwapBuffers(const CompositorFrameMetadata& metadata) {
DCHECK(!is_backbuffer_discarded_);
TRACE_EVENT0("cc", "GLRenderer::SwapBuffers");
// We're done! Time to swapbuffers!
+ gfx::Size surface_size = output_surface_->SurfaceSize();
+
CompositorFrame compositor_frame;
- compositor_frame.metadata = client_->MakeCompositorFrameMetadata();
+ compositor_frame.metadata = metadata;
compositor_frame.gl_frame_data = make_scoped_ptr(new GLFrameData);
- compositor_frame.gl_frame_data->size = output_surface_->SurfaceSize();
+ compositor_frame.gl_frame_data->size = surface_size;
if (capabilities_.using_partial_swap) {
// If supported, we can save significant bandwidth by only swapping the
- // damaged/scissored region (clamped to the viewport)
- swap_buffer_rect_.Intersect(client_->DeviceViewport());
- int flipped_y_pos_of_rect_bottom =
- client_->DeviceViewport().height() - swap_buffer_rect_.y() -
- swap_buffer_rect_.height();
+ // damaged/scissored region (clamped to the viewport).
+ swap_buffer_rect_.Intersect(gfx::Rect(surface_size));
+ int flipped_y_pos_of_rect_bottom = surface_size.height() -
+ swap_buffer_rect_.y() -
+ swap_buffer_rect_.height();
compositor_frame.gl_frame_data->sub_buffer_rect =
gfx::Rect(swap_buffer_rect_.x(),
flipped_y_pos_of_rect_bottom,
@@ -2143,19 +2145,13 @@ void GLRenderer::SwapBuffers() {
resource_provider_->SetReadLockFence(new SimpleSwapFence());
}
-void GLRenderer::SetDiscardBackBufferWhenNotVisible(bool discard) {
- discard_backbuffer_when_not_visible_ = discard;
- EnforceMemoryPolicy();
-}
-
void GLRenderer::EnforceMemoryPolicy() {
if (!visible_) {
TRACE_EVENT0("cc", "GLRenderer::EnforceMemoryPolicy dropping resources");
ReleaseRenderPassTextures();
- if (discard_backbuffer_when_not_visible_)
- DiscardBackbuffer();
+ DiscardBackbuffer();
resource_provider_->ReleaseCachedData();
- GLC(context_, context_->flush());
+ GLC(gl_, gl_->Flush());
}
}
@@ -2198,7 +2194,8 @@ void GLRenderer::GetFramebufferPixels(void* pixels, gfx::Rect rect) {
}
void GLRenderer::GetFramebufferPixelsAsync(
- gfx::Rect rect, scoped_ptr<CopyOutputRequest> request) {
+ gfx::Rect rect,
+ scoped_ptr<CopyOutputRequest> request) {
DCHECK(!request->IsEmpty());
if (request->IsEmpty())
return;
@@ -2208,48 +2205,69 @@ void GLRenderer::GetFramebufferPixelsAsync(
gfx::Rect window_rect = MoveFromDrawToWindowSpace(rect);
if (!request->force_bitmap_result()) {
- unsigned int texture_id = context_->createTexture();
- GLC(context_, context_->bindTexture(GL_TEXTURE_2D, texture_id));
- GLC(context_, context_->texParameteri(
- GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
- GLC(context_, context_->texParameteri(
- GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
- GLC(context_, context_->texParameteri(
- GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
- GLC(context_, context_->texParameteri(
- GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
- GetFramebufferTexture(texture_id, RGBA_8888, window_rect);
+ bool own_mailbox = !request->has_texture_mailbox();
+
+ GLuint texture_id = 0;
+ gl_->GenTextures(1, &texture_id);
gpu::Mailbox mailbox;
- unsigned sync_point = 0;
- GLC(context_, context_->genMailboxCHROMIUM(mailbox.name));
- if (mailbox.IsZero()) {
- context_->deleteTexture(texture_id);
- request->SendEmptyResult();
- return;
+ if (own_mailbox) {
+ GLC(gl_, gl_->GenMailboxCHROMIUM(mailbox.name));
+ if (mailbox.IsZero()) {
+ gl_->DeleteTextures(1, &texture_id);
+ request->SendEmptyResult();
+ return;
+ }
+ } else {
+ mailbox = request->texture_mailbox().name();
+ DCHECK_EQ(static_cast<unsigned>(GL_TEXTURE_2D),
+ request->texture_mailbox().target());
+ DCHECK(!mailbox.IsZero());
+ unsigned incoming_sync_point = request->texture_mailbox().sync_point();
+ if (incoming_sync_point)
+ GLC(gl_, gl_->WaitSyncPointCHROMIUM(incoming_sync_point));
}
- GLC(context_, context_->bindTexture(GL_TEXTURE_2D, texture_id));
- GLC(context_, context_->produceTextureCHROMIUM(
- GL_TEXTURE_2D, mailbox.name));
- GLC(context_, context_->bindTexture(GL_TEXTURE_2D, 0));
- sync_point = context_->insertSyncPoint();
+ GLC(gl_, gl_->BindTexture(GL_TEXTURE_2D, texture_id));
+ if (own_mailbox) {
+ GLC(gl_,
+ gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
+ GLC(gl_,
+ gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
+ GLC(gl_,
+ gl_->TexParameteri(
+ GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
+ GLC(gl_,
+ gl_->TexParameteri(
+ GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
+ GLC(gl_, gl_->ProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name));
+ } else {
+ GLC(gl_, gl_->ConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name));
+ }
+ GetFramebufferTexture(texture_id, RGBA_8888, window_rect);
+ GLC(gl_, gl_->BindTexture(GL_TEXTURE_2D, 0));
+
+ unsigned sync_point = gl_->InsertSyncPointCHROMIUM();
TextureMailbox texture_mailbox(mailbox, GL_TEXTURE_2D, sync_point);
- scoped_ptr<SingleReleaseCallback> release_callback =
- texture_mailbox_deleter_->GetReleaseCallback(
- output_surface_->context_provider(), texture_id);
- request->SendTextureResult(window_rect.size(),
- texture_mailbox,
- release_callback.Pass());
+
+ scoped_ptr<SingleReleaseCallback> release_callback;
+ if (own_mailbox) {
+ release_callback = texture_mailbox_deleter_->GetReleaseCallback(
+ output_surface_->context_provider(), texture_id);
+ } else {
+ gl_->DeleteTextures(1, &texture_id);
+ }
+
+ request->SendTextureResult(
+ window_rect.size(), texture_mailbox, release_callback.Pass());
return;
}
DCHECK(request->force_bitmap_result());
scoped_ptr<SkBitmap> bitmap(new SkBitmap);
- bitmap->setConfig(SkBitmap::kARGB_8888_Config,
- window_rect.width(),
- window_rect.height());
+ bitmap->setConfig(
+ SkBitmap::kARGB_8888_Config, window_rect.width(), window_rect.height());
bitmap->allocPixels();
scoped_ptr<SkAutoLockPixels> lock(new SkAutoLockPixels(*bitmap));
@@ -2257,11 +2275,11 @@ void GLRenderer::GetFramebufferPixelsAsync(
// Save a pointer to the pixels, the bitmap is owned by the cleanup_callback.
uint8* pixels = static_cast<uint8*>(bitmap->getPixels());
- AsyncGetFramebufferPixelsCleanupCallback cleanup_callback = base::Bind(
- &GLRenderer::PassOnSkBitmap,
- base::Unretained(this),
- base::Passed(&bitmap),
- base::Passed(&lock));
+ AsyncGetFramebufferPixelsCleanupCallback cleanup_callback =
+ base::Bind(&GLRenderer::PassOnSkBitmap,
+ base::Unretained(this),
+ base::Passed(&bitmap),
+ base::Passed(&lock));
scoped_ptr<PendingAsyncReadPixels> pending_read(new PendingAsyncReadPixels);
pending_read->copy_request = request.Pass();
@@ -2283,8 +2301,6 @@ void GLRenderer::DoGetFramebufferPixels(
bool is_async = !cleanup_callback.is_null();
- MakeContextCurrent();
-
bool do_workaround = NeedsIOSurfaceReadbackWorkaround();
unsigned temporary_texture = 0;
@@ -2297,78 +2313,75 @@ void GLRenderer::DoGetFramebufferPixels(
// is the root cause of top crasher
// http://crbug.com/99393. <rdar://problem/10949687>
- temporary_texture = context_->createTexture();
- GLC(context_, context_->bindTexture(GL_TEXTURE_2D, temporary_texture));
- GLC(context_, context_->texParameteri(
- GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
- GLC(context_, context_->texParameteri(
- GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
- GLC(context_, context_->texParameteri(
- GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
- GLC(context_, context_->texParameteri(
- GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
+ gl_->GenTextures(1, &temporary_texture);
+ GLC(gl_, gl_->BindTexture(GL_TEXTURE_2D, temporary_texture));
+ GLC(gl_,
+ gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
+ GLC(gl_,
+ gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
+ GLC(gl_,
+ gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
+ GLC(gl_,
+ gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
// Copy the contents of the current (IOSurface-backed) framebuffer into a
// temporary texture.
- GetFramebufferTexture(temporary_texture,
- RGBA_8888,
- gfx::Rect(current_surface_size_));
- temporary_fbo = context_->createFramebuffer();
+ GetFramebufferTexture(
+ temporary_texture, RGBA_8888, gfx::Rect(current_surface_size_));
+ gl_->GenFramebuffers(1, &temporary_fbo);
// Attach this texture to an FBO, and perform the readback from that FBO.
- GLC(context_, context_->bindFramebuffer(GL_FRAMEBUFFER, temporary_fbo));
- GLC(context_, context_->framebufferTexture2D(GL_FRAMEBUFFER,
- GL_COLOR_ATTACHMENT0,
- GL_TEXTURE_2D,
- temporary_texture,
- 0));
+ GLC(gl_, gl_->BindFramebuffer(GL_FRAMEBUFFER, temporary_fbo));
+ GLC(gl_,
+ gl_->FramebufferTexture2D(GL_FRAMEBUFFER,
+ GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D,
+ temporary_texture,
+ 0));
DCHECK_EQ(static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE),
- context_->checkFramebufferStatus(GL_FRAMEBUFFER));
+ gl_->CheckFramebufferStatus(GL_FRAMEBUFFER));
}
- unsigned buffer = context_->createBuffer();
- GLC(context_, context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM,
- buffer));
- GLC(context_, context_->bufferData(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM,
- 4 * window_rect.size().GetArea(),
- NULL,
- GL_STREAM_READ));
+ GLuint buffer = 0;
+ gl_->GenBuffers(1, &buffer);
+ GLC(gl_, gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, buffer));
+ GLC(gl_,
+ gl_->BufferData(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM,
+ 4 * window_rect.size().GetArea(),
+ NULL,
+ GL_STREAM_READ));
- WebKit::WebGLId query = 0;
+ GLuint query = 0;
if (is_async) {
- query = context_->createQueryEXT();
- GLC(context_, context_->beginQueryEXT(
- GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM,
- query));
+ gl_->GenQueriesEXT(1, &query);
+ GLC(gl_, gl_->BeginQueryEXT(GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM, query));
}
- GLC(context_,
- context_->readPixels(window_rect.x(),
- window_rect.y(),
- window_rect.width(),
- window_rect.height(),
- GL_RGBA,
- GL_UNSIGNED_BYTE,
- NULL));
+ GLC(gl_,
+ gl_->ReadPixels(window_rect.x(),
+ window_rect.y(),
+ window_rect.width(),
+ window_rect.height(),
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ NULL));
- GLC(context_, context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM,
- 0));
+ GLC(gl_, gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0));
if (do_workaround) {
// Clean up.
- GLC(context_, context_->bindFramebuffer(GL_FRAMEBUFFER, 0));
- GLC(context_, context_->bindTexture(GL_TEXTURE_2D, 0));
- GLC(context_, context_->deleteFramebuffer(temporary_fbo));
- GLC(context_, context_->deleteTexture(temporary_texture));
- }
-
- base::Closure finished_callback =
- base::Bind(&GLRenderer::FinishedReadback,
- base::Unretained(this),
- cleanup_callback,
- buffer,
- query,
- dest_pixels,
- window_rect.size());
+ GLC(gl_, gl_->BindFramebuffer(GL_FRAMEBUFFER, 0));
+ GLC(gl_, gl_->BindTexture(GL_TEXTURE_2D, 0));
+ GLC(gl_, gl_->DeleteFramebuffers(1, &temporary_fbo));
+ GLC(gl_, gl_->DeleteTextures(1, &temporary_texture));
+ }
+
+ base::Closure finished_callback = base::Bind(&GLRenderer::FinishedReadback,
+ base::Unretained(this),
+ cleanup_callback,
+ buffer,
+ query,
+ dest_pixels,
+ window_rect.size());
// Save the finished_callback so it can be cancelled.
pending_async_read_pixels_.front()->finished_read_pixels_callback.Reset(
finished_callback);
@@ -2377,12 +2390,8 @@ void GLRenderer::DoGetFramebufferPixels(
pending_async_read_pixels_.front()->buffer = buffer;
if (is_async) {
- GLC(context_, context_->endQueryEXT(
- GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM));
- SyncPointHelper::SignalQuery(
- context_,
- query,
- finished_callback);
+ GLC(gl_, gl_->EndQueryEXT(GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM));
+ context_support_->SignalQuery(query, finished_callback);
} else {
resource_provider_->Finish();
finished_callback.Run();
@@ -2400,7 +2409,7 @@ void GLRenderer::FinishedReadback(
DCHECK(!pending_async_read_pixels_.empty());
if (query != 0) {
- GLC(context_, context_->deleteQueryEXT(query));
+ GLC(gl_, gl_->DeleteQueriesEXT(1, &query));
}
PendingAsyncReadPixels* current_read = pending_async_read_pixels_.back();
@@ -2410,11 +2419,10 @@ void GLRenderer::FinishedReadback(
uint8* src_pixels = NULL;
if (source_buffer != 0) {
- GLC(context_, context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM,
- source_buffer));
- src_pixels = static_cast<uint8*>(
- context_->mapBufferCHROMIUM(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM,
- GL_READ_ONLY));
+ GLC(gl_,
+ gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, source_buffer));
+ src_pixels = static_cast<uint8*>(gl_->MapBufferCHROMIUM(
+ GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, GL_READ_ONLY));
if (src_pixels) {
size_t row_bytes = size.width() * 4;
@@ -2425,19 +2433,22 @@ void GLRenderer::FinishedReadback(
size_t src_y = total_bytes - dest_y - row_bytes;
// Swizzle OpenGL -> Skia byte order.
for (size_t x = 0; x < row_bytes; x += 4) {
- dest_pixels[dest_y + x + SK_R32_SHIFT/8] = src_pixels[src_y + x + 0];
- dest_pixels[dest_y + x + SK_G32_SHIFT/8] = src_pixels[src_y + x + 1];
- dest_pixels[dest_y + x + SK_B32_SHIFT/8] = src_pixels[src_y + x + 2];
- dest_pixels[dest_y + x + SK_A32_SHIFT/8] = src_pixels[src_y + x + 3];
+ dest_pixels[dest_y + x + SK_R32_SHIFT / 8] =
+ src_pixels[src_y + x + 0];
+ dest_pixels[dest_y + x + SK_G32_SHIFT / 8] =
+ src_pixels[src_y + x + 1];
+ dest_pixels[dest_y + x + SK_B32_SHIFT / 8] =
+ src_pixels[src_y + x + 2];
+ dest_pixels[dest_y + x + SK_A32_SHIFT / 8] =
+ src_pixels[src_y + x + 3];
}
}
- GLC(context_, context_->unmapBufferCHROMIUM(
- GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM));
+ GLC(gl_,
+ gl_->UnmapBufferCHROMIUM(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM));
}
- GLC(context_, context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM,
- 0));
- GLC(context_, context_->deleteBuffer(source_buffer));
+ GLC(gl_, gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0));
+ GLC(gl_, gl_->DeleteBuffers(1, &source_buffer));
}
// TODO(danakj): This can go away when synchronous readback is no more and its
@@ -2448,11 +2459,10 @@ void GLRenderer::FinishedReadback(
pending_async_read_pixels_.pop_back();
}
-void GLRenderer::PassOnSkBitmap(
- scoped_ptr<SkBitmap> bitmap,
- scoped_ptr<SkAutoLockPixels> lock,
- scoped_ptr<CopyOutputRequest> request,
- bool success) {
+void GLRenderer::PassOnSkBitmap(scoped_ptr<SkBitmap> bitmap,
+ scoped_ptr<SkAutoLockPixels> lock,
+ scoped_ptr<CopyOutputRequest> request,
+ bool success) {
DCHECK(request->force_bitmap_result());
lock.reset();
@@ -2460,26 +2470,26 @@ void GLRenderer::PassOnSkBitmap(
request->SendBitmapResult(bitmap.Pass());
}
-void GLRenderer::GetFramebufferTexture(
- unsigned texture_id, ResourceFormat texture_format, gfx::Rect window_rect) {
+void GLRenderer::GetFramebufferTexture(unsigned texture_id,
+ ResourceFormat texture_format,
+ gfx::Rect window_rect) {
DCHECK(texture_id);
DCHECK_GE(window_rect.x(), 0);
DCHECK_GE(window_rect.y(), 0);
DCHECK_LE(window_rect.right(), current_surface_size_.width());
DCHECK_LE(window_rect.bottom(), current_surface_size_.height());
- GLC(context_, context_->bindTexture(GL_TEXTURE_2D, texture_id));
- GLC(context_,
- context_->copyTexImage2D(
- GL_TEXTURE_2D,
- 0,
- ResourceProvider::GetGLDataFormat(texture_format),
- window_rect.x(),
- window_rect.y(),
- window_rect.width(),
- window_rect.height(),
- 0));
- GLC(context_, context_->bindTexture(GL_TEXTURE_2D, 0));
+ GLC(gl_, gl_->BindTexture(GL_TEXTURE_2D, texture_id));
+ GLC(gl_,
+ gl_->CopyTexImage2D(GL_TEXTURE_2D,
+ 0,
+ GLDataFormat(texture_format),
+ window_rect.x(),
+ window_rect.y(),
+ window_rect.width(),
+ window_rect.height(),
+ 0));
+ GLC(gl_, gl_->BindTexture(GL_TEXTURE_2D, 0));
}
bool GLRenderer::UseScopedTexture(DrawingFrame* frame,
@@ -2498,7 +2508,7 @@ void GLRenderer::BindFramebufferToOutputSurface(DrawingFrame* frame) {
if (output_surface_->HasExternalStencilTest()) {
SetStencilEnabled(true);
- GLC(context_, context_->stencilFunc(GL_EQUAL, 1, 1));
+ GLC(gl_, gl_->StencilFunc(GL_EQUAL, 1, 1));
} else {
SetStencilEnabled(false);
}
@@ -2512,23 +2522,21 @@ bool GLRenderer::BindFramebufferToTexture(DrawingFrame* frame,
current_framebuffer_lock_.reset();
SetStencilEnabled(false);
- GLC(context_,
- context_->bindFramebuffer(GL_FRAMEBUFFER, offscreen_framebuffer_id_));
+ GLC(gl_, gl_->BindFramebuffer(GL_FRAMEBUFFER, offscreen_framebuffer_id_));
current_framebuffer_lock_ =
make_scoped_ptr(new ResourceProvider::ScopedWriteLockGL(
resource_provider_, texture->id()));
unsigned texture_id = current_framebuffer_lock_->texture_id();
- GLC(context_,
- context_->framebufferTexture2D(
+ GLC(gl_,
+ gl_->FramebufferTexture2D(
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_id, 0));
- DCHECK(context_->checkFramebufferStatus(GL_FRAMEBUFFER) ==
- GL_FRAMEBUFFER_COMPLETE || IsContextLost());
+ DCHECK(gl_->CheckFramebufferStatus(GL_FRAMEBUFFER) ==
+ GL_FRAMEBUFFER_COMPLETE ||
+ IsContextLost());
- InitializeViewport(frame,
- target_rect,
- gfx::Rect(target_rect.size()),
- target_rect.size());
+ InitializeViewport(
+ frame, target_rect, gfx::Rect(target_rect.size()), target_rect.size());
return true;
}
@@ -2537,550 +2545,441 @@ void GLRenderer::SetScissorTestRect(gfx::Rect scissor_rect) {
// Don't unnecessarily ask the context to change the scissor, because it
// may cause undesired GPU pipeline flushes.
- if (scissor_rect == scissor_rect_)
+ if (scissor_rect == scissor_rect_ && !scissor_rect_needs_reset_)
return;
scissor_rect_ = scissor_rect;
FlushTextureQuadCache();
- GLC(context_,
- context_->scissor(scissor_rect.x(),
- scissor_rect.y(),
- scissor_rect.width(),
- scissor_rect.height()));
+ GLC(gl_,
+ gl_->Scissor(scissor_rect.x(),
+ scissor_rect.y(),
+ scissor_rect.width(),
+ scissor_rect.height()));
+
+ scissor_rect_needs_reset_ = false;
}
void GLRenderer::SetDrawViewport(gfx::Rect window_space_viewport) {
viewport_ = window_space_viewport;
- GLC(context_, context_->viewport(window_space_viewport.x(),
- window_space_viewport.y(),
- window_space_viewport.width(),
- window_space_viewport.height()));
+ GLC(gl_,
+ gl_->Viewport(window_space_viewport.x(),
+ window_space_viewport.y(),
+ window_space_viewport.width(),
+ window_space_viewport.height()));
}
-bool GLRenderer::MakeContextCurrent() { return context_->makeContextCurrent(); }
-
-bool GLRenderer::InitializeSharedObjects() {
+void GLRenderer::InitializeSharedObjects() {
TRACE_EVENT0("cc", "GLRenderer::InitializeSharedObjects");
- MakeContextCurrent();
// Create an FBO for doing offscreen rendering.
- GLC(context_, offscreen_framebuffer_id_ = context_->createFramebuffer());
+ GLC(gl_, gl_->GenFramebuffers(1, &offscreen_framebuffer_id_));
- // We will always need these programs to render, so create the programs
- // eagerly so that the shader compilation can start while we do other work.
- // Other programs are created lazily on first access.
shared_geometry_ = make_scoped_ptr(
- new GeometryBinding(context_, QuadVertexRect()));
- render_pass_program_ = make_scoped_ptr(
- new RenderPassProgram(context_, TexCoordPrecisionMedium));
- render_pass_program_highp_ = make_scoped_ptr(
- new RenderPassProgram(context_, TexCoordPrecisionHigh));
- tile_program_ = make_scoped_ptr(
- new TileProgram(context_, TexCoordPrecisionMedium));
- tile_program_opaque_ = make_scoped_ptr(
- new TileProgramOpaque(context_, TexCoordPrecisionMedium));
- tile_program_highp_ = make_scoped_ptr(
- new TileProgram(context_, TexCoordPrecisionHigh));
- tile_program_opaque_highp_ = make_scoped_ptr(
- new TileProgramOpaque(context_, TexCoordPrecisionHigh));
-
- GLC(context_, context_->flush());
-
- return true;
+ new GeometryBinding(gl_, QuadVertexRect()));
}
const GLRenderer::TileCheckerboardProgram*
GLRenderer::GetTileCheckerboardProgram() {
- if (!tile_checkerboard_program_)
- tile_checkerboard_program_ = make_scoped_ptr(
- new TileCheckerboardProgram(context_, TexCoordPrecisionNA));
- if (!tile_checkerboard_program_->initialized()) {
+ if (!tile_checkerboard_program_.initialized()) {
TRACE_EVENT0("cc", "GLRenderer::checkerboardProgram::initalize");
- tile_checkerboard_program_->Initialize(context_, is_using_bind_uniform_);
+ tile_checkerboard_program_.Initialize(output_surface_->context_provider(),
+ TexCoordPrecisionNA,
+ SamplerTypeNA);
}
- return tile_checkerboard_program_.get();
+ return &tile_checkerboard_program_;
}
const GLRenderer::DebugBorderProgram* GLRenderer::GetDebugBorderProgram() {
- if (!debug_border_program_)
- debug_border_program_ = make_scoped_ptr(
- new DebugBorderProgram(context_, TexCoordPrecisionNA));
- if (!debug_border_program_->initialized()) {
+ if (!debug_border_program_.initialized()) {
TRACE_EVENT0("cc", "GLRenderer::debugBorderProgram::initialize");
- debug_border_program_->Initialize(context_, is_using_bind_uniform_);
+ debug_border_program_.Initialize(output_surface_->context_provider(),
+ TexCoordPrecisionNA,
+ SamplerTypeNA);
}
- return debug_border_program_.get();
+ return &debug_border_program_;
}
const GLRenderer::SolidColorProgram* GLRenderer::GetSolidColorProgram() {
- if (!solid_color_program_)
- solid_color_program_ = make_scoped_ptr(
- new SolidColorProgram(context_, TexCoordPrecisionNA));
- if (!solid_color_program_->initialized()) {
+ if (!solid_color_program_.initialized()) {
TRACE_EVENT0("cc", "GLRenderer::solidColorProgram::initialize");
- solid_color_program_->Initialize(context_, is_using_bind_uniform_);
+ solid_color_program_.Initialize(output_surface_->context_provider(),
+ TexCoordPrecisionNA,
+ SamplerTypeNA);
}
- return solid_color_program_.get();
+ return &solid_color_program_;
}
const GLRenderer::SolidColorProgramAA* GLRenderer::GetSolidColorProgramAA() {
- if (!solid_color_program_aa_) {
- solid_color_program_aa_ =
- make_scoped_ptr(new SolidColorProgramAA(context_, TexCoordPrecisionNA));
- }
- if (!solid_color_program_aa_->initialized()) {
+ if (!solid_color_program_aa_.initialized()) {
TRACE_EVENT0("cc", "GLRenderer::solidColorProgramAA::initialize");
- solid_color_program_aa_->Initialize(context_, is_using_bind_uniform_);
+ solid_color_program_aa_.Initialize(output_surface_->context_provider(),
+ TexCoordPrecisionNA,
+ SamplerTypeNA);
}
- return solid_color_program_aa_.get();
+ return &solid_color_program_aa_;
}
const GLRenderer::RenderPassProgram* GLRenderer::GetRenderPassProgram(
- TexCoordPrecision precision) {
- scoped_ptr<RenderPassProgram>& program =
- (precision == TexCoordPrecisionHigh) ? render_pass_program_highp_
- : render_pass_program_;
- DCHECK(program);
+ TexCoordPrecision precision) {
+ DCHECK_GE(precision, 0);
+ DCHECK_LT(precision, NumTexCoordPrecisions);
+ RenderPassProgram* program = &render_pass_program_[precision];
if (!program->initialized()) {
TRACE_EVENT0("cc", "GLRenderer::renderPassProgram::initialize");
- program->Initialize(context_, is_using_bind_uniform_);
+ program->Initialize(
+ output_surface_->context_provider(), precision, SamplerType2D);
}
- return program.get();
+ return program;
}
const GLRenderer::RenderPassProgramAA* GLRenderer::GetRenderPassProgramAA(
- TexCoordPrecision precision) {
- scoped_ptr<RenderPassProgramAA>& program =
- (precision == TexCoordPrecisionHigh) ? render_pass_program_aa_highp_
- : render_pass_program_aa_;
- if (!program)
- program =
- make_scoped_ptr(new RenderPassProgramAA(context_, precision));
+ TexCoordPrecision precision) {
+ DCHECK_GE(precision, 0);
+ DCHECK_LT(precision, NumTexCoordPrecisions);
+ RenderPassProgramAA* program = &render_pass_program_aa_[precision];
if (!program->initialized()) {
TRACE_EVENT0("cc", "GLRenderer::renderPassProgramAA::initialize");
- program->Initialize(context_, is_using_bind_uniform_);
+ program->Initialize(
+ output_surface_->context_provider(), precision, SamplerType2D);
}
- return program.get();
+ return program;
}
-const GLRenderer::RenderPassMaskProgram*
-GLRenderer::GetRenderPassMaskProgram(TexCoordPrecision precision) {
- scoped_ptr<RenderPassMaskProgram>& program =
- (precision == TexCoordPrecisionHigh) ? render_pass_mask_program_highp_
- : render_pass_mask_program_;
- if (!program)
- program = make_scoped_ptr(new RenderPassMaskProgram(context_, precision));
+const GLRenderer::RenderPassMaskProgram* GLRenderer::GetRenderPassMaskProgram(
+ TexCoordPrecision precision) {
+ DCHECK_GE(precision, 0);
+ DCHECK_LT(precision, NumTexCoordPrecisions);
+ RenderPassMaskProgram* program = &render_pass_mask_program_[precision];
if (!program->initialized()) {
TRACE_EVENT0("cc", "GLRenderer::renderPassMaskProgram::initialize");
- program->Initialize(context_, is_using_bind_uniform_);
+ program->Initialize(
+ output_surface_->context_provider(), precision, SamplerType2D);
}
- return program.get();
+ return program;
}
const GLRenderer::RenderPassMaskProgramAA*
GLRenderer::GetRenderPassMaskProgramAA(TexCoordPrecision precision) {
- scoped_ptr<RenderPassMaskProgramAA>& program =
- (precision == TexCoordPrecisionHigh) ? render_pass_mask_program_aa_highp_
- : render_pass_mask_program_aa_;
- if (!program)
- program =
- make_scoped_ptr(new RenderPassMaskProgramAA(context_, precision));
+ DCHECK_GE(precision, 0);
+ DCHECK_LT(precision, NumTexCoordPrecisions);
+ RenderPassMaskProgramAA* program = &render_pass_mask_program_aa_[precision];
if (!program->initialized()) {
TRACE_EVENT0("cc", "GLRenderer::renderPassMaskProgramAA::initialize");
- program->Initialize(context_, is_using_bind_uniform_);
+ program->Initialize(
+ output_surface_->context_provider(), precision, SamplerType2D);
}
- return program.get();
+ return program;
}
const GLRenderer::RenderPassColorMatrixProgram*
GLRenderer::GetRenderPassColorMatrixProgram(TexCoordPrecision precision) {
- scoped_ptr<RenderPassColorMatrixProgram>& program =
- (precision == TexCoordPrecisionHigh) ?
- render_pass_color_matrix_program_highp_ :
- render_pass_color_matrix_program_;
- if (!program)
- program = make_scoped_ptr(
- new RenderPassColorMatrixProgram(context_, precision));
+ DCHECK_GE(precision, 0);
+ DCHECK_LT(precision, NumTexCoordPrecisions);
+ RenderPassColorMatrixProgram* program =
+ &render_pass_color_matrix_program_[precision];
if (!program->initialized()) {
TRACE_EVENT0("cc", "GLRenderer::renderPassColorMatrixProgram::initialize");
- program->Initialize(context_, is_using_bind_uniform_);
+ program->Initialize(
+ output_surface_->context_provider(), precision, SamplerType2D);
}
- return program.get();
+ return program;
}
const GLRenderer::RenderPassColorMatrixProgramAA*
GLRenderer::GetRenderPassColorMatrixProgramAA(TexCoordPrecision precision) {
- scoped_ptr<RenderPassColorMatrixProgramAA>& program =
- (precision == TexCoordPrecisionHigh) ?
- render_pass_color_matrix_program_aa_highp_ :
- render_pass_color_matrix_program_aa_;
- if (!program)
- program = make_scoped_ptr(
- new RenderPassColorMatrixProgramAA(context_, precision));
+ DCHECK_GE(precision, 0);
+ DCHECK_LT(precision, NumTexCoordPrecisions);
+ RenderPassColorMatrixProgramAA* program =
+ &render_pass_color_matrix_program_aa_[precision];
if (!program->initialized()) {
TRACE_EVENT0("cc",
"GLRenderer::renderPassColorMatrixProgramAA::initialize");
- program->Initialize(context_, is_using_bind_uniform_);
+ program->Initialize(
+ output_surface_->context_provider(), precision, SamplerType2D);
}
- return program.get();
+ return program;
}
const GLRenderer::RenderPassMaskColorMatrixProgram*
GLRenderer::GetRenderPassMaskColorMatrixProgram(TexCoordPrecision precision) {
- scoped_ptr<RenderPassMaskColorMatrixProgram>& program =
- (precision == TexCoordPrecisionHigh) ?
- render_pass_mask_color_matrix_program_highp_ :
- render_pass_mask_color_matrix_program_;
- if (!program)
- program = make_scoped_ptr(
- new RenderPassMaskColorMatrixProgram(context_, precision));
+ DCHECK_GE(precision, 0);
+ DCHECK_LT(precision, NumTexCoordPrecisions);
+ RenderPassMaskColorMatrixProgram* program =
+ &render_pass_mask_color_matrix_program_[precision];
if (!program->initialized()) {
TRACE_EVENT0("cc",
"GLRenderer::renderPassMaskColorMatrixProgram::initialize");
- program->Initialize(context_, is_using_bind_uniform_);
+ program->Initialize(
+ output_surface_->context_provider(), precision, SamplerType2D);
}
- return program.get();
+ return program;
}
const GLRenderer::RenderPassMaskColorMatrixProgramAA*
GLRenderer::GetRenderPassMaskColorMatrixProgramAA(TexCoordPrecision precision) {
- scoped_ptr<RenderPassMaskColorMatrixProgramAA>& program =
- (precision == TexCoordPrecisionHigh) ?
- render_pass_mask_color_matrix_program_aa_highp_ :
- render_pass_mask_color_matrix_program_aa_;
- if (!program)
- program = make_scoped_ptr(
- new RenderPassMaskColorMatrixProgramAA(context_, precision));
+ DCHECK_GE(precision, 0);
+ DCHECK_LT(precision, NumTexCoordPrecisions);
+ RenderPassMaskColorMatrixProgramAA* program =
+ &render_pass_mask_color_matrix_program_aa_[precision];
if (!program->initialized()) {
TRACE_EVENT0("cc",
"GLRenderer::renderPassMaskColorMatrixProgramAA::initialize");
- program->Initialize(context_, is_using_bind_uniform_);
+ program->Initialize(
+ output_surface_->context_provider(), precision, SamplerType2D);
}
- return program.get();
+ return program;
}
const GLRenderer::TileProgram* GLRenderer::GetTileProgram(
- TexCoordPrecision precision) {
- scoped_ptr<TileProgram>& program =
- (precision == TexCoordPrecisionHigh) ? tile_program_highp_
- : tile_program_;
- DCHECK(program);
+ TexCoordPrecision precision,
+ SamplerType sampler) {
+ DCHECK_GE(precision, 0);
+ DCHECK_LT(precision, NumTexCoordPrecisions);
+ DCHECK_GE(sampler, 0);
+ DCHECK_LT(sampler, NumSamplerTypes);
+ TileProgram* program = &tile_program_[precision][sampler];
if (!program->initialized()) {
TRACE_EVENT0("cc", "GLRenderer::tileProgram::initialize");
- program->Initialize(context_, is_using_bind_uniform_);
+ program->Initialize(
+ output_surface_->context_provider(), precision, sampler);
}
- return program.get();
+ return program;
}
const GLRenderer::TileProgramOpaque* GLRenderer::GetTileProgramOpaque(
- TexCoordPrecision precision) {
- scoped_ptr<TileProgramOpaque>& program =
- (precision == TexCoordPrecisionHigh) ? tile_program_opaque_highp_
- : tile_program_opaque_;
- DCHECK(program);
+ TexCoordPrecision precision,
+ SamplerType sampler) {
+ DCHECK_GE(precision, 0);
+ DCHECK_LT(precision, NumTexCoordPrecisions);
+ DCHECK_GE(sampler, 0);
+ DCHECK_LT(sampler, NumSamplerTypes);
+ TileProgramOpaque* program = &tile_program_opaque_[precision][sampler];
if (!program->initialized()) {
TRACE_EVENT0("cc", "GLRenderer::tileProgramOpaque::initialize");
- program->Initialize(context_, is_using_bind_uniform_);
+ program->Initialize(
+ output_surface_->context_provider(), precision, sampler);
}
- return program.get();
+ return program;
}
const GLRenderer::TileProgramAA* GLRenderer::GetTileProgramAA(
- TexCoordPrecision precision) {
- scoped_ptr<TileProgramAA>& program =
- (precision == TexCoordPrecisionHigh) ? tile_program_aa_highp_
- : tile_program_aa_;
- if (!program)
- program = make_scoped_ptr(new TileProgramAA(context_, precision));
+ TexCoordPrecision precision,
+ SamplerType sampler) {
+ DCHECK_GE(precision, 0);
+ DCHECK_LT(precision, NumTexCoordPrecisions);
+ DCHECK_GE(sampler, 0);
+ DCHECK_LT(sampler, NumSamplerTypes);
+ TileProgramAA* program = &tile_program_aa_[precision][sampler];
if (!program->initialized()) {
TRACE_EVENT0("cc", "GLRenderer::tileProgramAA::initialize");
- program->Initialize(context_, is_using_bind_uniform_);
+ program->Initialize(
+ output_surface_->context_provider(), precision, sampler);
}
- return program.get();
+ return program;
}
const GLRenderer::TileProgramSwizzle* GLRenderer::GetTileProgramSwizzle(
- TexCoordPrecision precision) {
- scoped_ptr<TileProgramSwizzle>& program =
- (precision == TexCoordPrecisionHigh) ? tile_program_swizzle_highp_
- : tile_program_swizzle_;
- if (!program)
- program = make_scoped_ptr(new TileProgramSwizzle(context_, precision));
+ TexCoordPrecision precision,
+ SamplerType sampler) {
+ DCHECK_GE(precision, 0);
+ DCHECK_LT(precision, NumTexCoordPrecisions);
+ DCHECK_GE(sampler, 0);
+ DCHECK_LT(sampler, NumSamplerTypes);
+ TileProgramSwizzle* program = &tile_program_swizzle_[precision][sampler];
if (!program->initialized()) {
TRACE_EVENT0("cc", "GLRenderer::tileProgramSwizzle::initialize");
- program->Initialize(context_, is_using_bind_uniform_);
+ program->Initialize(
+ output_surface_->context_provider(), precision, sampler);
}
- return program.get();
+ return program;
}
const GLRenderer::TileProgramSwizzleOpaque*
-GLRenderer::GetTileProgramSwizzleOpaque(TexCoordPrecision precision) {
- scoped_ptr<TileProgramSwizzleOpaque>& program =
- (precision == TexCoordPrecisionHigh) ? tile_program_swizzle_opaque_highp_
- : tile_program_swizzle_opaque_;
- if (!program)
- program = make_scoped_ptr(
- new TileProgramSwizzleOpaque(context_, precision));
+GLRenderer::GetTileProgramSwizzleOpaque(TexCoordPrecision precision,
+ SamplerType sampler) {
+ DCHECK_GE(precision, 0);
+ DCHECK_LT(precision, NumTexCoordPrecisions);
+ DCHECK_GE(sampler, 0);
+ DCHECK_LT(sampler, NumSamplerTypes);
+ TileProgramSwizzleOpaque* program =
+ &tile_program_swizzle_opaque_[precision][sampler];
if (!program->initialized()) {
TRACE_EVENT0("cc", "GLRenderer::tileProgramSwizzleOpaque::initialize");
- program->Initialize(context_, is_using_bind_uniform_);
+ program->Initialize(
+ output_surface_->context_provider(), precision, sampler);
}
- return program.get();
+ return program;
}
const GLRenderer::TileProgramSwizzleAA* GLRenderer::GetTileProgramSwizzleAA(
- TexCoordPrecision precision) {
- scoped_ptr<TileProgramSwizzleAA>& program =
- (precision == TexCoordPrecisionHigh) ? tile_program_swizzle_aa_highp_
- : tile_program_swizzle_aa_;
- if (!program)
- program = make_scoped_ptr(new TileProgramSwizzleAA(context_, precision));
+ TexCoordPrecision precision,
+ SamplerType sampler) {
+ DCHECK_GE(precision, 0);
+ DCHECK_LT(precision, NumTexCoordPrecisions);
+ DCHECK_GE(sampler, 0);
+ DCHECK_LT(sampler, NumSamplerTypes);
+ TileProgramSwizzleAA* program = &tile_program_swizzle_aa_[precision][sampler];
if (!program->initialized()) {
TRACE_EVENT0("cc", "GLRenderer::tileProgramSwizzleAA::initialize");
- program->Initialize(context_, is_using_bind_uniform_);
+ program->Initialize(
+ output_surface_->context_provider(), precision, sampler);
}
- return program.get();
+ return program;
}
const GLRenderer::TextureProgram* GLRenderer::GetTextureProgram(
TexCoordPrecision precision) {
- scoped_ptr<TextureProgram>& program =
- (precision == TexCoordPrecisionHigh) ? texture_program_highp_
- : texture_program_;
- if (!program)
- program = make_scoped_ptr(new TextureProgram(context_, precision));
+ DCHECK_GE(precision, 0);
+ DCHECK_LT(precision, NumTexCoordPrecisions);
+ TextureProgram* program = &texture_program_[precision];
if (!program->initialized()) {
TRACE_EVENT0("cc", "GLRenderer::textureProgram::initialize");
- program->Initialize(context_, is_using_bind_uniform_);
+ program->Initialize(
+ output_surface_->context_provider(), precision, SamplerType2D);
}
- return program.get();
+ return program;
}
const GLRenderer::NonPremultipliedTextureProgram*
- GLRenderer::GetNonPremultipliedTextureProgram(TexCoordPrecision precision) {
- scoped_ptr<NonPremultipliedTextureProgram>& program =
- (precision == TexCoordPrecisionHigh) ?
- nonpremultiplied_texture_program_highp_ :
- nonpremultiplied_texture_program_;
- if (!program) {
- program = make_scoped_ptr(
- new NonPremultipliedTextureProgram(context_, precision));
- }
+GLRenderer::GetNonPremultipliedTextureProgram(TexCoordPrecision precision) {
+ DCHECK_GE(precision, 0);
+ DCHECK_LT(precision, NumTexCoordPrecisions);
+ NonPremultipliedTextureProgram* program =
+ &nonpremultiplied_texture_program_[precision];
if (!program->initialized()) {
TRACE_EVENT0("cc",
"GLRenderer::NonPremultipliedTextureProgram::Initialize");
- program->Initialize(context_, is_using_bind_uniform_);
+ program->Initialize(
+ output_surface_->context_provider(), precision, SamplerType2D);
}
- return program.get();
+ return program;
}
const GLRenderer::TextureBackgroundProgram*
GLRenderer::GetTextureBackgroundProgram(TexCoordPrecision precision) {
- scoped_ptr<TextureBackgroundProgram>& program =
- (precision == TexCoordPrecisionHigh) ? texture_background_program_highp_
- : texture_background_program_;
- if (!program) {
- program = make_scoped_ptr(
- new TextureBackgroundProgram(context_, precision));
- }
+ DCHECK_GE(precision, 0);
+ DCHECK_LT(precision, NumTexCoordPrecisions);
+ TextureBackgroundProgram* program = &texture_background_program_[precision];
if (!program->initialized()) {
TRACE_EVENT0("cc", "GLRenderer::textureProgram::initialize");
- program->Initialize(context_, is_using_bind_uniform_);
+ program->Initialize(
+ output_surface_->context_provider(), precision, SamplerType2D);
}
- return program.get();
+ return program;
}
const GLRenderer::NonPremultipliedTextureBackgroundProgram*
GLRenderer::GetNonPremultipliedTextureBackgroundProgram(
TexCoordPrecision precision) {
- scoped_ptr<NonPremultipliedTextureBackgroundProgram>& program =
- (precision == TexCoordPrecisionHigh) ?
- nonpremultiplied_texture_background_program_highp_ :
- nonpremultiplied_texture_background_program_;
- if (!program) {
- program = make_scoped_ptr(
- new NonPremultipliedTextureBackgroundProgram(context_, precision));
- }
+ DCHECK_GE(precision, 0);
+ DCHECK_LT(precision, NumTexCoordPrecisions);
+ NonPremultipliedTextureBackgroundProgram* program =
+ &nonpremultiplied_texture_background_program_[precision];
if (!program->initialized()) {
TRACE_EVENT0("cc",
"GLRenderer::NonPremultipliedTextureProgram::Initialize");
- program->Initialize(context_, is_using_bind_uniform_);
+ program->Initialize(
+ output_surface_->context_provider(), precision, SamplerType2D);
}
- return program.get();
+ return program;
}
-const GLRenderer::TextureIOSurfaceProgram*
-GLRenderer::GetTextureIOSurfaceProgram(TexCoordPrecision precision) {
- scoped_ptr<TextureIOSurfaceProgram>& program =
- (precision == TexCoordPrecisionHigh) ? texture_io_surface_program_highp_
- : texture_io_surface_program_;
- if (!program)
- program =
- make_scoped_ptr(new TextureIOSurfaceProgram(context_, precision));
+const GLRenderer::TextureProgram* GLRenderer::GetTextureIOSurfaceProgram(
+ TexCoordPrecision precision) {
+ DCHECK_GE(precision, 0);
+ DCHECK_LT(precision, NumTexCoordPrecisions);
+ TextureProgram* program = &texture_io_surface_program_[precision];
if (!program->initialized()) {
TRACE_EVENT0("cc", "GLRenderer::textureIOSurfaceProgram::initialize");
- program->Initialize(context_, is_using_bind_uniform_);
+ program->Initialize(
+ output_surface_->context_provider(), precision, SamplerType2DRect);
}
- return program.get();
+ return program;
}
const GLRenderer::VideoYUVProgram* GLRenderer::GetVideoYUVProgram(
TexCoordPrecision precision) {
- scoped_ptr<VideoYUVProgram>& program =
- (precision == TexCoordPrecisionHigh) ? video_yuv_program_highp_
- : video_yuv_program_;
- if (!program)
- program = make_scoped_ptr(new VideoYUVProgram(context_, precision));
+ DCHECK_GE(precision, 0);
+ DCHECK_LT(precision, NumTexCoordPrecisions);
+ VideoYUVProgram* program = &video_yuv_program_[precision];
if (!program->initialized()) {
TRACE_EVENT0("cc", "GLRenderer::videoYUVProgram::initialize");
- program->Initialize(context_, is_using_bind_uniform_);
+ program->Initialize(
+ output_surface_->context_provider(), precision, SamplerType2D);
}
- return program.get();
+ return program;
}
const GLRenderer::VideoYUVAProgram* GLRenderer::GetVideoYUVAProgram(
TexCoordPrecision precision) {
- scoped_ptr<VideoYUVAProgram>& program =
- (precision == TexCoordPrecisionHigh) ? video_yuva_program_highp_
- : video_yuva_program_;
- if (!program)
- program = make_scoped_ptr(new VideoYUVAProgram(context_, precision));
+ DCHECK_GE(precision, 0);
+ DCHECK_LT(precision, NumTexCoordPrecisions);
+ VideoYUVAProgram* program = &video_yuva_program_[precision];
if (!program->initialized()) {
TRACE_EVENT0("cc", "GLRenderer::videoYUVAProgram::initialize");
- program->Initialize(context_, is_using_bind_uniform_);
+ program->Initialize(
+ output_surface_->context_provider(), precision, SamplerType2D);
}
- return program.get();
+ return program;
}
const GLRenderer::VideoStreamTextureProgram*
GLRenderer::GetVideoStreamTextureProgram(TexCoordPrecision precision) {
if (!Capabilities().using_egl_image)
return NULL;
- scoped_ptr<VideoStreamTextureProgram>& program =
- (precision == TexCoordPrecisionHigh) ? video_stream_texture_program_highp_
- : video_stream_texture_program_;
- if (!program)
- program =
- make_scoped_ptr(new VideoStreamTextureProgram(context_, precision));
+ DCHECK_GE(precision, 0);
+ DCHECK_LT(precision, NumTexCoordPrecisions);
+ VideoStreamTextureProgram* program =
+ &video_stream_texture_program_[precision];
if (!program->initialized()) {
TRACE_EVENT0("cc", "GLRenderer::streamTextureProgram::initialize");
- program->Initialize(context_, is_using_bind_uniform_);
+ program->Initialize(
+ output_surface_->context_provider(), precision, SamplerTypeExternalOES);
}
- return program.get();
+ return program;
}
void GLRenderer::CleanupSharedObjects() {
- MakeContextCurrent();
-
shared_geometry_.reset();
- if (tile_program_)
- tile_program_->Cleanup(context_);
- if (tile_program_opaque_)
- tile_program_opaque_->Cleanup(context_);
- if (tile_program_swizzle_)
- tile_program_swizzle_->Cleanup(context_);
- if (tile_program_swizzle_opaque_)
- tile_program_swizzle_opaque_->Cleanup(context_);
- if (tile_program_aa_)
- tile_program_aa_->Cleanup(context_);
- if (tile_program_swizzle_aa_)
- tile_program_swizzle_aa_->Cleanup(context_);
- if (tile_checkerboard_program_)
- tile_checkerboard_program_->Cleanup(context_);
-
- if (tile_program_highp_)
- tile_program_highp_->Cleanup(context_);
- if (tile_program_opaque_highp_)
- tile_program_opaque_highp_->Cleanup(context_);
- if (tile_program_swizzle_highp_)
- tile_program_swizzle_highp_->Cleanup(context_);
- if (tile_program_swizzle_opaque_highp_)
- tile_program_swizzle_opaque_highp_->Cleanup(context_);
- if (tile_program_aa_highp_)
- tile_program_aa_highp_->Cleanup(context_);
- if (tile_program_swizzle_aa_highp_)
- tile_program_swizzle_aa_highp_->Cleanup(context_);
-
- if (render_pass_mask_program_)
- render_pass_mask_program_->Cleanup(context_);
- if (render_pass_program_)
- render_pass_program_->Cleanup(context_);
- if (render_pass_mask_program_aa_)
- render_pass_mask_program_aa_->Cleanup(context_);
- if (render_pass_program_aa_)
- render_pass_program_aa_->Cleanup(context_);
- if (render_pass_color_matrix_program_)
- render_pass_color_matrix_program_->Cleanup(context_);
- if (render_pass_mask_color_matrix_program_aa_)
- render_pass_mask_color_matrix_program_aa_->Cleanup(context_);
- if (render_pass_color_matrix_program_aa_)
- render_pass_color_matrix_program_aa_->Cleanup(context_);
- if (render_pass_mask_color_matrix_program_)
- render_pass_mask_color_matrix_program_->Cleanup(context_);
-
- if (render_pass_mask_program_highp_)
- render_pass_mask_program_highp_->Cleanup(context_);
- if (render_pass_program_highp_)
- render_pass_program_highp_->Cleanup(context_);
- if (render_pass_mask_program_aa_highp_)
- render_pass_mask_program_aa_highp_->Cleanup(context_);
- if (render_pass_program_aa_highp_)
- render_pass_program_aa_highp_->Cleanup(context_);
- if (render_pass_color_matrix_program_highp_)
- render_pass_color_matrix_program_highp_->Cleanup(context_);
- if (render_pass_mask_color_matrix_program_aa_highp_)
- render_pass_mask_color_matrix_program_aa_highp_->Cleanup(context_);
- if (render_pass_color_matrix_program_aa_highp_)
- render_pass_color_matrix_program_aa_highp_->Cleanup(context_);
- if (render_pass_mask_color_matrix_program_highp_)
- render_pass_mask_color_matrix_program_highp_->Cleanup(context_);
-
- if (texture_program_)
- texture_program_->Cleanup(context_);
- if (nonpremultiplied_texture_program_)
- nonpremultiplied_texture_program_->Cleanup(context_);
- if (texture_background_program_)
- texture_background_program_->Cleanup(context_);
- if (nonpremultiplied_texture_background_program_)
- nonpremultiplied_texture_background_program_->Cleanup(context_);
- if (texture_io_surface_program_)
- texture_io_surface_program_->Cleanup(context_);
-
- if (texture_program_highp_)
- texture_program_highp_->Cleanup(context_);
- if (nonpremultiplied_texture_program_highp_)
- nonpremultiplied_texture_program_highp_->Cleanup(context_);
- if (texture_background_program_highp_)
- texture_background_program_highp_->Cleanup(context_);
- if (nonpremultiplied_texture_background_program_highp_)
- nonpremultiplied_texture_background_program_highp_->Cleanup(context_);
- if (texture_io_surface_program_highp_)
- texture_io_surface_program_highp_->Cleanup(context_);
-
- if (video_yuv_program_)
- video_yuv_program_->Cleanup(context_);
- if (video_yuva_program_)
- video_yuva_program_->Cleanup(context_);
- if (video_stream_texture_program_)
- video_stream_texture_program_->Cleanup(context_);
-
- if (video_yuv_program_highp_)
- video_yuv_program_highp_->Cleanup(context_);
- if (video_yuva_program_highp_)
- video_yuva_program_highp_->Cleanup(context_);
- if (video_stream_texture_program_highp_)
- video_stream_texture_program_highp_->Cleanup(context_);
-
- if (debug_border_program_)
- debug_border_program_->Cleanup(context_);
- if (solid_color_program_)
- solid_color_program_->Cleanup(context_);
- if (solid_color_program_aa_)
- solid_color_program_aa_->Cleanup(context_);
+ for (int i = 0; i < NumTexCoordPrecisions; ++i) {
+ for (int j = 0; j < NumSamplerTypes; ++j) {
+ tile_program_[i][j].Cleanup(gl_);
+ tile_program_opaque_[i][j].Cleanup(gl_);
+ tile_program_swizzle_[i][j].Cleanup(gl_);
+ tile_program_swizzle_opaque_[i][j].Cleanup(gl_);
+ tile_program_aa_[i][j].Cleanup(gl_);
+ tile_program_swizzle_aa_[i][j].Cleanup(gl_);
+ }
+
+ render_pass_mask_program_[i].Cleanup(gl_);
+ render_pass_program_[i].Cleanup(gl_);
+ render_pass_mask_program_aa_[i].Cleanup(gl_);
+ render_pass_program_aa_[i].Cleanup(gl_);
+ render_pass_color_matrix_program_[i].Cleanup(gl_);
+ render_pass_mask_color_matrix_program_aa_[i].Cleanup(gl_);
+ render_pass_color_matrix_program_aa_[i].Cleanup(gl_);
+ render_pass_mask_color_matrix_program_[i].Cleanup(gl_);
+
+ texture_program_[i].Cleanup(gl_);
+ nonpremultiplied_texture_program_[i].Cleanup(gl_);
+ texture_background_program_[i].Cleanup(gl_);
+ nonpremultiplied_texture_background_program_[i].Cleanup(gl_);
+ texture_io_surface_program_[i].Cleanup(gl_);
+
+ video_yuv_program_[i].Cleanup(gl_);
+ video_yuva_program_[i].Cleanup(gl_);
+ 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_);
if (offscreen_framebuffer_id_)
- GLC(context_, context_->deleteFramebuffer(offscreen_framebuffer_id_));
+ GLC(gl_, gl_->DeleteFramebuffers(1, &offscreen_framebuffer_id_));
if (on_demand_tile_raster_resource_id_)
resource_provider_->DeleteResource(on_demand_tile_raster_resource_id_);
@@ -3088,54 +2987,29 @@ void GLRenderer::CleanupSharedObjects() {
ReleaseRenderPassTextures();
}
-void GLRenderer::ReinitializeGrCanvas() {
- if (!CanUseSkiaGPUBackend())
- return;
-
- GrBackendRenderTargetDesc desc;
- desc.fWidth = client_->DeviceViewport().width();
- desc.fHeight = client_->DeviceViewport().height();
- desc.fConfig = kRGBA_8888_GrPixelConfig;
- desc.fOrigin = kTopLeft_GrSurfaceOrigin;
- desc.fSampleCnt = 1;
- desc.fStencilBits = 8;
- desc.fRenderTargetHandle = 0;
-
- skia::RefPtr<GrSurface> surface(
- skia::AdoptRef(gr_context_->wrapBackendRenderTarget(desc)));
- skia::RefPtr<SkBaseDevice> device(
- skia::AdoptRef(SkGpuDevice::Create(surface.get())));
- sk_canvas_ = skia::AdoptRef(new SkCanvas(device.get()));
-}
-
void GLRenderer::ReinitializeGLState() {
// Bind the common vertex attributes used for drawing all the layers.
shared_geometry_->PrepareForDraw();
- GLC(context_, context_->disable(GL_DEPTH_TEST));
- GLC(context_, context_->disable(GL_CULL_FACE));
- GLC(context_, context_->colorMask(true, true, true, true));
- GLC(context_, context_->disable(GL_STENCIL_TEST));
+ GLC(gl_, gl_->Disable(GL_DEPTH_TEST));
+ GLC(gl_, gl_->Disable(GL_CULL_FACE));
+ GLC(gl_, gl_->ColorMask(true, true, true, true));
+ GLC(gl_, gl_->Disable(GL_STENCIL_TEST));
stencil_shadow_ = false;
- GLC(context_, context_->enable(GL_BLEND));
+ GLC(gl_, gl_->Enable(GL_BLEND));
blend_shadow_ = true;
- GLC(context_, context_->blendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
- GLC(context_, context_->activeTexture(GL_TEXTURE0));
+ GLC(gl_, gl_->BlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
+ GLC(gl_, gl_->ActiveTexture(GL_TEXTURE0));
program_shadow_ = 0;
// Make sure scissoring starts as disabled.
is_scissor_enabled_ = false;
- GLC(context_, context_->disable(GL_SCISSOR_TEST));
-}
-
-bool GLRenderer::CanUseSkiaGPUBackend() const {
- // The Skia GPU backend requires a stencil buffer. See ReinitializeGrCanvas
- // implementation.
- return gr_context_ && context_->getContextAttributes().stencil;
+ GLC(gl_, gl_->Disable(GL_SCISSOR_TEST));
+ scissor_rect_needs_reset_ = true;
}
bool GLRenderer::IsContextLost() {
- return (context_->getGraphicsResetStatusARB() != GL_NO_ERROR);
+ return output_surface_->context_provider()->IsContextLost();
}
} // namespace cc
diff --git a/chromium/cc/output/gl_renderer.h b/chromium/cc/output/gl_renderer.h
index bc47870063d..cf672f0afa4 100644
--- a/chromium/cc/output/gl_renderer.h
+++ b/chromium/cc/output/gl_renderer.h
@@ -23,7 +23,13 @@
class SkBitmap;
-namespace WebKit { class WebGraphicsContext3D; }
+namespace blink { class WebGraphicsContext3D; }
+
+namespace gpu {
+namespace gles2 {
+class GLES2Interface;
+}
+}
namespace cc {
@@ -46,22 +52,19 @@ class CC_EXPORT GLRenderer : public DirectRenderer {
OutputSurface* output_surface,
ResourceProvider* resource_provider,
TextureMailboxDeleter* texture_mailbox_deleter,
- int highp_threshold_min,
- bool use_skia_gpu_backend);
+ int highp_threshold_min);
virtual ~GLRenderer();
virtual const RendererCapabilities& Capabilities() const OVERRIDE;
- WebKit::WebGraphicsContext3D* Context();
-
- virtual void ViewportChanged() OVERRIDE;
+ blink::WebGraphicsContext3D* Context();
// Waits for rendering to finish.
virtual void Finish() OVERRIDE;
virtual void DoNoOp() OVERRIDE;
- virtual void SwapBuffers() OVERRIDE;
+ virtual void SwapBuffers(const CompositorFrameMetadata& metadata) OVERRIDE;
virtual void GetFramebufferPixels(void* pixels, gfx::Rect rect) OVERRIDE;
@@ -73,15 +76,11 @@ class CC_EXPORT GLRenderer : public DirectRenderer {
size_t bytes_visible_and_nearby,
size_t bytes_allocated) OVERRIDE;
- virtual void SetDiscardBackBufferWhenNotVisible(bool discard) OVERRIDE;
-
- static void DebugGLCall(WebKit::WebGraphicsContext3D* context,
+ static void DebugGLCall(gpu::gles2::GLES2Interface* gl,
const char* command,
const char* file,
int line);
- bool CanUseSkiaGPUBackend() const;
-
protected:
GLRenderer(RendererClient* client,
const LayerTreeSettings* settings,
@@ -91,7 +90,6 @@ class CC_EXPORT GLRenderer : public DirectRenderer {
int highp_threshold_min);
bool IsBackbufferDiscarded() const { return is_backbuffer_discarded_; }
- bool Initialize();
void InitializeGrContext();
const gfx::QuadF& SharedGeometryQuad() const { return shared_geometry_quad_; }
@@ -153,11 +151,12 @@ class CC_EXPORT GLRenderer : public DirectRenderer {
const CheckerboardDrawQuad* quad);
void DrawDebugBorderQuad(const DrawingFrame* frame,
const DebugBorderDrawQuad* quad);
- scoped_ptr<ScopedResource> DrawBackgroundFilters(
+ scoped_ptr<ScopedResource> GetBackgroundWithFilters(
DrawingFrame* frame,
const RenderPassDrawQuad* quad,
const gfx::Transform& contents_device_transform,
- const gfx::Transform& contents_device_transformInverse);
+ const gfx::Transform& contents_device_transformInverse,
+ bool* background_changed);
void DrawRenderPassQuad(DrawingFrame* frame, const RenderPassDrawQuad* quad);
void DrawSolidColorQuad(const DrawingFrame* frame,
const SolidColorDrawQuad* quad);
@@ -176,8 +175,6 @@ class CC_EXPORT GLRenderer : public DirectRenderer {
const YUVVideoDrawQuad* quad);
void DrawPictureQuad(const DrawingFrame* frame,
const PictureDrawQuad* quad);
- void DrawPictureQuadDirectToBackbuffer(const DrawingFrame* frame,
- const PictureDrawQuad* quad);
void SetShaderOpacity(float opacity, int alpha_location);
void SetShaderQuadF(const gfx::QuadF& quad, int quad_location);
@@ -199,7 +196,7 @@ class CC_EXPORT GLRenderer : public DirectRenderer {
bool MakeContextCurrent();
- bool InitializeSharedObjects();
+ void InitializeSharedObjects();
void CleanupSharedObjects();
typedef base::Callback<void(scoped_ptr<CopyOutputRequest> copy_request,
@@ -220,7 +217,6 @@ class CC_EXPORT GLRenderer : public DirectRenderer {
scoped_ptr<CopyOutputRequest> request,
bool success);
- void ReinitializeGrCanvas();
void ReinitializeGLState();
virtual void DiscardBackbuffer() OVERRIDE;
@@ -266,9 +262,6 @@ class CC_EXPORT GLRenderer : public DirectRenderer {
typedef ProgramBinding<VertexShaderPosTexTransform,
FragmentShaderTexBackgroundPremultiplyAlpha>
NonPremultipliedTextureBackgroundProgram;
- typedef ProgramBinding<VertexShaderPosTexTransform,
- FragmentShaderRGBATexRectVaryingAlpha>
- TextureIOSurfaceProgram;
// Render surface shaders.
typedef ProgramBinding<VertexShaderPosTexTransform,
@@ -294,8 +287,7 @@ class CC_EXPORT GLRenderer : public DirectRenderer {
RenderPassMaskColorMatrixProgram;
// Video shaders.
- typedef ProgramBinding<VertexShaderVideoTransform,
- FragmentShaderOESImageExternal>
+ typedef ProgramBinding<VertexShaderVideoTransform, FragmentShaderRGBATex>
VideoStreamTextureProgram;
typedef ProgramBinding<VertexShaderPosTexYUVStretch, FragmentShaderYUVVideo>
VideoYUVProgram;
@@ -310,14 +302,19 @@ class CC_EXPORT GLRenderer : public DirectRenderer {
typedef ProgramBinding<VertexShaderQuadAA, FragmentShaderColorAA>
SolidColorProgramAA;
- const TileProgram* GetTileProgram(TexCoordPrecision precision);
- const TileProgramOpaque* GetTileProgramOpaque(TexCoordPrecision precision);
- const TileProgramAA* GetTileProgramAA(TexCoordPrecision precision);
- const TileProgramSwizzle* GetTileProgramSwizzle(TexCoordPrecision precision);
+ const TileProgram* GetTileProgram(
+ TexCoordPrecision precision, SamplerType sampler);
+ const TileProgramOpaque* GetTileProgramOpaque(
+ TexCoordPrecision precision, SamplerType sampler);
+ const TileProgramAA* GetTileProgramAA(
+ TexCoordPrecision precision, SamplerType sampler);
+ const TileProgramSwizzle* GetTileProgramSwizzle(
+ TexCoordPrecision precision, SamplerType sampler);
const TileProgramSwizzleOpaque* GetTileProgramSwizzleOpaque(
- TexCoordPrecision precision);
+ TexCoordPrecision precision, SamplerType sampler);
const TileProgramSwizzleAA* GetTileProgramSwizzleAA(
- TexCoordPrecision precision);
+ TexCoordPrecision precision, SamplerType sampler);
+
const TileCheckerboardProgram* GetTileCheckerboardProgram();
const RenderPassProgram* GetRenderPassProgram(
@@ -345,7 +342,7 @@ class CC_EXPORT GLRenderer : public DirectRenderer {
TexCoordPrecision precision);
const NonPremultipliedTextureBackgroundProgram*
GetNonPremultipliedTextureBackgroundProgram(TexCoordPrecision precision);
- const TextureIOSurfaceProgram* GetTextureIOSurfaceProgram(
+ const TextureProgram* GetTextureIOSurfaceProgram(
TexCoordPrecision precision);
const VideoYUVProgram* GetVideoYUVProgram(
@@ -359,74 +356,52 @@ class CC_EXPORT GLRenderer : public DirectRenderer {
const SolidColorProgram* GetSolidColorProgram();
const SolidColorProgramAA* GetSolidColorProgramAA();
- scoped_ptr<TileProgram> tile_program_;
- scoped_ptr<TileProgramOpaque> tile_program_opaque_;
- scoped_ptr<TileProgramAA> tile_program_aa_;
- scoped_ptr<TileProgramSwizzle> tile_program_swizzle_;
- scoped_ptr<TileProgramSwizzleOpaque> tile_program_swizzle_opaque_;
- scoped_ptr<TileProgramSwizzleAA> tile_program_swizzle_aa_;
- scoped_ptr<TileCheckerboardProgram> tile_checkerboard_program_;
-
- scoped_ptr<TileProgram> tile_program_highp_;
- scoped_ptr<TileProgramOpaque> tile_program_opaque_highp_;
- scoped_ptr<TileProgramAA> tile_program_aa_highp_;
- scoped_ptr<TileProgramSwizzle> tile_program_swizzle_highp_;
- scoped_ptr<TileProgramSwizzleOpaque> tile_program_swizzle_opaque_highp_;
- scoped_ptr<TileProgramSwizzleAA> tile_program_swizzle_aa_highp_;
-
- scoped_ptr<TextureProgram> texture_program_;
- scoped_ptr<NonPremultipliedTextureProgram> nonpremultiplied_texture_program_;
- scoped_ptr<TextureBackgroundProgram> texture_background_program_;
- scoped_ptr<NonPremultipliedTextureBackgroundProgram>
- nonpremultiplied_texture_background_program_;
- scoped_ptr<TextureIOSurfaceProgram> texture_io_surface_program_;
-
- scoped_ptr<TextureProgram> texture_program_highp_;
- scoped_ptr<NonPremultipliedTextureProgram>
- nonpremultiplied_texture_program_highp_;
- scoped_ptr<TextureBackgroundProgram> texture_background_program_highp_;
- scoped_ptr<NonPremultipliedTextureBackgroundProgram>
- nonpremultiplied_texture_background_program_highp_;
- scoped_ptr<TextureIOSurfaceProgram> texture_io_surface_program_highp_;
-
- scoped_ptr<RenderPassProgram> render_pass_program_;
- scoped_ptr<RenderPassProgramAA> render_pass_program_aa_;
- scoped_ptr<RenderPassMaskProgram> render_pass_mask_program_;
- scoped_ptr<RenderPassMaskProgramAA> render_pass_mask_program_aa_;
- scoped_ptr<RenderPassColorMatrixProgram> render_pass_color_matrix_program_;
- scoped_ptr<RenderPassColorMatrixProgramAA>
- render_pass_color_matrix_program_aa_;
- scoped_ptr<RenderPassMaskColorMatrixProgram>
- render_pass_mask_color_matrix_program_;
- scoped_ptr<RenderPassMaskColorMatrixProgramAA>
- render_pass_mask_color_matrix_program_aa_;
-
- scoped_ptr<RenderPassProgram> render_pass_program_highp_;
- scoped_ptr<RenderPassProgramAA> render_pass_program_aa_highp_;
- scoped_ptr<RenderPassMaskProgram> render_pass_mask_program_highp_;
- scoped_ptr<RenderPassMaskProgramAA> render_pass_mask_program_aa_highp_;
- scoped_ptr<RenderPassColorMatrixProgram>
- render_pass_color_matrix_program_highp_;
- scoped_ptr<RenderPassColorMatrixProgramAA>
- render_pass_color_matrix_program_aa_highp_;
- scoped_ptr<RenderPassMaskColorMatrixProgram>
- render_pass_mask_color_matrix_program_highp_;
- scoped_ptr<RenderPassMaskColorMatrixProgramAA>
- render_pass_mask_color_matrix_program_aa_highp_;
-
- scoped_ptr<VideoYUVProgram> video_yuv_program_;
- scoped_ptr<VideoYUVAProgram> video_yuva_program_;
- scoped_ptr<VideoStreamTextureProgram> video_stream_texture_program_;
-
- scoped_ptr<VideoYUVProgram> video_yuv_program_highp_;
- scoped_ptr<VideoYUVAProgram> video_yuva_program_highp_;
- scoped_ptr<VideoStreamTextureProgram> video_stream_texture_program_highp_;
-
- scoped_ptr<DebugBorderProgram> debug_border_program_;
- scoped_ptr<SolidColorProgram> solid_color_program_;
- scoped_ptr<SolidColorProgramAA> solid_color_program_aa_;
-
- WebKit::WebGraphicsContext3D* context_;
+ TileProgram tile_program_[NumTexCoordPrecisions][NumSamplerTypes];
+ TileProgramOpaque
+ tile_program_opaque_[NumTexCoordPrecisions][NumSamplerTypes];
+ TileProgramAA tile_program_aa_[NumTexCoordPrecisions][NumSamplerTypes];
+ TileProgramSwizzle
+ tile_program_swizzle_[NumTexCoordPrecisions][NumSamplerTypes];
+ TileProgramSwizzleOpaque
+ tile_program_swizzle_opaque_[NumTexCoordPrecisions][NumSamplerTypes];
+ TileProgramSwizzleAA
+ tile_program_swizzle_aa_[NumTexCoordPrecisions][NumSamplerTypes];
+
+ TileCheckerboardProgram tile_checkerboard_program_;
+
+ TextureProgram texture_program_[NumTexCoordPrecisions];
+ NonPremultipliedTextureProgram
+ nonpremultiplied_texture_program_[NumTexCoordPrecisions];
+ TextureBackgroundProgram texture_background_program_[NumTexCoordPrecisions];
+ NonPremultipliedTextureBackgroundProgram
+ nonpremultiplied_texture_background_program_[NumTexCoordPrecisions];
+ TextureProgram texture_io_surface_program_[NumTexCoordPrecisions];
+
+ RenderPassProgram render_pass_program_[NumTexCoordPrecisions];
+ RenderPassProgramAA render_pass_program_aa_[NumTexCoordPrecisions];
+ RenderPassMaskProgram render_pass_mask_program_[NumTexCoordPrecisions];
+ RenderPassMaskProgramAA render_pass_mask_program_aa_[NumTexCoordPrecisions];
+ RenderPassColorMatrixProgram
+ render_pass_color_matrix_program_[NumTexCoordPrecisions];
+ RenderPassColorMatrixProgramAA
+ render_pass_color_matrix_program_aa_[NumTexCoordPrecisions];
+ RenderPassMaskColorMatrixProgram
+ render_pass_mask_color_matrix_program_[NumTexCoordPrecisions];
+ RenderPassMaskColorMatrixProgramAA
+ render_pass_mask_color_matrix_program_aa_[NumTexCoordPrecisions];
+
+ VideoYUVProgram video_yuv_program_[NumTexCoordPrecisions];
+ VideoYUVAProgram video_yuva_program_[NumTexCoordPrecisions];
+ VideoStreamTextureProgram
+ video_stream_texture_program_[NumTexCoordPrecisions];
+
+ DebugBorderProgram debug_border_program_;
+ SolidColorProgram solid_color_program_;
+ SolidColorProgramAA solid_color_program_aa_;
+
+ blink::WebGraphicsContext3D* context_;
+ gpu::gles2::GLES2Interface* gl_;
+ gpu::ContextSupport* context_support_;
skia::RefPtr<GrContext> gr_context_;
skia::RefPtr<SkCanvas> sk_canvas_;
@@ -437,10 +412,10 @@ class CC_EXPORT GLRenderer : public DirectRenderer {
gfx::Rect scissor_rect_;
gfx::Rect viewport_;
bool is_backbuffer_discarded_;
- bool discard_backbuffer_when_not_visible_;
bool is_using_bind_uniform_;
bool visible_;
bool is_scissor_enabled_;
+ bool scissor_rect_needs_reset_;
bool stencil_shadow_;
bool blend_shadow_;
unsigned program_shadow_;
diff --git a/chromium/cc/output/gl_renderer_unittest.cc b/chromium/cc/output/gl_renderer_unittest.cc
index 836287f4448..f165e153bf0 100644
--- a/chromium/cc/output/gl_renderer_unittest.cc
+++ b/chromium/cc/output/gl_renderer_unittest.cc
@@ -7,11 +7,9 @@
#include <set>
#include "cc/base/math_util.h"
-#include "cc/debug/test_web_graphics_context_3d.h"
#include "cc/output/compositor_frame_metadata.h"
#include "cc/resources/prioritized_resource_manager.h"
#include "cc/resources/resource_provider.h"
-#include "cc/resources/sync_point_helper.h"
#include "cc/test/fake_impl_proxy.h"
#include "cc/test/fake_layer_tree_host_impl.h"
#include "cc/test/fake_output_surface.h"
@@ -20,7 +18,9 @@
#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_web_graphics_context_3d.h"
#include "gpu/GLES2/gl2extchromium.h"
+#include "gpu/command_buffer/client/context_support.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/khronos/GLES2/gl2.h"
@@ -40,25 +40,32 @@ using testing::InSequence;
using testing::Mock;
using testing::Return;
using testing::StrictMock;
-using WebKit::WebGLId;
-using WebKit::WebString;
-using WebKit::WGC3Dbitfield;
-using WebKit::WGC3Dboolean;
-using WebKit::WGC3Dchar;
-using WebKit::WGC3Denum;
-using WebKit::WGC3Dfloat;
-using WebKit::WGC3Dint;
-using WebKit::WGC3Dintptr;
-using WebKit::WGC3Dsizei;
-using WebKit::WGC3Dsizeiptr;
-using WebKit::WGC3Duint;
+using blink::WebGLId;
+using blink::WebString;
+using blink::WGC3Dbitfield;
+using blink::WGC3Dboolean;
+using blink::WGC3Dchar;
+using blink::WGC3Denum;
+using blink::WGC3Dfloat;
+using blink::WGC3Dint;
+using blink::WGC3Dintptr;
+using blink::WGC3Dsizei;
+using blink::WGC3Dsizeiptr;
+using blink::WGC3Duint;
namespace cc {
-#define EXPECT_PROGRAM_VALID(program_binding) \
- do { \
- EXPECT_TRUE(program_binding->program()); \
- EXPECT_TRUE(program_binding->initialized()); \
+class GLRendererTest : public testing::Test {
+ protected:
+ RenderPass* root_render_pass() { return render_passes_in_draw_order_.back(); }
+
+ RenderPassList render_passes_in_draw_order_;
+};
+
+#define EXPECT_PROGRAM_VALID(program_binding) \
+ do { \
+ EXPECT_TRUE((program_binding)->program()); \
+ EXPECT_TRUE((program_binding)->initialized()); \
} while (false)
// Explicitly named to be a friend in GLRenderer for shader access.
@@ -76,12 +83,6 @@ class GLRendererShaderPixelTest : public GLRendererPixelTest {
}
void TestShadersWithTexCoordPrecision(TexCoordPrecision precision) {
- EXPECT_PROGRAM_VALID(renderer()->GetTileProgram(precision));
- EXPECT_PROGRAM_VALID(renderer()->GetTileProgramOpaque(precision));
- EXPECT_PROGRAM_VALID(renderer()->GetTileProgramAA(precision));
- EXPECT_PROGRAM_VALID(renderer()->GetTileProgramSwizzle(precision));
- EXPECT_PROGRAM_VALID(renderer()->GetTileProgramSwizzleOpaque(precision));
- EXPECT_PROGRAM_VALID(renderer()->GetTileProgramSwizzleAA(precision));
EXPECT_PROGRAM_VALID(renderer()->GetRenderPassProgram(precision));
EXPECT_PROGRAM_VALID(renderer()->GetRenderPassProgramAA(precision));
EXPECT_PROGRAM_VALID(renderer()->GetRenderPassMaskProgram(precision));
@@ -108,6 +109,23 @@ class GLRendererShaderPixelTest : public GLRendererPixelTest {
EXPECT_PROGRAM_VALID(renderer()->GetVideoStreamTextureProgram(precision));
else
EXPECT_FALSE(renderer()->GetVideoStreamTextureProgram(precision));
+ TestShadersWithSamplerType(precision, SamplerType2D);
+ TestShadersWithSamplerType(precision, SamplerType2DRect);
+ // This is unlikely to be ever true in tests due to usage of osmesa.
+ if (renderer()->Capabilities().using_egl_image)
+ TestShadersWithSamplerType(precision, SamplerTypeExternalOES);
+ }
+
+ void TestShadersWithSamplerType(TexCoordPrecision precision,
+ SamplerType sampler) {
+ EXPECT_PROGRAM_VALID(renderer()->GetTileProgram(precision, sampler));
+ EXPECT_PROGRAM_VALID(renderer()->GetTileProgramOpaque(precision, sampler));
+ EXPECT_PROGRAM_VALID(renderer()->GetTileProgramAA(precision, sampler));
+ EXPECT_PROGRAM_VALID(renderer()->GetTileProgramSwizzle(precision, sampler));
+ EXPECT_PROGRAM_VALID(
+ renderer()->GetTileProgramSwizzleOpaque(precision, sampler));
+ EXPECT_PROGRAM_VALID(
+ renderer()->GetTileProgramSwizzleAA(precision, sampler));
}
};
@@ -117,73 +135,22 @@ namespace {
TEST_F(GLRendererShaderPixelTest, AllShadersCompile) { TestShaders(); }
#endif
-class FrameCountingContext : public TestWebGraphicsContext3D {
- public:
- FrameCountingContext()
- : frame_(0) {
- test_capabilities_.set_visibility = true;
- test_capabilities_.discard_backbuffer = true;
- }
-
- // WebGraphicsContext3D methods.
-
- // This method would normally do a glSwapBuffers under the hood.
- virtual void prepareTexture() { frame_++; }
-
- // Methods added for test.
- int frame_count() { return frame_; }
-
- private:
- int frame_;
-};
-
class FakeRendererClient : public RendererClient {
public:
- FakeRendererClient()
- : host_impl_(&proxy_),
- set_full_root_layer_damage_count_(0),
- root_layer_(LayerImpl::Create(host_impl_.active_tree(), 1)),
- viewport_(gfx::Rect(0, 0, 1, 1)),
- clip_(gfx::Rect(0, 0, 1, 1)) {
- root_layer_->CreateRenderSurface();
- RenderPass::Id render_pass_id =
- root_layer_->render_surface()->RenderPassId();
- scoped_ptr<RenderPass> root_render_pass = RenderPass::Create();
- root_render_pass->SetNew(
- render_pass_id, gfx::Rect(), gfx::Rect(), gfx::Transform());
- render_passes_in_draw_order_.push_back(root_render_pass.Pass());
- }
+ FakeRendererClient() : set_full_root_layer_damage_count_(0) {}
// RendererClient methods.
- virtual gfx::Rect DeviceViewport() const OVERRIDE { return viewport_; }
- virtual gfx::Rect DeviceClip() const OVERRIDE { return clip_; }
virtual void SetFullRootLayerDamage() OVERRIDE {
set_full_root_layer_damage_count_++;
}
- virtual CompositorFrameMetadata MakeCompositorFrameMetadata() const OVERRIDE {
- return CompositorFrameMetadata();
- }
// Methods added for test.
int set_full_root_layer_damage_count() const {
return set_full_root_layer_damage_count_;
}
- void set_viewport(gfx::Rect viewport) { viewport_ = viewport; }
- void set_clip(gfx::Rect clip) { clip_ = clip; }
-
- RenderPass* root_render_pass() { return render_passes_in_draw_order_.back(); }
- RenderPassList* render_passes_in_draw_order() {
- return &render_passes_in_draw_order_;
- }
private:
- FakeImplProxy proxy_;
- FakeLayerTreeHostImpl host_impl_;
int set_full_root_layer_damage_count_;
- scoped_ptr<LayerImpl> root_layer_;
- RenderPassList render_passes_in_draw_order_;
- gfx::Rect viewport_;
- gfx::Rect clip_;
};
class FakeRendererGL : public GLRenderer {
@@ -202,7 +169,6 @@ class FakeRendererGL : public GLRenderer {
// GLRenderer methods.
// Changing visibility to public.
- using GLRenderer::Initialize;
using GLRenderer::IsBackbufferDiscarded;
using GLRenderer::DoDrawQuad;
using GLRenderer::BeginDrawingFrame;
@@ -210,30 +176,24 @@ class FakeRendererGL : public GLRenderer {
using GLRenderer::stencil_enabled;
};
-class GLRendererTest : public testing::Test {
+class GLRendererWithDefaultHarnessTest : public GLRendererTest {
protected:
- GLRendererTest() {
- scoped_ptr<FrameCountingContext> context3d(new FrameCountingContext);
- context3d_ = context3d.get();
-
+ GLRendererWithDefaultHarnessTest() {
output_surface_ = FakeOutputSurface::Create3d(
- context3d.PassAs<TestWebGraphicsContext3D>()).Pass();
+ TestWebGraphicsContext3D::Create()).Pass();
CHECK(output_surface_->BindToClient(&output_surface_client_));
- resource_provider_ =
- ResourceProvider::Create(output_surface_.get(), 0, false).Pass();
+ resource_provider_ = ResourceProvider::Create(
+ output_surface_.get(), NULL, 0, false, 1).Pass();
renderer_ = make_scoped_ptr(new FakeRendererGL(&renderer_client_,
&settings_,
output_surface_.get(),
resource_provider_.get()));
}
- virtual void SetUp() { renderer_->Initialize(); }
-
- void SwapBuffers() { renderer_->SwapBuffers(); }
+ void SwapBuffers() { renderer_->SwapBuffers(CompositorFrameMetadata()); }
LayerTreeSettings settings_;
- FrameCountingContext* context3d_;
FakeOutputSurfaceClient output_surface_client_;
scoped_ptr<FakeOutputSurface> output_surface_;
FakeRendererClient renderer_client_;
@@ -246,132 +206,78 @@ class GLRendererTest : public testing::Test {
// declared above it.
} // namespace
-
-// Gives unique shader ids and unique program ids for tests that need them.
-class ShaderCreatorMockGraphicsContext : public TestWebGraphicsContext3D {
- public:
- ShaderCreatorMockGraphicsContext()
- : next_program_id_number_(10000),
- next_shader_id_number_(1) {}
-
- bool hasShader(WebGLId shader) {
- return shader_set_.find(shader) != shader_set_.end();
- }
-
- bool hasProgram(WebGLId program) {
- return program_set_.find(program) != program_set_.end();
- }
-
- virtual WebGLId createProgram() {
- unsigned program = next_program_id_number_;
- program_set_.insert(program);
- next_program_id_number_++;
- return program;
- }
-
- virtual void deleteProgram(WebGLId program) {
- ASSERT_TRUE(hasProgram(program));
- program_set_.erase(program);
- }
-
- virtual void useProgram(WebGLId program) {
- if (!program)
- return;
- ASSERT_TRUE(hasProgram(program));
- }
-
- virtual WebKit::WebGLId createShader(WebKit::WGC3Denum) {
- unsigned shader = next_shader_id_number_;
- shader_set_.insert(shader);
- next_shader_id_number_++;
- return shader;
- }
-
- virtual void deleteShader(WebKit::WebGLId shader) {
- ASSERT_TRUE(hasShader(shader));
- shader_set_.erase(shader);
- }
-
- virtual void attachShader(WebGLId program, WebGLId shader) {
- ASSERT_TRUE(hasProgram(program));
- ASSERT_TRUE(hasShader(shader));
- }
-
- protected:
- unsigned next_program_id_number_;
- unsigned next_shader_id_number_;
- std::set<unsigned> program_set_;
- std::set<unsigned> shader_set_;
-};
-
-class GLRendererShaderTest : public testing::Test {
+class GLRendererShaderTest : public GLRendererTest {
protected:
GLRendererShaderTest() {
- output_surface_ = FakeOutputSurface::Create3d(
- scoped_ptr<TestWebGraphicsContext3D>(
- new ShaderCreatorMockGraphicsContext())).Pass();
+ output_surface_ = FakeOutputSurface::Create3d().Pass();
CHECK(output_surface_->BindToClient(&output_surface_client_));
resource_provider_ = ResourceProvider::Create(
- output_surface_.get(), 0, false).Pass();
+ output_surface_.get(), NULL, 0, false, 1).Pass();
renderer_.reset(new FakeRendererGL(&renderer_client_,
&settings_,
output_surface_.get(),
resource_provider_.get()));
- renderer_->Initialize();
}
- void TestRenderPassProgram() {
- EXPECT_PROGRAM_VALID(renderer_->render_pass_program_);
- EXPECT_EQ(renderer_->render_pass_program_->program(),
+ void TestRenderPassProgram(TexCoordPrecision precision) {
+ EXPECT_PROGRAM_VALID(&renderer_->render_pass_program_[precision]);
+ EXPECT_EQ(renderer_->render_pass_program_[precision].program(),
renderer_->program_shadow_);
}
- void TestRenderPassColorMatrixProgram() {
- EXPECT_PROGRAM_VALID(renderer_->render_pass_color_matrix_program_);
- EXPECT_EQ(renderer_->render_pass_color_matrix_program_->program(),
+ void TestRenderPassColorMatrixProgram(TexCoordPrecision precision) {
+ EXPECT_PROGRAM_VALID(
+ &renderer_->render_pass_color_matrix_program_[precision]);
+ EXPECT_EQ(renderer_->render_pass_color_matrix_program_[precision].program(),
renderer_->program_shadow_);
}
- void TestRenderPassMaskProgram() {
- EXPECT_PROGRAM_VALID(renderer_->render_pass_mask_program_);
- EXPECT_EQ(renderer_->render_pass_mask_program_->program(),
+ void TestRenderPassMaskProgram(TexCoordPrecision precision) {
+ EXPECT_PROGRAM_VALID(&renderer_->render_pass_mask_program_[precision]);
+ EXPECT_EQ(renderer_->render_pass_mask_program_[precision].program(),
renderer_->program_shadow_);
}
- void TestRenderPassMaskColorMatrixProgram() {
- EXPECT_PROGRAM_VALID(renderer_->render_pass_mask_color_matrix_program_);
- EXPECT_EQ(renderer_->render_pass_mask_color_matrix_program_->program(),
- renderer_->program_shadow_);
+ void TestRenderPassMaskColorMatrixProgram(TexCoordPrecision precision) {
+ EXPECT_PROGRAM_VALID(
+ &renderer_->render_pass_mask_color_matrix_program_[precision]);
+ EXPECT_EQ(
+ renderer_->render_pass_mask_color_matrix_program_[precision].program(),
+ renderer_->program_shadow_);
}
- void TestRenderPassProgramAA() {
- EXPECT_PROGRAM_VALID(renderer_->render_pass_program_aa_);
- EXPECT_EQ(renderer_->render_pass_program_aa_->program(),
+ void TestRenderPassProgramAA(TexCoordPrecision precision) {
+ EXPECT_PROGRAM_VALID(&renderer_->render_pass_program_aa_[precision]);
+ EXPECT_EQ(renderer_->render_pass_program_aa_[precision].program(),
renderer_->program_shadow_);
}
- void TestRenderPassColorMatrixProgramAA() {
- EXPECT_PROGRAM_VALID(renderer_->render_pass_color_matrix_program_aa_);
- EXPECT_EQ(renderer_->render_pass_color_matrix_program_aa_->program(),
- renderer_->program_shadow_);
+ void TestRenderPassColorMatrixProgramAA(TexCoordPrecision precision) {
+ EXPECT_PROGRAM_VALID(
+ &renderer_->render_pass_color_matrix_program_aa_[precision]);
+ EXPECT_EQ(
+ renderer_->render_pass_color_matrix_program_aa_[precision].program(),
+ renderer_->program_shadow_);
}
- void TestRenderPassMaskProgramAA() {
- EXPECT_PROGRAM_VALID(renderer_->render_pass_mask_program_aa_);
- EXPECT_EQ(renderer_->render_pass_mask_program_aa_->program(),
+ void TestRenderPassMaskProgramAA(TexCoordPrecision precision) {
+ EXPECT_PROGRAM_VALID(&renderer_->render_pass_mask_program_aa_[precision]);
+ EXPECT_EQ(renderer_->render_pass_mask_program_aa_[precision].program(),
renderer_->program_shadow_);
}
- void TestRenderPassMaskColorMatrixProgramAA() {
- EXPECT_PROGRAM_VALID(renderer_->render_pass_mask_color_matrix_program_aa_);
- EXPECT_EQ(renderer_->render_pass_mask_color_matrix_program_aa_->program(),
+ void TestRenderPassMaskColorMatrixProgramAA(TexCoordPrecision precision) {
+ EXPECT_PROGRAM_VALID(
+ &renderer_->render_pass_mask_color_matrix_program_aa_[precision]);
+ EXPECT_EQ(renderer_->render_pass_mask_color_matrix_program_aa_[precision]
+ .program(),
renderer_->program_shadow_);
}
void TestSolidColorProgramAA() {
- EXPECT_PROGRAM_VALID(renderer_->solid_color_program_aa_);
- EXPECT_EQ(renderer_->solid_color_program_aa_->program(),
+ EXPECT_PROGRAM_VALID(&renderer_->solid_color_program_aa_);
+ EXPECT_EQ(renderer_->solid_color_program_aa_.program(),
renderer_->program_shadow_);
}
@@ -385,27 +291,14 @@ class GLRendererShaderTest : public testing::Test {
namespace {
-// Test GLRenderer discardBackbuffer functionality:
-// Suggest recreating framebuffer when one already exists.
-// Expected: it does nothing.
-TEST_F(GLRendererTest, SuggestBackbufferYesWhenItAlreadyExistsShouldDoNothing) {
- renderer_->SetDiscardBackBufferWhenNotVisible(false);
- EXPECT_EQ(0, renderer_client_.set_full_root_layer_damage_count());
- EXPECT_FALSE(renderer_->IsBackbufferDiscarded());
-
- SwapBuffers();
- EXPECT_EQ(1, context3d_->frame_count());
-}
-
// Test GLRenderer DiscardBackbuffer functionality:
// Suggest discarding framebuffer when one exists and the renderer is not
// visible.
// Expected: it is discarded and damage tracker is reset.
TEST_F(
- GLRendererTest,
+ GLRendererWithDefaultHarnessTest,
SuggestBackbufferNoShouldDiscardBackbufferAndDamageRootLayerIfNotVisible) {
renderer_->SetVisible(false);
- renderer_->SetDiscardBackBufferWhenNotVisible(true);
EXPECT_EQ(1, renderer_client_.set_full_root_layer_damage_count());
EXPECT_TRUE(renderer_->IsBackbufferDiscarded());
}
@@ -413,9 +306,9 @@ TEST_F(
// Test GLRenderer DiscardBackbuffer functionality:
// Suggest discarding framebuffer when one exists and the renderer is visible.
// Expected: the allocation is ignored.
-TEST_F(GLRendererTest, SuggestBackbufferNoDoNothingWhenVisible) {
+TEST_F(GLRendererWithDefaultHarnessTest,
+ SuggestBackbufferNoDoNothingWhenVisible) {
renderer_->SetVisible(true);
- renderer_->SetDiscardBackBufferWhenNotVisible(true);
EXPECT_EQ(0, renderer_client_.set_full_root_layer_damage_count());
EXPECT_FALSE(renderer_->IsBackbufferDiscarded());
}
@@ -423,13 +316,12 @@ TEST_F(GLRendererTest, SuggestBackbufferNoDoNothingWhenVisible) {
// Test GLRenderer DiscardBackbuffer functionality:
// Suggest discarding framebuffer when one does not exist.
// Expected: it does nothing.
-TEST_F(GLRendererTest, SuggestBackbufferNoWhenItDoesntExistShouldDoNothing) {
+TEST_F(GLRendererWithDefaultHarnessTest,
+ SuggestBackbufferNoWhenItDoesntExistShouldDoNothing) {
renderer_->SetVisible(false);
- renderer_->SetDiscardBackBufferWhenNotVisible(true);
EXPECT_EQ(1, renderer_client_.set_full_root_layer_damage_count());
EXPECT_TRUE(renderer_->IsBackbufferDiscarded());
- renderer_->SetDiscardBackBufferWhenNotVisible(true);
EXPECT_EQ(1, renderer_client_.set_full_root_layer_damage_count());
EXPECT_TRUE(renderer_->IsBackbufferDiscarded());
}
@@ -437,30 +329,52 @@ TEST_F(GLRendererTest, SuggestBackbufferNoWhenItDoesntExistShouldDoNothing) {
// Test GLRenderer DiscardBackbuffer functionality:
// Begin drawing a frame while a framebuffer is discarded.
// Expected: will recreate framebuffer.
-TEST_F(GLRendererTest, DiscardedBackbufferIsRecreatedForScopeDuration) {
+TEST_F(GLRendererWithDefaultHarnessTest,
+ DiscardedBackbufferIsRecreatedForScopeDuration) {
+ gfx::Rect viewport_rect(1, 1);
renderer_->SetVisible(false);
- renderer_->SetDiscardBackBufferWhenNotVisible(true);
EXPECT_TRUE(renderer_->IsBackbufferDiscarded());
EXPECT_EQ(1, renderer_client_.set_full_root_layer_damage_count());
+ AddRenderPass(&render_passes_in_draw_order_,
+ RenderPass::Id(1, 0),
+ viewport_rect,
+ gfx::Transform());
+
renderer_->SetVisible(true);
- renderer_->DrawFrame(
- renderer_client_.render_passes_in_draw_order(), NULL, 1.f, true);
+ renderer_->DrawFrame(&render_passes_in_draw_order_,
+ NULL,
+ 1.f,
+ viewport_rect,
+ viewport_rect,
+ true,
+ false);
EXPECT_FALSE(renderer_->IsBackbufferDiscarded());
SwapBuffers();
- EXPECT_EQ(1, context3d_->frame_count());
+ EXPECT_EQ(1u, output_surface_->num_sent_frames());
}
-TEST_F(GLRendererTest, FramebufferDiscardedAfterReadbackWhenNotVisible) {
+TEST_F(GLRendererWithDefaultHarnessTest,
+ FramebufferDiscardedAfterReadbackWhenNotVisible) {
+ gfx::Rect viewport_rect(1, 1);
renderer_->SetVisible(false);
- renderer_->SetDiscardBackBufferWhenNotVisible(true);
EXPECT_TRUE(renderer_->IsBackbufferDiscarded());
EXPECT_EQ(1, renderer_client_.set_full_root_layer_damage_count());
+ AddRenderPass(&render_passes_in_draw_order_,
+ RenderPass::Id(1, 0),
+ viewport_rect,
+ gfx::Transform());
+
char pixels[4];
- renderer_->DrawFrame(
- renderer_client_.render_passes_in_draw_order(), NULL, 1.f, true);
+ renderer_->DrawFrame(&render_passes_in_draw_order_,
+ NULL,
+ 1.f,
+ viewport_rect,
+ viewport_rect,
+ true,
+ false);
EXPECT_FALSE(renderer_->IsBackbufferDiscarded());
renderer_->GetFramebufferPixels(pixels, gfx::Rect(0, 0, 1, 1));
@@ -468,14 +382,25 @@ TEST_F(GLRendererTest, FramebufferDiscardedAfterReadbackWhenNotVisible) {
EXPECT_EQ(2, renderer_client_.set_full_root_layer_damage_count());
}
-TEST_F(GLRendererTest, ExternalStencil) {
+TEST_F(GLRendererWithDefaultHarnessTest, ExternalStencil) {
+ gfx::Rect viewport_rect(1, 1);
EXPECT_FALSE(renderer_->stencil_enabled());
output_surface_->set_has_external_stencil_test(true);
- renderer_client_.root_render_pass()->has_transparent_background = false;
- renderer_->DrawFrame(
- renderer_client_.render_passes_in_draw_order(), NULL, 1.f, true);
+ TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
+ RenderPass::Id(1, 0),
+ viewport_rect,
+ gfx::Transform());
+ root_pass->has_transparent_background = false;
+
+ renderer_->DrawFrame(&render_passes_in_draw_order_,
+ NULL,
+ 1.f,
+ viewport_rect,
+ viewport_rect,
+ true,
+ false);
EXPECT_TRUE(renderer_->stencil_enabled());
}
@@ -625,16 +550,14 @@ class ForbidSynchronousCallContext : public TestWebGraphicsContext3D {
}
};
-// This test isn't using the same fixture as GLRendererTest, and you can't mix
-// TEST() and TEST_F() with the same name, Hence LRC2.
-TEST(GLRendererTest2, InitializationDoesNotMakeSynchronousCalls) {
+TEST_F(GLRendererTest, InitializationDoesNotMakeSynchronousCalls) {
FakeOutputSurfaceClient output_surface_client;
scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
scoped_ptr<TestWebGraphicsContext3D>(new ForbidSynchronousCallContext)));
CHECK(output_surface->BindToClient(&output_surface_client));
scoped_ptr<ResourceProvider> resource_provider(
- ResourceProvider::Create(output_surface.get(), 0, false));
+ ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
LayerTreeSettings settings;
FakeRendererClient renderer_client;
@@ -642,44 +565,35 @@ TEST(GLRendererTest2, InitializationDoesNotMakeSynchronousCalls) {
&settings,
output_surface.get(),
resource_provider.get());
-
- EXPECT_TRUE(renderer.Initialize());
}
class LoseContextOnFirstGetContext : public TestWebGraphicsContext3D {
public:
- LoseContextOnFirstGetContext() : context_lost_(false) {}
+ LoseContextOnFirstGetContext() {}
- virtual bool makeContextCurrent() OVERRIDE { return !context_lost_; }
-
- virtual void getProgramiv(WebGLId program, WGC3Denum pname, WGC3Dint* value)
- OVERRIDE {
+ virtual void getProgramiv(WebGLId program,
+ WGC3Denum pname,
+ WGC3Dint* value) OVERRIDE {
context_lost_ = true;
*value = 0;
}
- virtual void getShaderiv(WebGLId shader, WGC3Denum pname, WGC3Dint* value)
- OVERRIDE {
+ virtual void getShaderiv(WebGLId shader,
+ WGC3Denum pname,
+ WGC3Dint* value) OVERRIDE {
context_lost_ = true;
*value = 0;
}
-
- virtual WGC3Denum getGraphicsResetStatusARB() OVERRIDE {
- return context_lost_ ? 1 : 0;
- }
-
- private:
- bool context_lost_;
};
-TEST(GLRendererTest2, InitializationWithQuicklyLostContextDoesNotAssert) {
+TEST_F(GLRendererTest, InitializationWithQuicklyLostContextDoesNotAssert) {
FakeOutputSurfaceClient output_surface_client;
scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
scoped_ptr<TestWebGraphicsContext3D>(new LoseContextOnFirstGetContext)));
CHECK(output_surface->BindToClient(&output_surface_client));
scoped_ptr<ResourceProvider> resource_provider(
- ResourceProvider::Create(output_surface.get(), 0, false));
+ ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
LayerTreeSettings settings;
FakeRendererClient renderer_client;
@@ -687,15 +601,11 @@ TEST(GLRendererTest2, InitializationWithQuicklyLostContextDoesNotAssert) {
&settings,
output_surface.get(),
resource_provider.get());
-
- renderer.Initialize();
}
class ClearCountingContext : public TestWebGraphicsContext3D {
public:
- ClearCountingContext() {
- test_capabilities_.discard_framebuffer = true;
- }
+ ClearCountingContext() { test_capabilities_.discard_framebuffer = true; }
MOCK_METHOD3(discardFramebufferEXT,
void(WGC3Denum target,
@@ -704,7 +614,7 @@ class ClearCountingContext : public TestWebGraphicsContext3D {
MOCK_METHOD1(clear, void(WGC3Dbitfield mask));
};
-TEST(GLRendererTest2, OpaqueBackground) {
+TEST_F(GLRendererTest, OpaqueBackground) {
scoped_ptr<ClearCountingContext> context_owned(new ClearCountingContext);
ClearCountingContext* context = context_owned.get();
@@ -714,7 +624,7 @@ TEST(GLRendererTest2, OpaqueBackground) {
CHECK(output_surface->BindToClient(&output_surface_client));
scoped_ptr<ResourceProvider> resource_provider(
- ResourceProvider::Create(output_surface.get(), 0, false));
+ ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
LayerTreeSettings settings;
FakeRendererClient renderer_client;
@@ -723,9 +633,12 @@ TEST(GLRendererTest2, OpaqueBackground) {
output_surface.get(),
resource_provider.get());
- renderer_client.root_render_pass()->has_transparent_background = false;
-
- EXPECT_TRUE(renderer.Initialize());
+ gfx::Rect viewport_rect(1, 1);
+ TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
+ RenderPass::Id(1, 0),
+ viewport_rect,
+ gfx::Transform());
+ root_pass->has_transparent_background = false;
// On DEBUG builds, render passes with opaque background clear to blue to
// easily see regions that were not drawn on the screen.
@@ -737,12 +650,17 @@ TEST(GLRendererTest2, OpaqueBackground) {
#else
EXPECT_CALL(*context, clear(_)).Times(1);
#endif
- renderer.DrawFrame(
- renderer_client.render_passes_in_draw_order(), NULL, 1.f, true);
+ renderer.DrawFrame(&render_passes_in_draw_order_,
+ NULL,
+ 1.f,
+ viewport_rect,
+ viewport_rect,
+ true,
+ false);
Mock::VerifyAndClearExpectations(context);
}
-TEST(GLRendererTest2, TransparentBackground) {
+TEST_F(GLRendererTest, TransparentBackground) {
scoped_ptr<ClearCountingContext> context_owned(new ClearCountingContext);
ClearCountingContext* context = context_owned.get();
@@ -752,7 +670,7 @@ TEST(GLRendererTest2, TransparentBackground) {
CHECK(output_surface->BindToClient(&output_surface_client));
scoped_ptr<ResourceProvider> resource_provider(
- ResourceProvider::Create(output_surface.get(), 0, false));
+ ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
LayerTreeSettings settings;
FakeRendererClient renderer_client;
@@ -761,20 +679,27 @@ TEST(GLRendererTest2, TransparentBackground) {
output_surface.get(),
resource_provider.get());
- renderer_client.root_render_pass()->has_transparent_background = true;
+ gfx::Rect viewport_rect(1, 1);
+ TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
+ RenderPass::Id(1, 0),
+ viewport_rect,
+ gfx::Transform());
+ root_pass->has_transparent_background = true;
- EXPECT_TRUE(renderer.Initialize());
-
- EXPECT_CALL(*context, discardFramebufferEXT(GL_FRAMEBUFFER, 1, _))
- .Times(1);
+ EXPECT_CALL(*context, discardFramebufferEXT(GL_FRAMEBUFFER, 1, _)).Times(1);
EXPECT_CALL(*context, clear(_)).Times(1);
- renderer.DrawFrame(
- renderer_client.render_passes_in_draw_order(), NULL, 1.f, true);
+ renderer.DrawFrame(&render_passes_in_draw_order_,
+ NULL,
+ 1.f,
+ viewport_rect,
+ viewport_rect,
+ true,
+ false);
Mock::VerifyAndClearExpectations(context);
}
-TEST(GLRendererTest2, OffscreenOutputSurface) {
+TEST_F(GLRendererTest, OffscreenOutputSurface) {
scoped_ptr<ClearCountingContext> context_owned(new ClearCountingContext);
ClearCountingContext* context = context_owned.get();
@@ -784,7 +709,7 @@ TEST(GLRendererTest2, OffscreenOutputSurface) {
CHECK(output_surface->BindToClient(&output_surface_client));
scoped_ptr<ResourceProvider> resource_provider(
- ResourceProvider::Create(output_surface.get(), 0, false));
+ ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
LayerTreeSettings settings;
FakeRendererClient renderer_client;
@@ -793,14 +718,23 @@ TEST(GLRendererTest2, OffscreenOutputSurface) {
output_surface.get(),
resource_provider.get());
- EXPECT_TRUE(renderer.Initialize());
+ gfx::Rect viewport_rect(1, 1);
+ AddRenderPass(&render_passes_in_draw_order_,
+ RenderPass::Id(1, 0),
+ viewport_rect,
+ gfx::Transform());
EXPECT_CALL(*context, discardFramebufferEXT(GL_FRAMEBUFFER, _, _))
.With(Args<2, 1>(ElementsAre(GL_COLOR_ATTACHMENT0)))
.Times(1);
EXPECT_CALL(*context, clear(_)).Times(AnyNumber());
- renderer.DrawFrame(
- renderer_client.render_passes_in_draw_order(), NULL, 1.f, true);
+ renderer.DrawFrame(&render_passes_in_draw_order_,
+ NULL,
+ 1.f,
+ viewport_rect,
+ viewport_rect,
+ true,
+ false);
Mock::VerifyAndClearExpectations(context);
}
@@ -808,16 +742,9 @@ class VisibilityChangeIsLastCallTrackingContext
: public TestWebGraphicsContext3D {
public:
VisibilityChangeIsLastCallTrackingContext()
- : last_call_was_set_visibility_(false) {
- test_capabilities_.set_visibility = true;
- test_capabilities_.discard_backbuffer = true;
- }
+ : last_call_was_set_visibility_(false) {}
// WebGraphicsContext3D methods.
- virtual void setVisibilityCHROMIUM(bool visible) {
- DCHECK(last_call_was_set_visibility_ == false);
- last_call_was_set_visibility_ = true;
- }
virtual void flush() {
last_call_was_set_visibility_ = false;
}
@@ -833,14 +760,12 @@ class VisibilityChangeIsLastCallTrackingContext
virtual void deleteRenderbuffer(WebGLId) {
last_call_was_set_visibility_ = false;
}
- virtual void discardBackbufferCHROMIUM() {
- last_call_was_set_visibility_ = false;
- }
- virtual void ensureBackbufferCHROMIUM() {
- last_call_was_set_visibility_ = false;
- }
// Methods added for test.
+ void set_last_call_was_visibility(bool visible) {
+ DCHECK(last_call_was_set_visibility_ == false);
+ last_call_was_set_visibility_ = true;
+ }
bool last_call_was_set_visibility() const {
return last_call_was_set_visibility_;
}
@@ -849,18 +774,25 @@ class VisibilityChangeIsLastCallTrackingContext
bool last_call_was_set_visibility_;
};
-TEST(GLRendererTest2, VisibilityChangeIsLastCall) {
+TEST_F(GLRendererTest, VisibilityChangeIsLastCall) {
scoped_ptr<VisibilityChangeIsLastCallTrackingContext> context_owned(
new VisibilityChangeIsLastCallTrackingContext);
VisibilityChangeIsLastCallTrackingContext* context = context_owned.get();
+ scoped_refptr<TestContextProvider> provider = TestContextProvider::Create(
+ context_owned.PassAs<TestWebGraphicsContext3D>());
+
+ provider->support()->SetSurfaceVisibleCallback(base::Bind(
+ &VisibilityChangeIsLastCallTrackingContext::set_last_call_was_visibility,
+ base::Unretained(context)));
+
FakeOutputSurfaceClient output_surface_client;
scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
- context_owned.PassAs<TestWebGraphicsContext3D>()));
+ provider));
CHECK(output_surface->BindToClient(&output_surface_client));
scoped_ptr<ResourceProvider> resource_provider(
- ResourceProvider::Create(output_surface.get(), 0, false));
+ ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
LayerTreeSettings settings;
FakeRendererClient renderer_client;
@@ -869,24 +801,32 @@ TEST(GLRendererTest2, VisibilityChangeIsLastCall) {
output_surface.get(),
resource_provider.get());
- EXPECT_TRUE(renderer.Initialize());
+ gfx::Rect viewport_rect(1, 1);
+ AddRenderPass(&render_passes_in_draw_order_,
+ RenderPass::Id(1, 0),
+ viewport_rect,
+ gfx::Transform());
- // Ensure that the call to setVisibilityCHROMIUM is the last call issue to the
+ // Ensure that the call to SetSurfaceVisible is the last call issue to the
// GPU process, after glFlush is called, and after the RendererClient's
// SetManagedMemoryPolicy is called. Plumb this tracking between both the
// RenderClient and the Context by giving them both a pointer to a variable on
// the stack.
renderer.SetVisible(true);
- renderer.DrawFrame(
- renderer_client.render_passes_in_draw_order(), NULL, 1.f, true);
+ renderer.DrawFrame(&render_passes_in_draw_order_,
+ NULL,
+ 1.f,
+ viewport_rect,
+ viewport_rect,
+ true,
+ false);
renderer.SetVisible(false);
EXPECT_TRUE(context->last_call_was_set_visibility());
}
class TextureStateTrackingContext : public TestWebGraphicsContext3D {
public:
- TextureStateTrackingContext()
- : active_texture_(GL_INVALID_ENUM) {
+ TextureStateTrackingContext() : active_texture_(GL_INVALID_ENUM) {
test_capabilities_.egl_image_external = true;
}
@@ -909,7 +849,7 @@ class TextureStateTrackingContext : public TestWebGraphicsContext3D {
WGC3Denum active_texture_;
};
-TEST(GLRendererTest2, ActiveTextureState) {
+TEST_F(GLRendererTest, ActiveTextureState) {
scoped_ptr<TextureStateTrackingContext> context_owned(
new TextureStateTrackingContext);
TextureStateTrackingContext* context = context_owned.get();
@@ -920,7 +860,7 @@ TEST(GLRendererTest2, ActiveTextureState) {
CHECK(output_surface->BindToClient(&output_surface_client));
scoped_ptr<ResourceProvider> resource_provider(
- ResourceProvider::Create(output_surface.get(), 0, false));
+ ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
LayerTreeSettings settings;
FakeRendererClient renderer_client;
@@ -931,15 +871,14 @@ TEST(GLRendererTest2, ActiveTextureState) {
// During initialization we are allowed to set any texture parameters.
EXPECT_CALL(*context, texParameteri(_, _, _)).Times(AnyNumber());
- EXPECT_TRUE(renderer.Initialize());
- cc::RenderPass::Id id(1, 1);
- scoped_ptr<TestRenderPass> pass = TestRenderPass::Create();
- pass->SetNew(id,
- gfx::Rect(0, 0, 100, 100),
- gfx::Rect(0, 0, 100, 100),
- gfx::Transform());
- pass->AppendOneOfEveryQuadType(resource_provider.get(), RenderPass::Id(2, 1));
+ RenderPass::Id id(1, 1);
+ TestRenderPass* root_pass = AddRenderPass(
+ &render_passes_in_draw_order_, id, gfx::Rect(100, 100), gfx::Transform());
+ root_pass->AppendOneOfEveryQuadType(resource_provider.get(),
+ RenderPass::Id(2, 1));
+
+ renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
// Set up expected texture filter state transitions that match the quads
// created in AppendOneOfEveryQuadType().
@@ -971,18 +910,14 @@ TEST(GLRendererTest2, ActiveTextureState) {
EXPECT_CALL(*context, drawElements(_, _, _, _)).Times(6);
}
- cc::DirectRenderer::DrawingFrame drawing_frame;
- renderer.BeginDrawingFrame(&drawing_frame);
- EXPECT_EQ(static_cast<unsigned>(GL_TEXTURE0), context->active_texture());
-
- for (cc::QuadList::BackToFrontIterator
- it = pass->quad_list.BackToFrontBegin();
- it != pass->quad_list.BackToFrontEnd();
- ++it) {
- renderer.DoDrawQuad(&drawing_frame, *it);
- }
- renderer.FinishDrawingQuadList();
- EXPECT_EQ(static_cast<unsigned>(GL_TEXTURE0), context->active_texture());
+ gfx::Rect viewport_rect(100, 100);
+ renderer.DrawFrame(&render_passes_in_draw_order_,
+ NULL,
+ 1.f,
+ viewport_rect,
+ viewport_rect,
+ true,
+ false);
Mock::VerifyAndClearExpectations(context);
}
@@ -996,18 +931,18 @@ class NoClearRootRenderPassMockContext : public TestWebGraphicsContext3D {
WGC3Dintptr offset));
};
-TEST(GLRendererTest2, ShouldClearRootRenderPass) {
+TEST_F(GLRendererTest, ShouldClearRootRenderPass) {
scoped_ptr<NoClearRootRenderPassMockContext> mock_context_owned(
new NoClearRootRenderPassMockContext);
NoClearRootRenderPassMockContext* mock_context = mock_context_owned.get();
FakeOutputSurfaceClient output_surface_client;
scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
- mock_context_owned.PassAs<TestWebGraphicsContext3D>()));
+ mock_context_owned.PassAs<TestWebGraphicsContext3D>()));
CHECK(output_surface->BindToClient(&output_surface_client));
scoped_ptr<ResourceProvider> resource_provider(
- ResourceProvider::Create(output_surface.get(), 0, false));
+ ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
LayerTreeSettings settings;
settings.should_clear_root_render_pass = false;
@@ -1017,21 +952,21 @@ TEST(GLRendererTest2, ShouldClearRootRenderPass) {
&settings,
output_surface.get(),
resource_provider.get());
- EXPECT_TRUE(renderer.Initialize());
- gfx::Rect viewport_rect(renderer_client.DeviceViewport());
- ScopedPtrVector<RenderPass>& render_passes =
- *renderer_client.render_passes_in_draw_order();
- render_passes.clear();
+ gfx::Rect viewport_rect(10, 10);
RenderPass::Id root_pass_id(1, 0);
- TestRenderPass* root_pass = AddRenderPass(
- &render_passes, root_pass_id, viewport_rect, gfx::Transform());
+ TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
+ root_pass_id,
+ viewport_rect,
+ gfx::Transform());
AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
RenderPass::Id child_pass_id(2, 0);
- TestRenderPass* child_pass = AddRenderPass(
- &render_passes, child_pass_id, viewport_rect, gfx::Transform());
+ TestRenderPass* child_pass = AddRenderPass(&render_passes_in_draw_order_,
+ child_pass_id,
+ viewport_rect,
+ gfx::Transform());
AddQuad(child_pass, viewport_rect, SK_ColorBLUE);
AddRenderPassQuad(root_pass, child_pass);
@@ -1049,16 +984,20 @@ TEST(GLRendererTest2, ShouldClearRootRenderPass) {
EXPECT_CALL(*mock_context, drawElements(_, _, _, _)).Times(1);
// The second render pass is the root one, clearing should be prevented.
- EXPECT_CALL(*mock_context, clear(clear_bits)).Times(0)
- .After(first_render_pass);
+ EXPECT_CALL(*mock_context, clear(clear_bits)).Times(0).After(
+ first_render_pass);
- EXPECT_CALL(*mock_context, drawElements(_, _, _, _)).Times(AnyNumber())
- .After(first_render_pass);
+ EXPECT_CALL(*mock_context, drawElements(_, _, _, _)).Times(AnyNumber()).After(
+ first_render_pass);
- renderer.DecideRenderPassAllocationsForFrame(
- *renderer_client.render_passes_in_draw_order());
- renderer.DrawFrame(
- renderer_client.render_passes_in_draw_order(), NULL, 1.f, true);
+ renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
+ renderer.DrawFrame(&render_passes_in_draw_order_,
+ NULL,
+ 1.f,
+ viewport_rect,
+ viewport_rect,
+ true,
+ false);
// In multiple render passes all but the root pass should clear the
// framebuffer.
@@ -1085,7 +1024,7 @@ class ScissorTestOnClearCheckingContext : public TestWebGraphicsContext3D {
bool scissor_enabled_;
};
-TEST(GLRendererTest2, ScissorTestWhenClearing) {
+TEST_F(GLRendererTest, ScissorTestWhenClearing) {
scoped_ptr<ScissorTestOnClearCheckingContext> context_owned(
new ScissorTestOnClearCheckingContext);
@@ -1095,7 +1034,7 @@ TEST(GLRendererTest2, ScissorTestWhenClearing) {
CHECK(output_surface->BindToClient(&output_surface_client));
scoped_ptr<ResourceProvider> resource_provider(
- ResourceProvider::Create(output_surface.get(), 0, false));
+ ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
LayerTreeSettings settings;
FakeRendererClient renderer_client;
@@ -1103,38 +1042,45 @@ TEST(GLRendererTest2, ScissorTestWhenClearing) {
&settings,
output_surface.get(),
resource_provider.get());
- EXPECT_TRUE(renderer.Initialize());
EXPECT_FALSE(renderer.Capabilities().using_partial_swap);
- gfx::Rect viewport_rect(renderer_client.DeviceViewport());
- ScopedPtrVector<RenderPass>& render_passes =
- *renderer_client.render_passes_in_draw_order();
- render_passes.clear();
+ gfx::Rect viewport_rect(1, 1);
gfx::Rect grand_child_rect(25, 25);
RenderPass::Id grand_child_pass_id(3, 0);
- TestRenderPass* grand_child_pass = AddRenderPass(
- &render_passes, grand_child_pass_id, grand_child_rect, gfx::Transform());
+ TestRenderPass* 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);
RenderPass::Id child_pass_id(2, 0);
- TestRenderPass* child_pass = AddRenderPass(
- &render_passes, child_pass_id, child_rect, gfx::Transform());
+ TestRenderPass* child_pass = AddRenderPass(&render_passes_in_draw_order_,
+ child_pass_id,
+ child_rect,
+ gfx::Transform());
AddQuad(child_pass, child_rect, SK_ColorBLUE);
RenderPass::Id root_pass_id(1, 0);
- TestRenderPass* root_pass = AddRenderPass(
- &render_passes, root_pass_id, viewport_rect, gfx::Transform());
+ TestRenderPass* 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);
AddRenderPassQuad(child_pass, grand_child_pass);
- renderer.DecideRenderPassAllocationsForFrame(
- *renderer_client.render_passes_in_draw_order());
- renderer.DrawFrame(
- renderer_client.render_passes_in_draw_order(), NULL, 1.f, true);
+ renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
+ renderer.DrawFrame(&render_passes_in_draw_order_,
+ NULL,
+ 1.f,
+ viewport_rect,
+ viewport_rect,
+ true,
+ false);
}
class DiscardCheckingContext : public TestWebGraphicsContext3D {
@@ -1169,7 +1115,7 @@ class NonReshapableOutputSurface : public FakeOutputSurface {
void set_fixed_size(gfx::Size size) { surface_size_ = size; }
};
-TEST(GLRendererTest2, NoDiscardOnPartialUpdates) {
+TEST_F(GLRendererTest, NoDiscardOnPartialUpdates) {
scoped_ptr<DiscardCheckingContext> context_owned(new DiscardCheckingContext);
DiscardCheckingContext* context = context_owned.get();
@@ -1181,67 +1127,80 @@ TEST(GLRendererTest2, NoDiscardOnPartialUpdates) {
output_surface->set_fixed_size(gfx::Size(100, 100));
scoped_ptr<ResourceProvider> resource_provider(
- ResourceProvider::Create(output_surface.get(), 0, false));
+ ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
LayerTreeSettings settings;
settings.partial_swap_enabled = true;
FakeRendererClient renderer_client;
- renderer_client.set_viewport(gfx::Rect(0, 0, 100, 100));
- renderer_client.set_clip(gfx::Rect(0, 0, 100, 100));
FakeRendererGL renderer(&renderer_client,
&settings,
output_surface.get(),
resource_provider.get());
- EXPECT_TRUE(renderer.Initialize());
EXPECT_TRUE(renderer.Capabilities().using_partial_swap);
- gfx::Rect viewport_rect(renderer_client.DeviceViewport());
- ScopedPtrVector<RenderPass>& render_passes =
- *renderer_client.render_passes_in_draw_order();
- render_passes.clear();
+ gfx::Rect viewport_rect(100, 100);
+ gfx::Rect clip_rect(100, 100);
{
// Partial frame, should not discard.
RenderPass::Id root_pass_id(1, 0);
- TestRenderPass* root_pass = AddRenderPass(
- &render_passes, root_pass_id, viewport_rect, gfx::Transform());
+ TestRenderPass* 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::RectF(2.f, 2.f, 3.f, 3.f);
- renderer.DecideRenderPassAllocationsForFrame(
- *renderer_client.render_passes_in_draw_order());
- renderer.DrawFrame(
- renderer_client.render_passes_in_draw_order(), NULL, 1.f, true);
+ renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
+ renderer.DrawFrame(&render_passes_in_draw_order_,
+ NULL,
+ 1.f,
+ viewport_rect,
+ clip_rect,
+ true,
+ false);
EXPECT_EQ(0, context->discarded());
context->reset();
}
{
// Full frame, should discard.
RenderPass::Id root_pass_id(1, 0);
- TestRenderPass* root_pass = AddRenderPass(
- &render_passes, root_pass_id, viewport_rect, gfx::Transform());
+ TestRenderPass* 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::RectF(root_pass->output_rect);
- renderer.DecideRenderPassAllocationsForFrame(
- *renderer_client.render_passes_in_draw_order());
- renderer.DrawFrame(
- renderer_client.render_passes_in_draw_order(), NULL, 1.f, true);
+ renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
+ renderer.DrawFrame(&render_passes_in_draw_order_,
+ NULL,
+ 1.f,
+ viewport_rect,
+ clip_rect,
+ true,
+ false);
EXPECT_EQ(1, context->discarded());
context->reset();
}
{
// Partial frame, disallow partial swap, should discard.
RenderPass::Id root_pass_id(1, 0);
- TestRenderPass* root_pass = AddRenderPass(
- &render_passes, root_pass_id, viewport_rect, gfx::Transform());
+ TestRenderPass* 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::RectF(2.f, 2.f, 3.f, 3.f);
- renderer.DecideRenderPassAllocationsForFrame(
- *renderer_client.render_passes_in_draw_order());
- renderer.DrawFrame(
- renderer_client.render_passes_in_draw_order(), NULL, 1.f, false);
+ renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
+ renderer.DrawFrame(&render_passes_in_draw_order_,
+ NULL,
+ 1.f,
+ viewport_rect,
+ clip_rect,
+ false,
+ false);
EXPECT_EQ(1, context->discarded());
context->reset();
}
@@ -1249,68 +1208,90 @@ TEST(GLRendererTest2, NoDiscardOnPartialUpdates) {
// Full frame, external scissor is set, should not discard.
output_surface->set_has_external_stencil_test(true);
RenderPass::Id root_pass_id(1, 0);
- TestRenderPass* root_pass = AddRenderPass(
- &render_passes, root_pass_id, viewport_rect, gfx::Transform());
+ TestRenderPass* 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::RectF(root_pass->output_rect);
root_pass->has_transparent_background = false;
- renderer.DecideRenderPassAllocationsForFrame(
- *renderer_client.render_passes_in_draw_order());
- renderer.DrawFrame(
- renderer_client.render_passes_in_draw_order(), NULL, 1.f, true);
+ renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
+ renderer.DrawFrame(&render_passes_in_draw_order_,
+ NULL,
+ 1.f,
+ viewport_rect,
+ clip_rect,
+ true,
+ false);
EXPECT_EQ(0, context->discarded());
context->reset();
output_surface->set_has_external_stencil_test(false);
}
{
// Full frame, clipped, should not discard.
- renderer_client.set_clip(gfx::Rect(10, 10, 10, 10));
+ clip_rect = gfx::Rect(10, 10, 10, 10);
RenderPass::Id root_pass_id(1, 0);
- TestRenderPass* root_pass = AddRenderPass(
- &render_passes, root_pass_id, viewport_rect, gfx::Transform());
+ TestRenderPass* 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::RectF(root_pass->output_rect);
- renderer.DecideRenderPassAllocationsForFrame(
- *renderer_client.render_passes_in_draw_order());
- renderer.DrawFrame(
- renderer_client.render_passes_in_draw_order(), NULL, 1.f, true);
+ renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
+ renderer.DrawFrame(&render_passes_in_draw_order_,
+ NULL,
+ 1.f,
+ viewport_rect,
+ clip_rect,
+ true,
+ false);
EXPECT_EQ(0, context->discarded());
context->reset();
}
{
// Full frame, doesn't cover the surface, should not discard.
- renderer_client.set_viewport(gfx::Rect(10, 10, 10, 10));
- viewport_rect = renderer_client.DeviceViewport();
+ viewport_rect = gfx::Rect(10, 10, 10, 10);
RenderPass::Id root_pass_id(1, 0);
- TestRenderPass* root_pass = AddRenderPass(
- &render_passes, root_pass_id, viewport_rect, gfx::Transform());
+ TestRenderPass* 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::RectF(root_pass->output_rect);
- renderer.DecideRenderPassAllocationsForFrame(
- *renderer_client.render_passes_in_draw_order());
- renderer.DrawFrame(
- renderer_client.render_passes_in_draw_order(), NULL, 1.f, true);
+ renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
+ renderer.DrawFrame(&render_passes_in_draw_order_,
+ NULL,
+ 1.f,
+ viewport_rect,
+ clip_rect,
+ true,
+ false);
EXPECT_EQ(0, context->discarded());
context->reset();
}
{
// Full frame, doesn't cover the surface (no offset), should not discard.
- renderer_client.set_viewport(gfx::Rect(0, 0, 50, 50));
- renderer_client.set_clip(gfx::Rect(0, 0, 100, 100));
- viewport_rect = renderer_client.DeviceViewport();
+ clip_rect = gfx::Rect(100, 100);
+ viewport_rect = gfx::Rect(50, 50);
RenderPass::Id root_pass_id(1, 0);
- TestRenderPass* root_pass = AddRenderPass(
- &render_passes, root_pass_id, viewport_rect, gfx::Transform());
+ TestRenderPass* 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::RectF(root_pass->output_rect);
- renderer.DecideRenderPassAllocationsForFrame(
- *renderer_client.render_passes_in_draw_order());
- renderer.DrawFrame(
- renderer_client.render_passes_in_draw_order(), NULL, 1.f, true);
+ renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
+ renderer.DrawFrame(&render_passes_in_draw_order_,
+ NULL,
+ 1.f,
+ viewport_rect,
+ clip_rect,
+ true,
+ false);
EXPECT_EQ(0, context->discarded());
context->reset();
}
@@ -1346,7 +1327,7 @@ class FlippedScissorAndViewportContext : public TestWebGraphicsContext3D {
bool did_call_scissor_;
};
-TEST(GLRendererTest2, ScissorAndViewportWithinNonreshapableSurface) {
+TEST_F(GLRendererTest, ScissorAndViewportWithinNonreshapableSurface) {
// In Android WebView, the OutputSurface is unable to respect reshape() calls
// and maintains a fixed size. This test verifies that glViewport and
// glScissor's Y coordinate is flipped correctly in this environment, and that
@@ -1360,40 +1341,39 @@ TEST(GLRendererTest2, ScissorAndViewportWithinNonreshapableSurface) {
CHECK(output_surface->BindToClient(&output_surface_client));
scoped_ptr<ResourceProvider> resource_provider(
- ResourceProvider::Create(output_surface.get(), 0, false));
+ ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
LayerTreeSettings settings;
FakeRendererClient renderer_client;
- renderer_client.set_viewport(gfx::Rect(10, 10, 100, 100));
- renderer_client.set_clip(gfx::Rect(10, 10, 100, 100));
FakeRendererGL renderer(&renderer_client,
&settings,
output_surface.get(),
resource_provider.get());
- EXPECT_TRUE(renderer.Initialize());
EXPECT_FALSE(renderer.Capabilities().using_partial_swap);
- gfx::Rect viewport_rect(renderer_client.DeviceViewport().size());
+ gfx::Rect device_viewport_rect(10, 10, 100, 100);
+ gfx::Rect viewport_rect(device_viewport_rect.size());
gfx::Rect quad_rect = gfx::Rect(20, 20, 20, 20);
- ScopedPtrVector<RenderPass>& render_passes =
- *renderer_client.render_passes_in_draw_order();
- render_passes.clear();
RenderPass::Id root_pass_id(1, 0);
- TestRenderPass* root_pass = AddRenderPass(
- &render_passes, root_pass_id, viewport_rect, gfx::Transform());
+ TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
+ root_pass_id,
+ viewport_rect,
+ gfx::Transform());
AddClippedQuad(root_pass, quad_rect, SK_ColorGREEN);
- renderer.DecideRenderPassAllocationsForFrame(
- *renderer_client.render_passes_in_draw_order());
- renderer.DrawFrame(
- renderer_client.render_passes_in_draw_order(), NULL, 1.f, true);
+ renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
+ renderer.DrawFrame(&render_passes_in_draw_order_,
+ NULL,
+ 1.f,
+ device_viewport_rect,
+ device_viewport_rect,
+ true,
+ false);
}
TEST_F(GLRendererShaderTest, DrawRenderPassQuadShaderPermutations) {
- gfx::Rect viewport_rect(renderer_client_.DeviceViewport());
- ScopedPtrVector<RenderPass>* render_passes =
- renderer_client_.render_passes_in_draw_order();
+ gfx::Rect viewport_rect(1, 1);
gfx::Rect child_rect(50, 50);
RenderPass::Id child_pass_id(2, 0);
@@ -1402,11 +1382,11 @@ TEST_F(GLRendererShaderTest, DrawRenderPassQuadShaderPermutations) {
RenderPass::Id root_pass_id(1, 0);
TestRenderPass* root_pass;
- cc::ResourceProvider::ResourceId mask =
- resource_provider_->CreateResource(gfx::Size(20, 12),
- GL_CLAMP_TO_EDGE,
- ResourceProvider::TextureUsageAny,
- resource_provider_->best_texture_format());
+ ResourceProvider::ResourceId mask = resource_provider_->CreateResource(
+ gfx::Size(20, 12),
+ GL_CLAMP_TO_EDGE,
+ ResourceProvider::TextureUsageAny,
+ resource_provider_->best_texture_format());
resource_provider_->AllocateForTesting(mask);
SkScalar matrix[20];
@@ -1429,158 +1409,213 @@ TEST_F(GLRendererShaderTest, DrawRenderPassQuadShaderPermutations) {
skia::AdoptRef(new SkColorMatrixFilter(matrix)));
skia::RefPtr<SkImageFilter> filter = skia::AdoptRef(
SkColorFilterImageFilter::Create(color_filter.get(), NULL));
+ FilterOperations filters;
+ filters.Append(FilterOperation::CreateReferenceFilter(filter));
gfx::Transform transform_causing_aa;
transform_causing_aa.Rotate(20.0);
// RenderPassProgram
- render_passes->clear();
-
- child_pass = AddRenderPass(
- render_passes, child_pass_id, child_rect, gfx::Transform());
-
- root_pass = AddRenderPass(
- render_passes, root_pass_id, viewport_rect, gfx::Transform());
-
- AddRenderPassQuad(root_pass,
- child_pass,
- 0,
- skia::RefPtr<SkImageFilter>(),
- gfx::Transform());
-
- renderer_->DecideRenderPassAllocationsForFrame(
- *renderer_client_.render_passes_in_draw_order());
- renderer_->DrawFrame(
- renderer_client_.render_passes_in_draw_order(), NULL, 1.f, true);
- TestRenderPassProgram();
+ child_pass = AddRenderPass(&render_passes_in_draw_order_,
+ child_pass_id,
+ child_rect,
+ gfx::Transform());
+
+ root_pass = AddRenderPass(&render_passes_in_draw_order_,
+ root_pass_id,
+ viewport_rect,
+ gfx::Transform());
+
+ AddRenderPassQuad(
+ root_pass, child_pass, 0, FilterOperations(), gfx::Transform());
+
+ renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
+ renderer_->DrawFrame(&render_passes_in_draw_order_,
+ NULL,
+ 1.f,
+ viewport_rect,
+ viewport_rect,
+ true,
+ false);
+ TestRenderPassProgram(TexCoordPrecisionMedium);
// RenderPassColorMatrixProgram
- render_passes->clear();
-
- child_pass = AddRenderPass(
- render_passes, child_pass_id, child_rect, transform_causing_aa);
-
- root_pass = AddRenderPass(
- render_passes, root_pass_id, viewport_rect, gfx::Transform());
-
- AddRenderPassQuad(root_pass, child_pass, 0, filter, gfx::Transform());
-
- renderer_->DecideRenderPassAllocationsForFrame(
- *renderer_client_.render_passes_in_draw_order());
- renderer_->DrawFrame(
- renderer_client_.render_passes_in_draw_order(), NULL, 1.f, true);
- TestRenderPassColorMatrixProgram();
+ render_passes_in_draw_order_.clear();
+
+ child_pass = AddRenderPass(&render_passes_in_draw_order_,
+ child_pass_id,
+ child_rect,
+ transform_causing_aa);
+
+ root_pass = AddRenderPass(&render_passes_in_draw_order_,
+ root_pass_id,
+ viewport_rect,
+ gfx::Transform());
+
+ AddRenderPassQuad(root_pass, child_pass, 0, filters, gfx::Transform());
+
+ renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
+ renderer_->DrawFrame(&render_passes_in_draw_order_,
+ NULL,
+ 1.f,
+ viewport_rect,
+ viewport_rect,
+ true,
+ false);
+ TestRenderPassColorMatrixProgram(TexCoordPrecisionMedium);
// RenderPassMaskProgram
- render_passes->clear();
-
- child_pass = AddRenderPass(
- render_passes, child_pass_id, child_rect, gfx::Transform());
-
- root_pass = AddRenderPass(
- render_passes, root_pass_id, viewport_rect, gfx::Transform());
-
- AddRenderPassQuad(root_pass,
- child_pass,
- mask,
- skia::RefPtr<SkImageFilter>(),
- gfx::Transform());
-
- renderer_->DecideRenderPassAllocationsForFrame(
- *renderer_client_.render_passes_in_draw_order());
- renderer_->DrawFrame(
- renderer_client_.render_passes_in_draw_order(), NULL, 1.f, true);
- TestRenderPassMaskProgram();
+ render_passes_in_draw_order_.clear();
+
+ child_pass = AddRenderPass(&render_passes_in_draw_order_,
+ child_pass_id,
+ child_rect,
+ gfx::Transform());
+
+ root_pass = AddRenderPass(&render_passes_in_draw_order_,
+ root_pass_id,
+ viewport_rect,
+ gfx::Transform());
+
+ AddRenderPassQuad(
+ root_pass, child_pass, mask, FilterOperations(), gfx::Transform());
+
+ renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
+ renderer_->DrawFrame(&render_passes_in_draw_order_,
+ NULL,
+ 1.f,
+ viewport_rect,
+ viewport_rect,
+ true,
+ false);
+ TestRenderPassMaskProgram(TexCoordPrecisionMedium);
// RenderPassMaskColorMatrixProgram
- render_passes->clear();
-
- child_pass = AddRenderPass(
- render_passes, child_pass_id, child_rect, gfx::Transform());
-
- root_pass = AddRenderPass(
- render_passes, root_pass_id, viewport_rect, gfx::Transform());
-
- AddRenderPassQuad(root_pass, child_pass, mask, filter, gfx::Transform());
-
- renderer_->DecideRenderPassAllocationsForFrame(
- *renderer_client_.render_passes_in_draw_order());
- renderer_->DrawFrame(
- renderer_client_.render_passes_in_draw_order(), NULL, 1.f, true);
- TestRenderPassMaskColorMatrixProgram();
+ render_passes_in_draw_order_.clear();
+
+ child_pass = AddRenderPass(&render_passes_in_draw_order_,
+ child_pass_id,
+ child_rect,
+ gfx::Transform());
+
+ root_pass = AddRenderPass(&render_passes_in_draw_order_,
+ root_pass_id,
+ viewport_rect,
+ gfx::Transform());
+
+ AddRenderPassQuad(root_pass, child_pass, mask, filters, gfx::Transform());
+
+ renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
+ renderer_->DrawFrame(&render_passes_in_draw_order_,
+ NULL,
+ 1.f,
+ viewport_rect,
+ viewport_rect,
+ true,
+ false);
+ TestRenderPassMaskColorMatrixProgram(TexCoordPrecisionMedium);
// RenderPassProgramAA
- render_passes->clear();
-
- child_pass = AddRenderPass(
- render_passes, child_pass_id, child_rect, transform_causing_aa);
-
- root_pass = AddRenderPass(
- render_passes, root_pass_id, viewport_rect, gfx::Transform());
-
- AddRenderPassQuad(root_pass,
- child_pass,
- 0,
- skia::RefPtr<SkImageFilter>(),
- transform_causing_aa);
-
- renderer_->DecideRenderPassAllocationsForFrame(
- *renderer_client_.render_passes_in_draw_order());
- renderer_->DrawFrame(
- renderer_client_.render_passes_in_draw_order(), NULL, 1.f, true);
- TestRenderPassProgramAA();
+ render_passes_in_draw_order_.clear();
+
+ child_pass = AddRenderPass(&render_passes_in_draw_order_,
+ child_pass_id,
+ child_rect,
+ transform_causing_aa);
+
+ root_pass = AddRenderPass(&render_passes_in_draw_order_,
+ root_pass_id,
+ viewport_rect,
+ gfx::Transform());
+
+ AddRenderPassQuad(
+ root_pass, child_pass, 0, FilterOperations(), transform_causing_aa);
+
+ renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
+ renderer_->DrawFrame(&render_passes_in_draw_order_,
+ NULL,
+ 1.f,
+ viewport_rect,
+ viewport_rect,
+ true,
+ false);
+ TestRenderPassProgramAA(TexCoordPrecisionMedium);
// RenderPassColorMatrixProgramAA
- render_passes->clear();
-
- child_pass = AddRenderPass(
- render_passes, child_pass_id, child_rect, transform_causing_aa);
-
- root_pass = AddRenderPass(
- render_passes, root_pass_id, viewport_rect, gfx::Transform());
-
- AddRenderPassQuad(root_pass, child_pass, 0, filter, transform_causing_aa);
-
- renderer_->DecideRenderPassAllocationsForFrame(
- *renderer_client_.render_passes_in_draw_order());
- renderer_->DrawFrame(
- renderer_client_.render_passes_in_draw_order(), NULL, 1.f, true);
- TestRenderPassColorMatrixProgramAA();
+ render_passes_in_draw_order_.clear();
+
+ child_pass = AddRenderPass(&render_passes_in_draw_order_,
+ child_pass_id,
+ child_rect,
+ transform_causing_aa);
+
+ root_pass = AddRenderPass(&render_passes_in_draw_order_,
+ root_pass_id,
+ viewport_rect,
+ gfx::Transform());
+
+ AddRenderPassQuad(root_pass, child_pass, 0, filters, transform_causing_aa);
+
+ renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
+ renderer_->DrawFrame(&render_passes_in_draw_order_,
+ NULL,
+ 1.f,
+ viewport_rect,
+ viewport_rect,
+ true,
+ false);
+ TestRenderPassColorMatrixProgramAA(TexCoordPrecisionMedium);
// RenderPassMaskProgramAA
- render_passes->clear();
-
- child_pass = AddRenderPass(render_passes, child_pass_id, child_rect,
- transform_causing_aa);
-
- root_pass = AddRenderPass(render_passes, root_pass_id, viewport_rect,
- gfx::Transform());
-
- AddRenderPassQuad(root_pass, child_pass, mask, skia::RefPtr<SkImageFilter>(),
- transform_causing_aa);
-
- renderer_->DecideRenderPassAllocationsForFrame(
- *renderer_client_.render_passes_in_draw_order());
- renderer_->DrawFrame(
- renderer_client_.render_passes_in_draw_order(), NULL, 1.f, true);
- TestRenderPassMaskProgramAA();
+ render_passes_in_draw_order_.clear();
+
+ child_pass = AddRenderPass(&render_passes_in_draw_order_,
+ child_pass_id,
+ child_rect,
+ transform_causing_aa);
+
+ root_pass = AddRenderPass(&render_passes_in_draw_order_,
+ root_pass_id,
+ viewport_rect,
+ gfx::Transform());
+
+ AddRenderPassQuad(
+ root_pass, child_pass, mask, FilterOperations(), transform_causing_aa);
+
+ renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
+ renderer_->DrawFrame(&render_passes_in_draw_order_,
+ NULL,
+ 1.f,
+ viewport_rect,
+ viewport_rect,
+ true,
+ false);
+ TestRenderPassMaskProgramAA(TexCoordPrecisionMedium);
// RenderPassMaskColorMatrixProgramAA
- render_passes->clear();
-
- child_pass = AddRenderPass(render_passes, child_pass_id, child_rect,
- transform_causing_aa);
-
- root_pass = AddRenderPass(render_passes, root_pass_id, viewport_rect,
- transform_causing_aa);
-
- AddRenderPassQuad(root_pass, child_pass, mask, filter, transform_causing_aa);
-
- renderer_->DecideRenderPassAllocationsForFrame(
- *renderer_client_.render_passes_in_draw_order());
- renderer_->DrawFrame(
- renderer_client_.render_passes_in_draw_order(), NULL, 1.f, true);
- TestRenderPassMaskColorMatrixProgramAA();
+ render_passes_in_draw_order_.clear();
+
+ child_pass = AddRenderPass(&render_passes_in_draw_order_,
+ child_pass_id,
+ child_rect,
+ transform_causing_aa);
+
+ root_pass = AddRenderPass(&render_passes_in_draw_order_,
+ root_pass_id,
+ viewport_rect,
+ transform_causing_aa);
+
+ AddRenderPassQuad(root_pass, child_pass, mask, filters, transform_causing_aa);
+
+ renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
+ renderer_->DrawFrame(&render_passes_in_draw_order_,
+ NULL,
+ 1.f,
+ viewport_rect,
+ viewport_rect,
+ true,
+ false);
+ TestRenderPassMaskColorMatrixProgramAA(TexCoordPrecisionMedium);
}
// At this time, the AA code path cannot be taken if the surface's rect would
@@ -1590,7 +1625,7 @@ TEST_F(GLRendererShaderTest, DrawRenderPassQuadSkipsAAForClippingTransform) {
RenderPass::Id child_pass_id(2, 0);
TestRenderPass* child_pass;
- gfx::Rect viewport_rect(renderer_client_.DeviceViewport());
+ gfx::Rect viewport_rect(1, 1);
RenderPass::Id root_pass_id(1, 0);
TestRenderPass* root_pass;
@@ -1602,44 +1637,38 @@ 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(child_rect), &clipped);
ASSERT_TRUE(clipped);
- // Set up the render pass quad to be drawn
- ScopedPtrVector<RenderPass>* render_passes =
- renderer_client_.render_passes_in_draw_order();
-
- render_passes->clear();
+ child_pass = AddRenderPass(&render_passes_in_draw_order_,
+ child_pass_id,
+ child_rect,
+ transform_preventing_aa);
- child_pass = AddRenderPass(
- render_passes, child_pass_id, child_rect, transform_preventing_aa);
+ root_pass = AddRenderPass(&render_passes_in_draw_order_,
+ root_pass_id,
+ viewport_rect,
+ gfx::Transform());
- root_pass = AddRenderPass(
- render_passes, root_pass_id, viewport_rect, gfx::Transform());
+ AddRenderPassQuad(
+ root_pass, child_pass, 0, FilterOperations(), transform_preventing_aa);
- AddRenderPassQuad(root_pass,
- child_pass,
- 0,
- skia::RefPtr<SkImageFilter>(),
- transform_preventing_aa);
-
- renderer_->DecideRenderPassAllocationsForFrame(
- *renderer_client_.render_passes_in_draw_order());
- renderer_->DrawFrame(
- renderer_client_.render_passes_in_draw_order(), NULL, 1.f, true);
+ renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
+ renderer_->DrawFrame(&render_passes_in_draw_order_,
+ NULL,
+ 1.f,
+ viewport_rect,
+ viewport_rect,
+ true,
+ false);
// If use_aa incorrectly ignores clipping, it will use the
// RenderPassProgramAA shader instead of the RenderPassProgram.
- TestRenderPassProgram();
+ TestRenderPassProgram(TexCoordPrecisionMedium);
}
TEST_F(GLRendererShaderTest, DrawSolidColorShader) {
- gfx::Rect viewport_rect(renderer_client_.DeviceViewport());
- ScopedPtrVector<RenderPass>* render_passes =
- renderer_client_.render_passes_in_draw_order();
-
+ gfx::Rect viewport_rect(1, 1);
RenderPass::Id root_pass_id(1, 0);
TestRenderPass* root_pass;
@@ -1647,19 +1676,23 @@ TEST_F(GLRendererShaderTest, DrawSolidColorShader) {
pixel_aligned_transform_causing_aa.Translate(25.5f, 25.5f);
pixel_aligned_transform_causing_aa.Scale(0.5f, 0.5f);
- render_passes->clear();
-
- root_pass = AddRenderPass(
- render_passes, root_pass_id, viewport_rect, gfx::Transform());
+ root_pass = AddRenderPass(&render_passes_in_draw_order_,
+ root_pass_id,
+ viewport_rect,
+ gfx::Transform());
AddTransformedQuad(root_pass,
viewport_rect,
SK_ColorYELLOW,
pixel_aligned_transform_causing_aa);
- renderer_->DecideRenderPassAllocationsForFrame(
- *renderer_client_.render_passes_in_draw_order());
- renderer_->DrawFrame(
- renderer_client_.render_passes_in_draw_order(), NULL, 1.f, true);
+ renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
+ renderer_->DrawFrame(&render_passes_in_draw_order_,
+ NULL,
+ 1.f,
+ viewport_rect,
+ viewport_rect,
+ true,
+ false);
TestSolidColorProgramAA();
}
@@ -1667,7 +1700,6 @@ TEST_F(GLRendererShaderTest, DrawSolidColorShader) {
class OutputSurfaceMockContext : public TestWebGraphicsContext3D {
public:
OutputSurfaceMockContext() {
- test_capabilities_.discard_backbuffer = true;
test_capabilities_.post_sub_buffer = true;
}
@@ -1675,10 +1707,7 @@ class OutputSurfaceMockContext : public TestWebGraphicsContext3D {
// with StrictMock). We need to make sure that GLRenderer does not issue
// framebuffer-related GL calls directly. Instead these are supposed to go
// through the OutputSurface abstraction.
- MOCK_METHOD0(ensureBackbufferCHROMIUM, void());
- MOCK_METHOD0(discardBackbufferCHROMIUM, void());
MOCK_METHOD2(bindFramebuffer, void(WGC3Denum target, WebGLId framebuffer));
- MOCK_METHOD0(prepareTexture, void());
MOCK_METHOD3(reshapeWithScaleFactor,
void(int width, int height, float scale_factor));
MOCK_METHOD4(drawElements,
@@ -1691,9 +1720,9 @@ class OutputSurfaceMockContext : public TestWebGraphicsContext3D {
class MockOutputSurface : public OutputSurface {
public:
MockOutputSurface()
- : OutputSurface(TestContextProvider::Create(
- scoped_ptr<TestWebGraphicsContext3D>(
- new StrictMock<OutputSurfaceMockContext>))) {
+ : OutputSurface(
+ TestContextProvider::Create(scoped_ptr<TestWebGraphicsContext3D>(
+ new StrictMock<OutputSurfaceMockContext>))) {
surface_size_ = gfx::Size(100, 100);
}
virtual ~MockOutputSurface() {}
@@ -1705,45 +1734,50 @@ class MockOutputSurface : public OutputSurface {
MOCK_METHOD1(SwapBuffers, void(CompositorFrame* frame));
};
-class MockOutputSurfaceTest : public testing::Test, public FakeRendererClient {
+class MockOutputSurfaceTest : public GLRendererTest {
protected:
virtual void SetUp() {
FakeOutputSurfaceClient output_surface_client_;
CHECK(output_surface_.BindToClient(&output_surface_client_));
resource_provider_ =
- ResourceProvider::Create(&output_surface_, 0, false).Pass();
+ ResourceProvider::Create(&output_surface_, NULL, 0, false, 1).Pass();
- renderer_.reset(new FakeRendererGL(
- this, &settings_, &output_surface_, resource_provider_.get()));
- EXPECT_TRUE(renderer_->Initialize());
+ renderer_.reset(new FakeRendererGL(&renderer_client_,
+ &settings_,
+ &output_surface_,
+ resource_provider_.get()));
}
- void SwapBuffers() { renderer_->SwapBuffers(); }
-
- void DrawFrame(float device_scale_factor) {
- gfx::Rect viewport_rect(DeviceViewport());
- ScopedPtrVector<RenderPass>* render_passes = render_passes_in_draw_order();
- render_passes->clear();
+ void SwapBuffers() { renderer_->SwapBuffers(CompositorFrameMetadata()); }
+ void DrawFrame(float device_scale_factor, gfx::Rect device_viewport_rect) {
RenderPass::Id render_pass_id(1, 0);
- TestRenderPass* render_pass = AddRenderPass(
- render_passes, render_pass_id, viewport_rect, gfx::Transform());
- AddQuad(render_pass, viewport_rect, SK_ColorGREEN);
+ TestRenderPass* 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());
EXPECT_CALL(output_surface_,
- Reshape(DeviceViewport().size(), device_scale_factor)).Times(1);
+ Reshape(device_viewport_rect.size(), device_scale_factor))
+ .Times(1);
EXPECT_CALL(output_surface_, BindFramebuffer()).Times(1);
EXPECT_CALL(*Context(), drawElements(_, _, _, _)).Times(1);
renderer_->DecideRenderPassAllocationsForFrame(
- *render_passes_in_draw_order());
- renderer_->DrawFrame(
- render_passes_in_draw_order(), NULL, device_scale_factor, true);
+ render_passes_in_draw_order_);
+ renderer_->DrawFrame(&render_passes_in_draw_order_,
+ NULL,
+ device_scale_factor,
+ device_viewport_rect,
+ device_viewport_rect,
+ true,
+ false);
}
OutputSurfaceMockContext* Context() {
@@ -1755,38 +1789,40 @@ class MockOutputSurfaceTest : public testing::Test, public FakeRendererClient {
FakeOutputSurfaceClient output_surface_client_;
StrictMock<MockOutputSurface> output_surface_;
scoped_ptr<ResourceProvider> resource_provider_;
+ FakeRendererClient renderer_client_;
scoped_ptr<FakeRendererGL> renderer_;
};
TEST_F(MockOutputSurfaceTest, DrawFrameAndSwap) {
- DrawFrame(1.f);
+ gfx::Rect device_viewport_rect(1, 1);
+ DrawFrame(1.f, device_viewport_rect);
EXPECT_CALL(output_surface_, SwapBuffers(_)).Times(1);
- renderer_->SwapBuffers();
+ renderer_->SwapBuffers(CompositorFrameMetadata());
}
TEST_F(MockOutputSurfaceTest, DrawFrameAndResizeAndSwap) {
- DrawFrame(1.f);
+ gfx::Rect device_viewport_rect(1, 1);
+
+ DrawFrame(1.f, device_viewport_rect);
EXPECT_CALL(output_surface_, SwapBuffers(_)).Times(1);
- renderer_->SwapBuffers();
+ renderer_->SwapBuffers(CompositorFrameMetadata());
- set_viewport(gfx::Rect(0, 0, 2, 2));
- renderer_->ViewportChanged();
+ device_viewport_rect = gfx::Rect(2, 2);
- DrawFrame(2.f);
+ DrawFrame(2.f, device_viewport_rect);
EXPECT_CALL(output_surface_, SwapBuffers(_)).Times(1);
- renderer_->SwapBuffers();
+ renderer_->SwapBuffers(CompositorFrameMetadata());
- DrawFrame(2.f);
+ DrawFrame(2.f, device_viewport_rect);
EXPECT_CALL(output_surface_, SwapBuffers(_)).Times(1);
- renderer_->SwapBuffers();
+ renderer_->SwapBuffers(CompositorFrameMetadata());
- set_viewport(gfx::Rect(0, 0, 1, 1));
- renderer_->ViewportChanged();
+ device_viewport_rect = gfx::Rect(1, 1);
- DrawFrame(1.f);
+ DrawFrame(1.f, device_viewport_rect);
EXPECT_CALL(output_surface_, SwapBuffers(_)).Times(1);
- renderer_->SwapBuffers();
+ renderer_->SwapBuffers(CompositorFrameMetadata());
}
class GLRendererTestSyncPoint : public GLRendererPixelTest {
@@ -1806,25 +1842,26 @@ class GLRendererTestSyncPoint : public GLRendererPixelTest {
TEST_F(GLRendererTestSyncPoint, SignalSyncPointOnLostContext) {
int sync_point_callback_count = 0;
int other_callback_count = 0;
- unsigned sync_point =
- output_surface_->context_provider()->Context3d()->insertSyncPoint();
+ blink::WebGraphicsContext3D* context3d =
+ output_surface_->context_provider()->Context3d();
+ gpu::ContextSupport* context_support =
+ output_surface_->context_provider()->ContextSupport();
+
+ uint32 sync_point = context3d->insertSyncPoint();
- output_surface_->context_provider()->Context3d()->loseContextCHROMIUM(
- GL_GUILTY_CONTEXT_RESET_ARB, GL_INNOCENT_CONTEXT_RESET_ARB);
+ context3d->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
+ GL_INNOCENT_CONTEXT_RESET_ARB);
- SyncPointHelper::SignalSyncPoint(
- output_surface_->context_provider()->Context3d(),
- sync_point,
- base::Bind(&SyncPointCallback, &sync_point_callback_count));
+ context_support->SignalSyncPoint(
+ sync_point, base::Bind(&SyncPointCallback, &sync_point_callback_count));
EXPECT_EQ(0, sync_point_callback_count);
EXPECT_EQ(0, other_callback_count);
// Make the sync point happen.
- output_surface_->context_provider()->Context3d()->finish();
+ context3d->finish();
// Post a task after the sync point.
base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&OtherCallback, &other_callback_count));
+ FROM_HERE, base::Bind(&OtherCallback, &other_callback_count));
base::MessageLoop::current()->Run();
@@ -1836,22 +1873,24 @@ TEST_F(GLRendererTestSyncPoint, SignalSyncPointOnLostContext) {
TEST_F(GLRendererTestSyncPoint, SignalSyncPoint) {
int sync_point_callback_count = 0;
int other_callback_count = 0;
- unsigned sync_point =
- output_surface_->context_provider()->Context3d()->insertSyncPoint();
- SyncPointHelper::SignalSyncPoint(
- output_surface_->context_provider()->Context3d(),
- sync_point,
- base::Bind(&SyncPointCallback, &sync_point_callback_count));
+ blink::WebGraphicsContext3D* context3d =
+ output_surface_->context_provider()->Context3d();
+ gpu::ContextSupport* context_support =
+ output_surface_->context_provider()->ContextSupport();
+
+ uint32 sync_point = context3d->insertSyncPoint();
+
+ context_support->SignalSyncPoint(
+ sync_point, base::Bind(&SyncPointCallback, &sync_point_callback_count));
EXPECT_EQ(0, sync_point_callback_count);
EXPECT_EQ(0, other_callback_count);
// Make the sync point happen.
- output_surface_->context_provider()->Context3d()->finish();
+ context3d->finish();
// Post a task after the sync point.
base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&OtherCallback, &other_callback_count));
+ FROM_HERE, base::Bind(&OtherCallback, &other_callback_count));
base::MessageLoop::current()->Run();
diff --git a/chromium/cc/output/managed_memory_policy.cc b/chromium/cc/output/managed_memory_policy.cc
index 7e837662c29..049d2b03f9f 100644
--- a/chromium/cc/output/managed_memory_policy.cc
+++ b/chromium/cc/output/managed_memory_policy.cc
@@ -11,31 +11,30 @@ namespace cc {
const size_t ManagedMemoryPolicy::kDefaultNumResourcesLimit = 10 * 1000 * 1000;
+using gpu::MemoryAllocation;
+
ManagedMemoryPolicy::ManagedMemoryPolicy(size_t bytes_limit_when_visible)
: bytes_limit_when_visible(bytes_limit_when_visible),
- priority_cutoff_when_visible(CUTOFF_ALLOW_EVERYTHING),
- bytes_limit_when_not_visible(0),
- priority_cutoff_when_not_visible(CUTOFF_ALLOW_NOTHING),
+ priority_cutoff_when_visible(MemoryAllocation::CUTOFF_ALLOW_EVERYTHING),
+ num_resources_limit(kDefaultNumResourcesLimit) {}
+
+ManagedMemoryPolicy::ManagedMemoryPolicy(
+ const gpu::MemoryAllocation& allocation)
+ : bytes_limit_when_visible(allocation.bytes_limit_when_visible),
+ priority_cutoff_when_visible(allocation.priority_cutoff_when_visible),
num_resources_limit(kDefaultNumResourcesLimit) {}
ManagedMemoryPolicy::ManagedMemoryPolicy(
size_t bytes_limit_when_visible,
- PriorityCutoff priority_cutoff_when_visible,
- size_t bytes_limit_when_not_visible,
- PriorityCutoff priority_cutoff_when_not_visible,
+ MemoryAllocation::PriorityCutoff priority_cutoff_when_visible,
size_t num_resources_limit)
: bytes_limit_when_visible(bytes_limit_when_visible),
priority_cutoff_when_visible(priority_cutoff_when_visible),
- bytes_limit_when_not_visible(bytes_limit_when_not_visible),
- priority_cutoff_when_not_visible(priority_cutoff_when_not_visible),
num_resources_limit(num_resources_limit) {}
bool ManagedMemoryPolicy::operator==(const ManagedMemoryPolicy& other) const {
return bytes_limit_when_visible == other.bytes_limit_when_visible &&
priority_cutoff_when_visible == other.priority_cutoff_when_visible &&
- bytes_limit_when_not_visible == other.bytes_limit_when_not_visible &&
- priority_cutoff_when_not_visible ==
- other.priority_cutoff_when_not_visible &&
num_resources_limit == other.num_resources_limit;
}
@@ -44,15 +43,16 @@ bool ManagedMemoryPolicy::operator!=(const ManagedMemoryPolicy& other) const {
}
// static
-int ManagedMemoryPolicy::PriorityCutoffToValue(PriorityCutoff priority_cutoff) {
+int ManagedMemoryPolicy::PriorityCutoffToValue(
+ MemoryAllocation::PriorityCutoff priority_cutoff) {
switch (priority_cutoff) {
- case CUTOFF_ALLOW_NOTHING:
+ case MemoryAllocation::CUTOFF_ALLOW_NOTHING:
return PriorityCalculator::AllowNothingCutoff();
- case CUTOFF_ALLOW_REQUIRED_ONLY:
+ case MemoryAllocation::CUTOFF_ALLOW_REQUIRED_ONLY:
return PriorityCalculator::AllowVisibleOnlyCutoff();
- case CUTOFF_ALLOW_NICE_TO_HAVE:
+ case MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE:
return PriorityCalculator::AllowVisibleAndNearbyCutoff();
- case CUTOFF_ALLOW_EVERYTHING:
+ case MemoryAllocation::CUTOFF_ALLOW_EVERYTHING:
return PriorityCalculator::AllowEverythingCutoff();
}
NOTREACHED();
@@ -62,15 +62,15 @@ int ManagedMemoryPolicy::PriorityCutoffToValue(PriorityCutoff priority_cutoff) {
// static
TileMemoryLimitPolicy
ManagedMemoryPolicy::PriorityCutoffToTileMemoryLimitPolicy(
- PriorityCutoff priority_cutoff) {
+ gpu::MemoryAllocation::PriorityCutoff priority_cutoff) {
switch (priority_cutoff) {
- case CUTOFF_ALLOW_NOTHING:
+ case MemoryAllocation::CUTOFF_ALLOW_NOTHING:
return ALLOW_NOTHING;
- case CUTOFF_ALLOW_REQUIRED_ONLY:
+ case MemoryAllocation::CUTOFF_ALLOW_REQUIRED_ONLY:
return ALLOW_ABSOLUTE_MINIMUM;
- case CUTOFF_ALLOW_NICE_TO_HAVE:
+ case MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE:
return ALLOW_PREPAINT_ONLY;
- case CUTOFF_ALLOW_EVERYTHING:
+ case MemoryAllocation::CUTOFF_ALLOW_EVERYTHING:
return ALLOW_ANYTHING;
}
NOTREACHED();
diff --git a/chromium/cc/output/managed_memory_policy.h b/chromium/cc/output/managed_memory_policy.h
index 5a607a7a1f2..ad0224b6c42 100644
--- a/chromium/cc/output/managed_memory_policy.h
+++ b/chromium/cc/output/managed_memory_policy.h
@@ -8,36 +8,31 @@
#include "base/basictypes.h"
#include "cc/base/cc_export.h"
#include "cc/resources/tile_priority.h"
+#include "gpu/command_buffer/common/gpu_memory_allocation.h"
namespace cc {
struct CC_EXPORT ManagedMemoryPolicy {
- enum PriorityCutoff {
- CUTOFF_ALLOW_NOTHING,
- CUTOFF_ALLOW_REQUIRED_ONLY,
- CUTOFF_ALLOW_NICE_TO_HAVE,
- CUTOFF_ALLOW_EVERYTHING,
- };
static const size_t kDefaultNumResourcesLimit;
explicit ManagedMemoryPolicy(size_t bytes_limit_when_visible);
- ManagedMemoryPolicy(size_t bytes_limit_when_visible,
- PriorityCutoff priority_cutoff_when_visible,
- size_t bytes_limit_when_not_visible,
- PriorityCutoff priority_cutoff_when_not_visible,
- size_t num_resources_limit);
+ explicit ManagedMemoryPolicy(
+ const gpu::MemoryAllocation& allocation);
+ ManagedMemoryPolicy(
+ size_t bytes_limit_when_visible,
+ gpu::MemoryAllocation::PriorityCutoff priority_cutoff_when_visible,
+ size_t num_resources_limit);
bool operator==(const ManagedMemoryPolicy&) const;
bool operator!=(const ManagedMemoryPolicy&) const;
size_t bytes_limit_when_visible;
- PriorityCutoff priority_cutoff_when_visible;
- size_t bytes_limit_when_not_visible;
- PriorityCutoff priority_cutoff_when_not_visible;
+ gpu::MemoryAllocation::PriorityCutoff priority_cutoff_when_visible;
size_t num_resources_limit;
- static int PriorityCutoffToValue(PriorityCutoff priority_cutoff);
+ static int PriorityCutoffToValue(
+ gpu::MemoryAllocation::PriorityCutoff priority_cutoff);
static TileMemoryLimitPolicy PriorityCutoffToTileMemoryLimitPolicy(
- PriorityCutoff priority_cutoff);
+ gpu::MemoryAllocation::PriorityCutoff priority_cutoff);
};
} // namespace cc
diff --git a/chromium/cc/output/output_surface.cc b/chromium/cc/output/output_surface.cc
index 555fea27911..5bad7ec89b7 100644
--- a/chromium/cc/output/output_surface.cc
+++ b/chromium/cc/output/output_surface.cc
@@ -13,6 +13,7 @@
#include "base/debug/trace_event.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
+#include "base/metrics/histogram.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "cc/output/compositor_frame.h"
@@ -20,9 +21,13 @@
#include "cc/output/managed_memory_policy.h"
#include "cc/output/output_surface_client.h"
#include "cc/scheduler/delay_based_time_source.h"
+#include "gpu/GLES2/gl2extchromium.h"
+#include "gpu/command_buffer/client/context_support.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/khronos/GLES2/gl2ext.h"
+#include "ui/gfx/frame_time.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/size.h"
@@ -30,62 +35,67 @@ using std::set;
using std::string;
using std::vector;
+namespace {
+
+const size_t kGpuLatencyHistorySize = 60;
+const double kGpuLatencyEstimationPercentile = 100.0;
+
+}
+
namespace cc {
OutputSurface::OutputSurface(scoped_refptr<ContextProvider> context_provider)
: context_provider_(context_provider),
- has_gl_discard_backbuffer_(false),
- has_swap_buffers_complete_callback_(false),
device_scale_factor_(-1),
- weak_ptr_factory_(this),
max_frames_pending_(0),
pending_swap_buffers_(0),
- needs_begin_frame_(false),
- client_ready_for_begin_frame_(true),
+ needs_begin_impl_frame_(false),
+ client_ready_for_begin_impl_frame_(true),
client_(NULL),
- check_for_retroactive_begin_frame_pending_(false),
- external_stencil_test_enabled_(false) {}
+ check_for_retroactive_begin_impl_frame_pending_(false),
+ external_stencil_test_enabled_(false),
+ weak_ptr_factory_(this),
+ gpu_latency_history_(kGpuLatencyHistorySize) {}
-OutputSurface::OutputSurface(
- scoped_ptr<cc::SoftwareOutputDevice> software_device)
+OutputSurface::OutputSurface(scoped_ptr<SoftwareOutputDevice> software_device)
: software_device_(software_device.Pass()),
- has_gl_discard_backbuffer_(false),
- has_swap_buffers_complete_callback_(false),
device_scale_factor_(-1),
- weak_ptr_factory_(this),
max_frames_pending_(0),
pending_swap_buffers_(0),
- needs_begin_frame_(false),
- client_ready_for_begin_frame_(true),
+ needs_begin_impl_frame_(false),
+ client_ready_for_begin_impl_frame_(true),
client_(NULL),
- check_for_retroactive_begin_frame_pending_(false),
- external_stencil_test_enabled_(false) {}
+ check_for_retroactive_begin_impl_frame_pending_(false),
+ external_stencil_test_enabled_(false),
+ weak_ptr_factory_(this),
+ gpu_latency_history_(kGpuLatencyHistorySize) {}
-OutputSurface::OutputSurface(
- scoped_refptr<ContextProvider> context_provider,
- scoped_ptr<cc::SoftwareOutputDevice> software_device)
+OutputSurface::OutputSurface(scoped_refptr<ContextProvider> context_provider,
+ scoped_ptr<SoftwareOutputDevice> software_device)
: context_provider_(context_provider),
software_device_(software_device.Pass()),
- has_gl_discard_backbuffer_(false),
- has_swap_buffers_complete_callback_(false),
device_scale_factor_(-1),
- weak_ptr_factory_(this),
max_frames_pending_(0),
pending_swap_buffers_(0),
- needs_begin_frame_(false),
- client_ready_for_begin_frame_(true),
+ needs_begin_impl_frame_(false),
+ client_ready_for_begin_impl_frame_(true),
client_(NULL),
- check_for_retroactive_begin_frame_pending_(false),
- external_stencil_test_enabled_(false) {}
+ check_for_retroactive_begin_impl_frame_pending_(false),
+ external_stencil_test_enabled_(false),
+ weak_ptr_factory_(this),
+ gpu_latency_history_(kGpuLatencyHistorySize) {}
-void OutputSurface::InitializeBeginFrameEmulation(
+void OutputSurface::InitializeBeginImplFrameEmulation(
base::SingleThreadTaskRunner* task_runner,
bool throttle_frame_production,
base::TimeDelta interval) {
if (throttle_frame_production) {
- frame_rate_controller_.reset(
- new FrameRateController(
- DelayBasedTimeSource::Create(interval, task_runner)));
+ scoped_refptr<DelayBasedTimeSource> time_source;
+ if (gfx::FrameTime::TimestampsAreHighRes())
+ time_source = DelayBasedTimeSourceHighRes::Create(interval, task_runner);
+ else
+ time_source = DelayBasedTimeSource::Create(interval, task_runner);
+ frame_rate_controller_.reset(new FrameRateController(time_source));
} else {
frame_rate_controller_.reset(new FrameRateController(task_runner));
}
@@ -121,9 +131,9 @@ void OutputSurface::FrameRateControllerTick(bool throttled,
const BeginFrameArgs& args) {
DCHECK(frame_rate_controller_);
if (throttled)
- skipped_begin_frame_args_ = args;
+ skipped_begin_impl_frame_args_ = args;
else
- BeginFrame(args);
+ BeginImplFrame(args);
}
// Forwarded to OutputSurfaceClient
@@ -132,71 +142,74 @@ void OutputSurface::SetNeedsRedrawRect(gfx::Rect damage_rect) {
client_->SetNeedsRedrawRect(damage_rect);
}
-void OutputSurface::SetNeedsBeginFrame(bool enable) {
- TRACE_EVENT1("cc", "OutputSurface::SetNeedsBeginFrame", "enable", enable);
- needs_begin_frame_ = enable;
- client_ready_for_begin_frame_ = true;
+void OutputSurface::SetNeedsBeginImplFrame(bool enable) {
+ TRACE_EVENT1("cc", "OutputSurface::SetNeedsBeginImplFrame", "enable", enable);
+ needs_begin_impl_frame_ = enable;
+ client_ready_for_begin_impl_frame_ = true;
if (frame_rate_controller_) {
BeginFrameArgs skipped = frame_rate_controller_->SetActive(enable);
if (skipped.IsValid())
- skipped_begin_frame_args_ = skipped;
+ skipped_begin_impl_frame_args_ = skipped;
}
- if (needs_begin_frame_)
- PostCheckForRetroactiveBeginFrame();
+ if (needs_begin_impl_frame_)
+ PostCheckForRetroactiveBeginImplFrame();
}
-void OutputSurface::BeginFrame(const BeginFrameArgs& args) {
- TRACE_EVENT2("cc", "OutputSurface::BeginFrame",
- "client_ready_for_begin_frame_", client_ready_for_begin_frame_,
+void OutputSurface::BeginImplFrame(const BeginFrameArgs& args) {
+ TRACE_EVENT2("cc", "OutputSurface::BeginImplFrame",
+ "client_ready_for_begin_impl_frame_",
+ client_ready_for_begin_impl_frame_,
"pending_swap_buffers_", pending_swap_buffers_);
- if (!needs_begin_frame_ || !client_ready_for_begin_frame_ ||
+ if (!needs_begin_impl_frame_ || !client_ready_for_begin_impl_frame_ ||
(pending_swap_buffers_ >= max_frames_pending_ &&
max_frames_pending_ > 0)) {
- skipped_begin_frame_args_ = args;
+ skipped_begin_impl_frame_args_ = args;
} else {
- client_ready_for_begin_frame_ = false;
- client_->BeginFrame(args);
- // args might be an alias for skipped_begin_frame_args_.
- // Do not reset it before calling BeginFrame!
- skipped_begin_frame_args_ = BeginFrameArgs();
+ client_ready_for_begin_impl_frame_ = false;
+ client_->BeginImplFrame(args);
+ // args might be an alias for skipped_begin_impl_frame_args_.
+ // Do not reset it before calling BeginImplFrame!
+ skipped_begin_impl_frame_args_ = BeginFrameArgs();
}
}
-base::TimeTicks OutputSurface::RetroactiveBeginFrameDeadline() {
+base::TimeTicks OutputSurface::RetroactiveBeginImplFrameDeadline() {
// TODO(brianderson): Remove the alternative deadline once we have better
// deadline estimations.
base::TimeTicks alternative_deadline =
- skipped_begin_frame_args_.frame_time +
+ skipped_begin_impl_frame_args_.frame_time +
BeginFrameArgs::DefaultRetroactiveBeginFramePeriod();
- return std::max(skipped_begin_frame_args_.deadline, alternative_deadline);
+ return std::max(skipped_begin_impl_frame_args_.deadline,
+ alternative_deadline);
}
-void OutputSurface::PostCheckForRetroactiveBeginFrame() {
- if (!skipped_begin_frame_args_.IsValid() ||
- check_for_retroactive_begin_frame_pending_)
+void OutputSurface::PostCheckForRetroactiveBeginImplFrame() {
+ if (!skipped_begin_impl_frame_args_.IsValid() ||
+ check_for_retroactive_begin_impl_frame_pending_)
return;
base::MessageLoop::current()->PostTask(
FROM_HERE,
- base::Bind(&OutputSurface::CheckForRetroactiveBeginFrame,
+ base::Bind(&OutputSurface::CheckForRetroactiveBeginImplFrame,
weak_ptr_factory_.GetWeakPtr()));
- check_for_retroactive_begin_frame_pending_ = true;
+ check_for_retroactive_begin_impl_frame_pending_ = true;
}
-void OutputSurface::CheckForRetroactiveBeginFrame() {
- TRACE_EVENT0("cc", "OutputSurface::CheckForRetroactiveBeginFrame");
- check_for_retroactive_begin_frame_pending_ = false;
- if (base::TimeTicks::Now() < RetroactiveBeginFrameDeadline())
- BeginFrame(skipped_begin_frame_args_);
+void OutputSurface::CheckForRetroactiveBeginImplFrame() {
+ TRACE_EVENT0("cc", "OutputSurface::CheckForRetroactiveBeginImplFrame");
+ check_for_retroactive_begin_impl_frame_pending_ = false;
+ if (gfx::FrameTime::Now() < RetroactiveBeginImplFrameDeadline())
+ BeginImplFrame(skipped_begin_impl_frame_args_);
}
void OutputSurface::DidSwapBuffers() {
pending_swap_buffers_++;
TRACE_EVENT1("cc", "OutputSurface::DidSwapBuffers",
"pending_swap_buffers_", pending_swap_buffers_);
+ client_->DidSwapBuffers();
if (frame_rate_controller_)
frame_rate_controller_->DidSwapBuffers();
- PostCheckForRetroactiveBeginFrame();
+ PostCheckForRetroactiveBeginImplFrame();
}
void OutputSurface::OnSwapBuffersComplete() {
@@ -206,7 +219,7 @@ void OutputSurface::OnSwapBuffersComplete() {
client_->OnSwapBuffersComplete();
if (frame_rate_controller_)
frame_rate_controller_->DidSwapBuffersComplete();
- PostCheckForRetroactiveBeginFrame();
+ PostCheckForRetroactiveBeginImplFrame();
}
void OutputSurface::ReclaimResources(const CompositorFrameAck* ack) {
@@ -215,11 +228,13 @@ void OutputSurface::ReclaimResources(const CompositorFrameAck* ack) {
void OutputSurface::DidLoseOutputSurface() {
TRACE_EVENT0("cc", "OutputSurface::DidLoseOutputSurface");
- client_ready_for_begin_frame_ = true;
+ client_ready_for_begin_impl_frame_ = true;
pending_swap_buffers_ = 0;
- skipped_begin_frame_args_ = BeginFrameArgs();
+ skipped_begin_impl_frame_args_ = BeginFrameArgs();
if (frame_rate_controller_)
frame_rate_controller_->SetActive(false);
+ pending_gpu_latency_query_ids_.clear();
+ available_gpu_latency_query_ids_.clear();
client_->DidLoseOutputSurface();
}
@@ -247,7 +262,7 @@ bool OutputSurface::HasExternalStencilTest() const {
bool OutputSurface::ForcedDrawToSoftwareDevice() const { return false; }
-bool OutputSurface::BindToClient(cc::OutputSurfaceClient* client) {
+bool OutputSurface::BindToClient(OutputSurfaceClient* client) {
DCHECK(client);
client_ = client;
bool success = true;
@@ -296,17 +311,12 @@ void OutputSurface::SetUpContext3d() {
DCHECK(context_provider_);
DCHECK(client_);
- const ContextProvider::Capabilities& caps =
- context_provider_->ContextCapabilities();
-
- has_gl_discard_backbuffer_ = caps.discard_backbuffer;
- has_swap_buffers_complete_callback_ = caps.swapbuffers_complete_callback;
-
context_provider_->SetLostContextCallback(
base::Bind(&OutputSurface::DidLoseOutputSurface,
base::Unretained(this)));
- context_provider_->SetSwapBuffersCompleteCallback(base::Bind(
- &OutputSurface::OnSwapBuffersComplete, base::Unretained(this)));
+ context_provider_->ContextSupport()->SetSwapBuffersCompleteCallback(
+ base::Bind(&OutputSurface::OnSwapBuffersComplete,
+ base::Unretained(this)));
context_provider_->SetMemoryPolicyChangedCallback(
base::Bind(&OutputSurface::SetMemoryPolicy,
base::Unretained(this)));
@@ -314,26 +324,34 @@ void OutputSurface::SetUpContext3d() {
void OutputSurface::ResetContext3d() {
if (context_provider_.get()) {
+ while (!pending_gpu_latency_query_ids_.empty()) {
+ unsigned query_id = pending_gpu_latency_query_ids_.front();
+ pending_gpu_latency_query_ids_.pop_front();
+ context_provider_->Context3d()->deleteQueryEXT(query_id);
+ }
+ while (!available_gpu_latency_query_ids_.empty()) {
+ unsigned query_id = available_gpu_latency_query_ids_.front();
+ available_gpu_latency_query_ids_.pop_front();
+ context_provider_->Context3d()->deleteQueryEXT(query_id);
+ }
context_provider_->SetLostContextCallback(
ContextProvider::LostContextCallback());
- context_provider_->SetSwapBuffersCompleteCallback(
- ContextProvider::SwapBuffersCompleteCallback());
context_provider_->SetMemoryPolicyChangedCallback(
ContextProvider::MemoryPolicyChangedCallback());
+ if (gpu::ContextSupport* support = context_provider_->ContextSupport())
+ support->SetSwapBuffersCompleteCallback(base::Closure());
}
context_provider_ = NULL;
}
void OutputSurface::EnsureBackbuffer() {
- if (context_provider_ && has_gl_discard_backbuffer_)
- context_provider_->Context3d()->ensureBackbufferCHROMIUM();
if (software_device_)
software_device_->EnsureBackbuffer();
}
void OutputSurface::DiscardBackbuffer() {
- if (context_provider_ && has_gl_discard_backbuffer_)
- context_provider_->Context3d()->discardBackbufferCHROMIUM();
+ if (context_provider_)
+ context_provider_->ContextGL()->DiscardBackbufferCHROMIUM();
if (software_device_)
software_device_->DiscardBackbuffer();
}
@@ -361,7 +379,7 @@ void OutputSurface::BindFramebuffer() {
context_provider_->Context3d()->bindFramebuffer(GL_FRAMEBUFFER, 0);
}
-void OutputSurface::SwapBuffers(cc::CompositorFrame* frame) {
+void OutputSurface::SwapBuffers(CompositorFrame* frame) {
if (frame->software_frame_data) {
PostSwapBuffersComplete();
DidSwapBuffers();
@@ -371,26 +389,90 @@ void OutputSurface::SwapBuffers(cc::CompositorFrame* frame) {
DCHECK(context_provider_);
DCHECK(frame->gl_frame_data);
+ UpdateAndMeasureGpuLatency();
if (frame->gl_frame_data->sub_buffer_rect ==
gfx::Rect(frame->gl_frame_data->size)) {
- // Note that currently this has the same effect as SwapBuffers; we should
- // consider exposing a different entry point on WebGraphicsContext3D.
- context_provider_->Context3d()->prepareTexture();
+ context_provider_->ContextSupport()->Swap();
} else {
- gfx::Rect sub_buffer_rect = frame->gl_frame_data->sub_buffer_rect;
- context_provider_->Context3d()->postSubBufferCHROMIUM(
- sub_buffer_rect.x(),
- sub_buffer_rect.y(),
- sub_buffer_rect.width(),
- sub_buffer_rect.height());
+ context_provider_->ContextSupport()->PartialSwapBuffers(
+ frame->gl_frame_data->sub_buffer_rect);
}
- if (!has_swap_buffers_complete_callback_)
- PostSwapBuffersComplete();
-
DidSwapBuffers();
}
+base::TimeDelta OutputSurface::GpuLatencyEstimate() {
+ if (context_provider_ && !capabilities_.adjust_deadline_for_parent)
+ return gpu_latency_history_.Percentile(kGpuLatencyEstimationPercentile);
+ else
+ return base::TimeDelta();
+}
+
+void OutputSurface::UpdateAndMeasureGpuLatency() {
+ return; // http://crbug.com/306690 tracks re-enabling latency queries.
+
+ // We only care about GPU latency for surfaces that do not have a parent
+ // compositor, since surfaces that do have a parent compositor can use
+ // mailboxes or delegated rendering to send frames to their parent without
+ // incurring GPU latency.
+ if (capabilities_.adjust_deadline_for_parent)
+ return;
+
+ while (pending_gpu_latency_query_ids_.size()) {
+ unsigned query_id = pending_gpu_latency_query_ids_.front();
+ unsigned query_complete = 1;
+ context_provider_->Context3d()->getQueryObjectuivEXT(
+ query_id, GL_QUERY_RESULT_AVAILABLE_EXT, &query_complete);
+ if (!query_complete)
+ break;
+
+ unsigned value = 0;
+ context_provider_->Context3d()->getQueryObjectuivEXT(
+ query_id, GL_QUERY_RESULT_EXT, &value);
+ pending_gpu_latency_query_ids_.pop_front();
+ available_gpu_latency_query_ids_.push_back(query_id);
+
+ base::TimeDelta latency = base::TimeDelta::FromMicroseconds(value);
+ base::TimeDelta latency_estimate = GpuLatencyEstimate();
+ gpu_latency_history_.InsertSample(latency);
+
+ base::TimeDelta latency_overestimate;
+ base::TimeDelta latency_underestimate;
+ if (latency > latency_estimate)
+ latency_underestimate = latency - latency_estimate;
+ else
+ latency_overestimate = latency_estimate - latency;
+ UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.GpuLatency",
+ latency,
+ base::TimeDelta::FromMilliseconds(1),
+ base::TimeDelta::FromMilliseconds(100),
+ 50);
+ UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.GpuLatencyUnderestimate",
+ latency_underestimate,
+ base::TimeDelta::FromMilliseconds(1),
+ base::TimeDelta::FromMilliseconds(100),
+ 50);
+ UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.GpuLatencyOverestimate",
+ latency_overestimate,
+ base::TimeDelta::FromMilliseconds(1),
+ base::TimeDelta::FromMilliseconds(100),
+ 50);
+ }
+
+ unsigned gpu_latency_query_id;
+ if (available_gpu_latency_query_ids_.size()) {
+ gpu_latency_query_id = available_gpu_latency_query_ids_.front();
+ available_gpu_latency_query_ids_.pop_front();
+ } else {
+ gpu_latency_query_id = context_provider_->Context3d()->createQueryEXT();
+ }
+
+ context_provider_->Context3d()->beginQueryEXT(GL_LATENCY_QUERY_CHROMIUM,
+ gpu_latency_query_id);
+ context_provider_->Context3d()->endQueryEXT(GL_LATENCY_QUERY_CHROMIUM);
+ pending_gpu_latency_query_ids_.push_back(gpu_latency_query_id);
+}
+
void OutputSurface::PostSwapBuffersComplete() {
base::MessageLoop::current()->PostTask(
FROM_HERE,
@@ -398,17 +480,14 @@ void OutputSurface::PostSwapBuffersComplete() {
weak_ptr_factory_.GetWeakPtr()));
}
-void OutputSurface::SetMemoryPolicy(const ManagedMemoryPolicy& policy,
- bool discard_backbuffer) {
- TRACE_EVENT2("cc", "OutputSurface::SetMemoryPolicy",
- "bytes_limit_when_visible", policy.bytes_limit_when_visible,
- "discard_backbuffer", discard_backbuffer);
+void OutputSurface::SetMemoryPolicy(const ManagedMemoryPolicy& policy) {
+ TRACE_EVENT1("cc", "OutputSurface::SetMemoryPolicy",
+ "bytes_limit_when_visible", policy.bytes_limit_when_visible);
// Just ignore the memory manager when it says to set the limit to zero
// bytes. This will happen when the memory manager thinks that the renderer
// is not visible (which the renderer knows better).
if (policy.bytes_limit_when_visible)
client_->SetMemoryPolicy(policy);
- client_->SetDiscardBackBufferWhenNotVisible(discard_backbuffer);
}
} // namespace cc
diff --git a/chromium/cc/output/output_surface.h b/chromium/cc/output/output_surface.h
index 13db5faa06b..0d7d4e7fb96 100644
--- a/chromium/cc/output/output_surface.h
+++ b/chromium/cc/output/output_surface.h
@@ -5,6 +5,8 @@
#ifndef CC_OUTPUT_OUTPUT_SURFACE_H_
#define CC_OUTPUT_OUTPUT_SURFACE_H_
+#include <deque>
+
#include "base/basictypes.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
@@ -13,6 +15,7 @@
#include "cc/output/context_provider.h"
#include "cc/output/software_output_device.h"
#include "cc/scheduler/frame_rate_controller.h"
+#include "cc/scheduler/rolling_time_delta_history.h"
namespace base { class SingleThreadTaskRunner; }
@@ -46,10 +49,10 @@ class CC_EXPORT OutputSurface : public FrameRateControllerClient {
explicit OutputSurface(scoped_refptr<ContextProvider> context_provider);
- explicit OutputSurface(scoped_ptr<cc::SoftwareOutputDevice> software_device);
+ explicit OutputSurface(scoped_ptr<SoftwareOutputDevice> software_device);
OutputSurface(scoped_refptr<ContextProvider> context_provider,
- scoped_ptr<cc::SoftwareOutputDevice> software_device);
+ scoped_ptr<SoftwareOutputDevice> software_device);
virtual ~OutputSurface();
@@ -65,7 +68,7 @@ class CC_EXPORT OutputSurface : public FrameRateControllerClient {
int max_frames_pending;
bool deferred_gl_initialization;
bool draw_and_swap_full_viewport_every_frame;
- // This doesn't handle the <webview> case, but once BeginFrame is
+ // This doesn't handle the <webview> case, but once BeginImplFrame is
// supported natively, we shouldn't need adjust_deadline_for_parent.
bool adjust_deadline_for_parent;
// Whether this output surface renders to the default OpenGL zero
@@ -101,7 +104,7 @@ class CC_EXPORT OutputSurface : public FrameRateControllerClient {
// thread.
virtual bool BindToClient(OutputSurfaceClient* client);
- void InitializeBeginFrameEmulation(
+ void InitializeBeginImplFrameEmulation(
base::SingleThreadTaskRunner* task_runner,
bool throttle_frame_production,
base::TimeDelta interval);
@@ -125,18 +128,22 @@ class CC_EXPORT OutputSurface : public FrameRateControllerClient {
// processing should be stopped, or lowered in priority.
virtual void UpdateSmoothnessTakesPriority(bool prefer_smoothness) {}
- // Requests a BeginFrame notification from the output surface. The
+ // Requests a BeginImplFrame notification from the output surface. The
// notification will be delivered by calling
- // OutputSurfaceClient::BeginFrame until the callback is disabled.
- virtual void SetNeedsBeginFrame(bool enable);
+ // OutputSurfaceClient::BeginImplFrame until the callback is disabled.
+ virtual void SetNeedsBeginImplFrame(bool enable);
bool HasClient() { return !!client_; }
+ // Returns an estimate of the current GPU latency. When only a software
+ // device is present, returns 0.
+ base::TimeDelta GpuLatencyEstimate();
+
protected:
// Synchronously initialize context3d and enter hardware mode.
// This can only supported in threaded compositing mode.
// |offscreen_context_provider| should match what is returned by
- // LayerTreeClient::OffscreenContextProviderForCompositorThread.
+ // LayerTreeClient::OffscreenContextProvider().
bool InitializeAndSetContext3d(
scoped_refptr<ContextProvider> context_provider,
scoped_refptr<ContextProvider> offscreen_context_provider);
@@ -144,17 +151,14 @@ class CC_EXPORT OutputSurface : public FrameRateControllerClient {
void PostSwapBuffersComplete();
- struct cc::OutputSurface::Capabilities capabilities_;
+ struct OutputSurface::Capabilities capabilities_;
scoped_refptr<ContextProvider> context_provider_;
- scoped_ptr<cc::SoftwareOutputDevice> software_device_;
- bool has_gl_discard_backbuffer_;
- bool has_swap_buffers_complete_callback_;
+ scoped_ptr<SoftwareOutputDevice> software_device_;
gfx::Size surface_size_;
float device_scale_factor_;
- base::WeakPtrFactory<OutputSurface> weak_ptr_factory_;
// The FrameRateController is deprecated.
- // Platforms should move to native BeginFrames instead.
+ // Platforms should move to native BeginImplFrames instead.
void OnVSyncParametersChanged(base::TimeTicks timebase,
base::TimeDelta interval);
virtual void FrameRateControllerTick(bool throttled,
@@ -162,17 +166,17 @@ class CC_EXPORT OutputSurface : public FrameRateControllerClient {
scoped_ptr<FrameRateController> frame_rate_controller_;
int max_frames_pending_;
int pending_swap_buffers_;
- bool needs_begin_frame_;
- bool client_ready_for_begin_frame_;
+ bool needs_begin_impl_frame_;
+ bool client_ready_for_begin_impl_frame_;
- // This stores a BeginFrame that we couldn't process immediately, but might
- // process retroactively in the near future.
- BeginFrameArgs skipped_begin_frame_args_;
+ // This stores a BeginImplFrame that we couldn't process immediately,
+ // but might process retroactively in the near future.
+ BeginFrameArgs skipped_begin_impl_frame_args_;
// Forwarded to OutputSurfaceClient but threaded through OutputSurface
// first so OutputSurface has a chance to update the FrameRateController
void SetNeedsRedrawRect(gfx::Rect damage_rect);
- void BeginFrame(const BeginFrameArgs& args);
+ void BeginImplFrame(const BeginFrameArgs& args);
void DidSwapBuffers();
void OnSwapBuffersComplete();
void ReclaimResources(const CompositorFrameAck* ack);
@@ -184,25 +188,30 @@ class CC_EXPORT OutputSurface : public FrameRateControllerClient {
bool valid_for_tile_management);
// virtual for testing.
- virtual base::TimeTicks RetroactiveBeginFrameDeadline();
- virtual void PostCheckForRetroactiveBeginFrame();
- void CheckForRetroactiveBeginFrame();
+ virtual base::TimeTicks RetroactiveBeginImplFrameDeadline();
+ virtual void PostCheckForRetroactiveBeginImplFrame();
+ void CheckForRetroactiveBeginImplFrame();
private:
OutputSurfaceClient* client_;
- friend class OutputSurfaceCallbacks;
void SetUpContext3d();
void ResetContext3d();
- void SetMemoryPolicy(const ManagedMemoryPolicy& policy,
- bool discard_backbuffer_when_not_visible);
+ void SetMemoryPolicy(const ManagedMemoryPolicy& policy);
+ void UpdateAndMeasureGpuLatency();
- // check_for_retroactive_begin_frame_pending_ is used to avoid posting
- // redundant checks for a retroactive BeginFrame.
- bool check_for_retroactive_begin_frame_pending_;
+ // check_for_retroactive_begin_impl_frame_pending_ is used to avoid posting
+ // redundant checks for a retroactive BeginImplFrame.
+ bool check_for_retroactive_begin_impl_frame_pending_;
bool external_stencil_test_enabled_;
+ base::WeakPtrFactory<OutputSurface> weak_ptr_factory_;
+
+ std::deque<unsigned> available_gpu_latency_query_ids_;
+ std::deque<unsigned> pending_gpu_latency_query_ids_;
+ RollingTimeDeltaHistory gpu_latency_history_;
+
DISALLOW_COPY_AND_ASSIGN(OutputSurface);
};
diff --git a/chromium/cc/output/output_surface_client.h b/chromium/cc/output/output_surface_client.h
index c0e2e4554b5..d82f30df499 100644
--- a/chromium/cc/output/output_surface_client.h
+++ b/chromium/cc/output/output_surface_client.h
@@ -31,7 +31,8 @@ class CC_EXPORT OutputSurfaceClient {
scoped_refptr<ContextProvider> offscreen_context_provider) = 0;
virtual void ReleaseGL() = 0;
virtual void SetNeedsRedrawRect(gfx::Rect damage_rect) = 0;
- virtual void BeginFrame(const BeginFrameArgs& args) = 0;
+ virtual void BeginImplFrame(const BeginFrameArgs& args) = 0;
+ virtual void DidSwapBuffers() = 0;
virtual void OnSwapBuffersComplete() = 0;
virtual void ReclaimResources(const CompositorFrameAck* ack) = 0;
virtual void DidLoseOutputSurface() = 0;
@@ -39,7 +40,6 @@ class CC_EXPORT OutputSurfaceClient {
gfx::Rect viewport,
gfx::Rect clip,
bool valid_for_tile_management) = 0;
- virtual void SetDiscardBackBufferWhenNotVisible(bool discard) = 0;
virtual void SetMemoryPolicy(const ManagedMemoryPolicy& policy) = 0;
// If set, |callback| will be called subsequent to each new tree activation,
// regardless of the compositor visibility or damage. |callback| must remain
diff --git a/chromium/cc/output/output_surface_unittest.cc b/chromium/cc/output/output_surface_unittest.cc
index 91e7c39d0b1..551ec595593 100644
--- a/chromium/cc/output/output_surface_unittest.cc
+++ b/chromium/cc/output/output_surface_unittest.cc
@@ -5,16 +5,17 @@
#include "cc/output/output_surface.h"
#include "base/test/test_simple_task_runner.h"
-#include "cc/debug/test_context_provider.h"
-#include "cc/debug/test_web_graphics_context_3d.h"
#include "cc/output/managed_memory_policy.h"
#include "cc/output/output_surface_client.h"
#include "cc/output/software_output_device.h"
#include "cc/test/fake_output_surface.h"
#include "cc/test/fake_output_surface_client.h"
#include "cc/test/scheduler_test_common.h"
+#include "cc/test/test_context_provider.h"
+#include "cc/test/test_web_graphics_context_3d.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/frame_time.h"
namespace cc {
namespace {
@@ -23,19 +24,18 @@ class TestOutputSurface : public OutputSurface {
public:
explicit TestOutputSurface(scoped_refptr<ContextProvider> context_provider)
: OutputSurface(context_provider),
- retroactive_begin_frame_deadline_enabled_(false),
+ retroactive_begin_impl_frame_deadline_enabled_(false),
override_retroactive_period_(false) {}
- explicit TestOutputSurface(
- scoped_ptr<cc::SoftwareOutputDevice> software_device)
+ explicit TestOutputSurface(scoped_ptr<SoftwareOutputDevice> software_device)
: OutputSurface(software_device.Pass()),
- retroactive_begin_frame_deadline_enabled_(false),
+ retroactive_begin_impl_frame_deadline_enabled_(false),
override_retroactive_period_(false) {}
TestOutputSurface(scoped_refptr<ContextProvider> context_provider,
- scoped_ptr<cc::SoftwareOutputDevice> software_device)
+ scoped_ptr<SoftwareOutputDevice> software_device)
: OutputSurface(context_provider, software_device.Pass()),
- retroactive_begin_frame_deadline_enabled_(false),
+ retroactive_begin_impl_frame_deadline_enabled_(false),
override_retroactive_period_(false) {}
bool InitializeNewContext3d(
@@ -51,8 +51,8 @@ class TestOutputSurface : public OutputSurface {
OnVSyncParametersChanged(timebase, interval);
}
- void BeginFrameForTesting() {
- OutputSurface::BeginFrame(BeginFrameArgs::CreateExpiredForTesting());
+ void BeginImplFrameForTesting() {
+ OutputSurface::BeginImplFrame(BeginFrameArgs::CreateExpiredForTesting());
}
void DidSwapBuffersForTesting() {
@@ -67,33 +67,34 @@ class TestOutputSurface : public OutputSurface {
OnSwapBuffersComplete();
}
- void EnableRetroactiveBeginFrameDeadline(bool enable,
- bool override_retroactive_period,
- base::TimeDelta period_override) {
- retroactive_begin_frame_deadline_enabled_ = enable;
+ void EnableRetroactiveBeginImplFrameDeadline(
+ bool enable,
+ bool override_retroactive_period,
+ base::TimeDelta period_override) {
+ retroactive_begin_impl_frame_deadline_enabled_ = enable;
override_retroactive_period_ = override_retroactive_period;
retroactive_period_override_ = period_override;
}
protected:
- virtual void PostCheckForRetroactiveBeginFrame() OVERRIDE {
+ virtual void PostCheckForRetroactiveBeginImplFrame() OVERRIDE {
// For testing purposes, we check immediately rather than posting a task.
- CheckForRetroactiveBeginFrame();
+ CheckForRetroactiveBeginImplFrame();
}
- virtual base::TimeTicks RetroactiveBeginFrameDeadline() OVERRIDE {
- if (retroactive_begin_frame_deadline_enabled_) {
+ virtual base::TimeTicks RetroactiveBeginImplFrameDeadline() OVERRIDE {
+ if (retroactive_begin_impl_frame_deadline_enabled_) {
if (override_retroactive_period_) {
- return skipped_begin_frame_args_.frame_time +
+ return skipped_begin_impl_frame_args_.frame_time +
retroactive_period_override_;
} else {
- return OutputSurface::RetroactiveBeginFrameDeadline();
+ return OutputSurface::RetroactiveBeginImplFrameDeadline();
}
}
return base::TimeTicks();
}
- bool retroactive_begin_frame_deadline_enabled_;
+ bool retroactive_begin_impl_frame_deadline_enabled_;
bool override_retroactive_period_;
base::TimeDelta retroactive_period_override_;
};
@@ -151,7 +152,7 @@ TEST(OutputSurfaceTest, ClientPointerIndicatesBindToClientFailure) {
TestContextProvider::Create();
// Lose the context so BindToClient fails.
- context_provider->UnboundTestContext3d()->set_times_make_current_succeeds(0);
+ context_provider->UnboundTestContext3d()->set_context_lost(true);
TestOutputSurface output_surface(context_provider);
EXPECT_FALSE(output_surface.HasClient());
@@ -207,8 +208,7 @@ TEST_F(OutputSurfaceTestInitializeNewContext3d, Success) {
TEST_F(OutputSurfaceTestInitializeNewContext3d, Context3dMakeCurrentFails) {
BindOutputSurface();
- context_provider_->UnboundTestContext3d()
- ->set_times_make_current_succeeds(0);
+ context_provider_->UnboundTestContext3d()->set_context_lost(true);
InitializeNewContextExpectFail();
}
@@ -218,7 +218,7 @@ TEST_F(OutputSurfaceTestInitializeNewContext3d, ClientDeferredInitializeFails) {
InitializeNewContextExpectFail();
}
-TEST(OutputSurfaceTest, BeginFrameEmulation) {
+TEST(OutputSurfaceTest, BeginImplFrameEmulation) {
TestOutputSurface output_surface(TestContextProvider::Create());
EXPECT_FALSE(output_surface.HasClient());
@@ -227,84 +227,86 @@ TEST(OutputSurfaceTest, BeginFrameEmulation) {
EXPECT_TRUE(output_surface.HasClient());
EXPECT_FALSE(client.deferred_initialize_called());
- // Initialize BeginFrame emulation
+ // Initialize BeginImplFrame emulation
scoped_refptr<base::TestSimpleTaskRunner> task_runner =
new base::TestSimpleTaskRunner;
bool throttle_frame_production = true;
const base::TimeDelta display_refresh_interval =
BeginFrameArgs::DefaultInterval();
- output_surface.InitializeBeginFrameEmulation(
+ output_surface.InitializeBeginImplFrameEmulation(
task_runner.get(),
throttle_frame_production,
display_refresh_interval);
output_surface.SetMaxFramesPending(2);
- output_surface.EnableRetroactiveBeginFrameDeadline(
+ output_surface.EnableRetroactiveBeginImplFrameDeadline(
false, false, base::TimeDelta());
- // We should start off with 0 BeginFrames
- EXPECT_EQ(client.begin_frame_count(), 0);
+ // We should start off with 0 BeginImplFrames
+ EXPECT_EQ(client.begin_impl_frame_count(), 0);
EXPECT_EQ(output_surface.pending_swap_buffers(), 0);
- // We should not have a pending task until a BeginFrame has been requested.
+ // We should not have a pending task until a BeginImplFrame has been
+ // requested.
EXPECT_FALSE(task_runner->HasPendingTask());
- output_surface.SetNeedsBeginFrame(true);
+ output_surface.SetNeedsBeginImplFrame(true);
EXPECT_TRUE(task_runner->HasPendingTask());
- // BeginFrame should be called on the first tick.
+ // BeginImplFrame should be called on the first tick.
task_runner->RunPendingTasks();
- EXPECT_EQ(client.begin_frame_count(), 1);
+ EXPECT_EQ(client.begin_impl_frame_count(), 1);
EXPECT_EQ(output_surface.pending_swap_buffers(), 0);
- // BeginFrame should not be called when there is a pending BeginFrame.
+ // BeginImplFrame should not be called when there is a pending BeginImplFrame.
task_runner->RunPendingTasks();
- EXPECT_EQ(client.begin_frame_count(), 1);
+ EXPECT_EQ(client.begin_impl_frame_count(), 1);
EXPECT_EQ(output_surface.pending_swap_buffers(), 0);
- // SetNeedsBeginFrame should clear the pending BeginFrame after
+ // SetNeedsBeginImplFrame should clear the pending BeginImplFrame after
// a SwapBuffers.
output_surface.DidSwapBuffersForTesting();
- output_surface.SetNeedsBeginFrame(true);
- EXPECT_EQ(client.begin_frame_count(), 1);
+ output_surface.SetNeedsBeginImplFrame(true);
+ EXPECT_EQ(client.begin_impl_frame_count(), 1);
EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
task_runner->RunPendingTasks();
- EXPECT_EQ(client.begin_frame_count(), 2);
+ EXPECT_EQ(client.begin_impl_frame_count(), 2);
EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
- // BeginFrame should be throttled by pending swap buffers.
+ // BeginImplFrame should be throttled by pending swap buffers.
output_surface.DidSwapBuffersForTesting();
- output_surface.SetNeedsBeginFrame(true);
- EXPECT_EQ(client.begin_frame_count(), 2);
+ output_surface.SetNeedsBeginImplFrame(true);
+ EXPECT_EQ(client.begin_impl_frame_count(), 2);
EXPECT_EQ(output_surface.pending_swap_buffers(), 2);
task_runner->RunPendingTasks();
- EXPECT_EQ(client.begin_frame_count(), 2);
+ EXPECT_EQ(client.begin_impl_frame_count(), 2);
EXPECT_EQ(output_surface.pending_swap_buffers(), 2);
- // SwapAck should decrement pending swap buffers and unblock BeginFrame again.
+ // SwapAck should decrement pending swap buffers and unblock BeginImplFrame
+ // again.
output_surface.OnSwapBuffersCompleteForTesting();
- EXPECT_EQ(client.begin_frame_count(), 2);
+ EXPECT_EQ(client.begin_impl_frame_count(), 2);
EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
task_runner->RunPendingTasks();
- EXPECT_EQ(client.begin_frame_count(), 3);
+ EXPECT_EQ(client.begin_impl_frame_count(), 3);
EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
- // Calling SetNeedsBeginFrame again indicates a swap did not occur but
- // the client still wants another BeginFrame.
- output_surface.SetNeedsBeginFrame(true);
+ // Calling SetNeedsBeginImplFrame again indicates a swap did not occur but
+ // the client still wants another BeginImplFrame.
+ output_surface.SetNeedsBeginImplFrame(true);
task_runner->RunPendingTasks();
- EXPECT_EQ(client.begin_frame_count(), 4);
+ EXPECT_EQ(client.begin_impl_frame_count(), 4);
EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
- // Disabling SetNeedsBeginFrame should prevent further BeginFrames.
- output_surface.SetNeedsBeginFrame(false);
+ // Disabling SetNeedsBeginImplFrame should prevent further BeginImplFrames.
+ output_surface.SetNeedsBeginImplFrame(false);
task_runner->RunPendingTasks();
EXPECT_FALSE(task_runner->HasPendingTask());
- EXPECT_EQ(client.begin_frame_count(), 4);
+ EXPECT_EQ(client.begin_impl_frame_count(), 4);
EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
}
-TEST(OutputSurfaceTest, OptimisticAndRetroactiveBeginFrames) {
+TEST(OutputSurfaceTest, OptimisticAndRetroactiveBeginImplFrames) {
TestOutputSurface output_surface(TestContextProvider::Create());
EXPECT_FALSE(output_surface.HasClient());
@@ -314,47 +316,48 @@ TEST(OutputSurfaceTest, OptimisticAndRetroactiveBeginFrames) {
EXPECT_FALSE(client.deferred_initialize_called());
output_surface.SetMaxFramesPending(2);
- output_surface.EnableRetroactiveBeginFrameDeadline(
+ output_surface.EnableRetroactiveBeginImplFrameDeadline(
true, false, base::TimeDelta());
- // Optimistically injected BeginFrames should be throttled if
- // SetNeedsBeginFrame is false...
- output_surface.SetNeedsBeginFrame(false);
- output_surface.BeginFrameForTesting();
- EXPECT_EQ(client.begin_frame_count(), 0);
- // ...and retroactively triggered by a SetNeedsBeginFrame.
- output_surface.SetNeedsBeginFrame(true);
- EXPECT_EQ(client.begin_frame_count(), 1);
-
- // Optimistically injected BeginFrames should be throttled by pending
- // BeginFrames...
- output_surface.BeginFrameForTesting();
- EXPECT_EQ(client.begin_frame_count(), 1);
- // ...and retroactively triggered by a SetNeedsBeginFrame.
- output_surface.SetNeedsBeginFrame(true);
- EXPECT_EQ(client.begin_frame_count(), 2);
+ // Optimistically injected BeginImplFrames should be throttled if
+ // SetNeedsBeginImplFrame is false...
+ output_surface.SetNeedsBeginImplFrame(false);
+ output_surface.BeginImplFrameForTesting();
+ EXPECT_EQ(client.begin_impl_frame_count(), 0);
+ // ...and retroactively triggered by a SetNeedsBeginImplFrame.
+ output_surface.SetNeedsBeginImplFrame(true);
+ EXPECT_EQ(client.begin_impl_frame_count(), 1);
+
+ // Optimistically injected BeginImplFrames should be throttled by pending
+ // BeginImplFrames...
+ output_surface.BeginImplFrameForTesting();
+ EXPECT_EQ(client.begin_impl_frame_count(), 1);
+ // ...and retroactively triggered by a SetNeedsBeginImplFrame.
+ output_surface.SetNeedsBeginImplFrame(true);
+ EXPECT_EQ(client.begin_impl_frame_count(), 2);
// ...or retroactively triggered by a Swap.
- output_surface.BeginFrameForTesting();
- EXPECT_EQ(client.begin_frame_count(), 2);
+ output_surface.BeginImplFrameForTesting();
+ EXPECT_EQ(client.begin_impl_frame_count(), 2);
output_surface.DidSwapBuffersForTesting();
- output_surface.SetNeedsBeginFrame(true);
- EXPECT_EQ(client.begin_frame_count(), 3);
+ output_surface.SetNeedsBeginImplFrame(true);
+ EXPECT_EQ(client.begin_impl_frame_count(), 3);
EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
- // Optimistically injected BeginFrames should be by throttled by pending
+ // Optimistically injected BeginImplFrames should be by throttled by pending
// swap buffers...
output_surface.DidSwapBuffersForTesting();
- output_surface.SetNeedsBeginFrame(true);
- EXPECT_EQ(client.begin_frame_count(), 3);
+ output_surface.SetNeedsBeginImplFrame(true);
+ EXPECT_EQ(client.begin_impl_frame_count(), 3);
EXPECT_EQ(output_surface.pending_swap_buffers(), 2);
- output_surface.BeginFrameForTesting();
- EXPECT_EQ(client.begin_frame_count(), 3);
+ output_surface.BeginImplFrameForTesting();
+ EXPECT_EQ(client.begin_impl_frame_count(), 3);
// ...and retroactively triggered by OnSwapBuffersComplete
output_surface.OnSwapBuffersCompleteForTesting();
- EXPECT_EQ(client.begin_frame_count(), 4);
+ EXPECT_EQ(client.begin_impl_frame_count(), 4);
}
-TEST(OutputSurfaceTest, RetroactiveBeginFrameDoesNotDoubleTickWhenEmulating) {
+TEST(OutputSurfaceTest,
+ RetroactiveBeginImplFrameDoesNotDoubleTickWhenEmulating) {
scoped_refptr<TestContextProvider> context_provider =
TestContextProvider::Create();
@@ -368,13 +371,13 @@ TEST(OutputSurfaceTest, RetroactiveBeginFrameDoesNotDoubleTickWhenEmulating) {
base::TimeDelta big_interval = base::TimeDelta::FromSeconds(10);
- // Initialize BeginFrame emulation
+ // Initialize BeginImplFrame emulation
scoped_refptr<base::TestSimpleTaskRunner> task_runner =
new base::TestSimpleTaskRunner;
bool throttle_frame_production = true;
const base::TimeDelta display_refresh_interval = big_interval;
- output_surface.InitializeBeginFrameEmulation(
+ output_surface.InitializeBeginImplFrameEmulation(
task_runner.get(),
throttle_frame_production,
display_refresh_interval);
@@ -382,31 +385,34 @@ TEST(OutputSurfaceTest, RetroactiveBeginFrameDoesNotDoubleTickWhenEmulating) {
// We need to subtract an epsilon from Now() because some platforms have
// a slow clock.
output_surface.OnVSyncParametersChangedForTesting(
- base::TimeTicks::Now() - base::TimeDelta::FromSeconds(1), big_interval);
+ gfx::FrameTime::Now() - base::TimeDelta::FromSeconds(1), big_interval);
output_surface.SetMaxFramesPending(2);
- output_surface.EnableRetroactiveBeginFrameDeadline(true, true, big_interval);
+ output_surface.EnableRetroactiveBeginImplFrameDeadline(
+ true, true, big_interval);
- // We should start off with 0 BeginFrames
- EXPECT_EQ(client.begin_frame_count(), 0);
+ // We should start off with 0 BeginImplFrames
+ EXPECT_EQ(client.begin_impl_frame_count(), 0);
EXPECT_EQ(output_surface.pending_swap_buffers(), 0);
- // The first SetNeedsBeginFrame(true) should start a retroactive BeginFrame.
+ // The first SetNeedsBeginImplFrame(true) should start a retroactive
+ // BeginImplFrame.
EXPECT_FALSE(task_runner->HasPendingTask());
- output_surface.SetNeedsBeginFrame(true);
+ output_surface.SetNeedsBeginImplFrame(true);
EXPECT_TRUE(task_runner->HasPendingTask());
EXPECT_GT(task_runner->NextPendingTaskDelay(), big_interval / 2);
- EXPECT_EQ(client.begin_frame_count(), 1);
+ EXPECT_EQ(client.begin_impl_frame_count(), 1);
- output_surface.SetNeedsBeginFrame(false);
+ output_surface.SetNeedsBeginImplFrame(false);
EXPECT_TRUE(task_runner->HasPendingTask());
- EXPECT_EQ(client.begin_frame_count(), 1);
+ EXPECT_EQ(client.begin_impl_frame_count(), 1);
- // The second SetNeedBeginFrame(true) should not retroactively start a
- // BeginFrame if the timestamp would be the same as the previous BeginFrame.
- output_surface.SetNeedsBeginFrame(true);
+ // The second SetNeedBeginImplFrame(true) should not retroactively start a
+ // BeginImplFrame if the timestamp would be the same as the previous
+ // BeginImplFrame.
+ output_surface.SetNeedsBeginImplFrame(true);
EXPECT_TRUE(task_runner->HasPendingTask());
- EXPECT_EQ(client.begin_frame_count(), 1);
+ EXPECT_EQ(client.begin_impl_frame_count(), 1);
}
TEST(OutputSurfaceTest, MemoryAllocation) {
@@ -421,43 +427,22 @@ TEST(OutputSurfaceTest, MemoryAllocation) {
ManagedMemoryPolicy policy(0);
policy.bytes_limit_when_visible = 1234;
policy.priority_cutoff_when_visible =
- ManagedMemoryPolicy::CUTOFF_ALLOW_REQUIRED_ONLY;
- policy.bytes_limit_when_not_visible = 4567;
- policy.priority_cutoff_when_not_visible =
- ManagedMemoryPolicy::CUTOFF_ALLOW_NOTHING;
+ gpu::MemoryAllocation::CUTOFF_ALLOW_REQUIRED_ONLY;
- bool discard_backbuffer_when_not_visible = false;
-
- context_provider->SetMemoryAllocation(policy,
- discard_backbuffer_when_not_visible);
+ context_provider->SetMemoryAllocation(policy);
EXPECT_EQ(1234u, client.memory_policy().bytes_limit_when_visible);
- EXPECT_EQ(ManagedMemoryPolicy::CUTOFF_ALLOW_REQUIRED_ONLY,
+ EXPECT_EQ(gpu::MemoryAllocation::CUTOFF_ALLOW_REQUIRED_ONLY,
client.memory_policy().priority_cutoff_when_visible);
- EXPECT_EQ(4567u, client.memory_policy().bytes_limit_when_not_visible);
- EXPECT_EQ(ManagedMemoryPolicy::CUTOFF_ALLOW_NOTHING,
- client.memory_policy().priority_cutoff_when_not_visible);
- EXPECT_FALSE(client.discard_backbuffer_when_not_visible());
-
- discard_backbuffer_when_not_visible = true;
- context_provider->SetMemoryAllocation(policy,
- discard_backbuffer_when_not_visible);
- EXPECT_TRUE(client.discard_backbuffer_when_not_visible());
policy.priority_cutoff_when_visible =
- ManagedMemoryPolicy::CUTOFF_ALLOW_EVERYTHING;
- policy.priority_cutoff_when_not_visible =
- ManagedMemoryPolicy::CUTOFF_ALLOW_NICE_TO_HAVE;
- context_provider->SetMemoryAllocation(policy,
- discard_backbuffer_when_not_visible);
- EXPECT_EQ(ManagedMemoryPolicy::CUTOFF_ALLOW_EVERYTHING,
+ gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING;
+ context_provider->SetMemoryAllocation(policy);
+ EXPECT_EQ(gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING,
client.memory_policy().priority_cutoff_when_visible);
- EXPECT_EQ(ManagedMemoryPolicy::CUTOFF_ALLOW_NICE_TO_HAVE,
- client.memory_policy().priority_cutoff_when_not_visible);
// 0 bytes limit should be ignored.
policy.bytes_limit_when_visible = 0;
- context_provider->SetMemoryAllocation(policy,
- discard_backbuffer_when_not_visible);
+ context_provider->SetMemoryAllocation(policy);
EXPECT_EQ(1234u, client.memory_policy().bytes_limit_when_visible);
}
diff --git a/chromium/cc/output/program_binding.cc b/chromium/cc/output/program_binding.cc
index 5b7b13ee06d..9152e5acd2c 100644
--- a/chromium/cc/output/program_binding.cc
+++ b/chromium/cc/output/program_binding.cc
@@ -6,11 +6,10 @@
#include "base/debug/trace_event.h"
#include "cc/output/geometry_binding.h"
-#include "cc/output/gl_renderer.h" // For the GLC() macro.
-#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
#include "third_party/khronos/GLES2/gl2.h"
-using WebKit::WebGraphicsContext3D;
+using gpu::gles2::GLES2Interface;
namespace cc {
@@ -28,123 +27,107 @@ ProgramBindingBase::~ProgramBindingBase() {
DCHECK(!initialized_);
}
-void ProgramBindingBase::Init(WebGraphicsContext3D* context,
+bool ProgramBindingBase::Init(GLES2Interface* context,
const std::string& vertex_shader,
const std::string& fragment_shader) {
TRACE_EVENT0("cc", "ProgramBindingBase::init");
vertex_shader_id_ = LoadShader(context, GL_VERTEX_SHADER, vertex_shader);
- if (!vertex_shader_id_) {
- if (!IsContextLost(context))
- LOG(ERROR) << "Failed to create vertex shader";
- return;
- }
+ if (!vertex_shader_id_)
+ return false;
fragment_shader_id_ =
LoadShader(context, GL_FRAGMENT_SHADER, fragment_shader);
if (!fragment_shader_id_) {
- GLC(context, context->deleteShader(vertex_shader_id_));
+ context->DeleteShader(vertex_shader_id_);
vertex_shader_id_ = 0;
- if (!IsContextLost(context))
- LOG(ERROR) << "Failed to create fragment shader";
- return;
+ return false;
}
program_ =
CreateShaderProgram(context, vertex_shader_id_, fragment_shader_id_);
- DCHECK(program_ || IsContextLost(context));
+ return !!program_;
}
-void ProgramBindingBase::Link(WebGraphicsContext3D* context) {
- GLC(context, context->linkProgram(program_));
+bool ProgramBindingBase::Link(GLES2Interface* context) {
+ context->LinkProgram(program_);
CleanupShaders(context);
if (!program_)
- return;
+ return false;
#ifndef NDEBUG
int linked = 0;
- GLC(context, context->getProgramiv(program_, GL_LINK_STATUS, &linked));
- if (!linked) {
- if (!IsContextLost(context))
- LOG(ERROR) << "Failed to link shader program";
- GLC(context, context->deleteProgram(program_));
- }
+ context->GetProgramiv(program_, GL_LINK_STATUS, &linked);
+ if (!linked)
+ return false;
#endif
+ return true;
}
-void ProgramBindingBase::Cleanup(WebGraphicsContext3D* context) {
+void ProgramBindingBase::Cleanup(GLES2Interface* context) {
initialized_ = false;
if (!program_)
return;
DCHECK(context);
- GLC(context, context->deleteProgram(program_));
+ context->DeleteProgram(program_);
program_ = 0;
CleanupShaders(context);
}
-unsigned ProgramBindingBase::LoadShader(WebGraphicsContext3D* context,
+unsigned ProgramBindingBase::LoadShader(GLES2Interface* context,
unsigned type,
const std::string& shader_source) {
- unsigned shader = context->createShader(type);
+ unsigned shader = context->CreateShader(type);
if (!shader)
- return 0;
- GLC(context, context->shaderSource(shader, shader_source.data()));
- GLC(context, context->compileShader(shader));
+ return 0u;
+
+ const char* shader_source_str[] = { shader_source.data() };
+ int shader_length[] = { static_cast<int>(shader_source.length()) };
+ context->ShaderSource(
+ shader, 1,
+ shader_source_str,
+ shader_length);
+ context->CompileShader(shader);
#ifndef NDEBUG
int compiled = 0;
- GLC(context, context->getShaderiv(shader, GL_COMPILE_STATUS, &compiled));
- if (!compiled) {
- GLC(context, context->deleteShader(shader));
- return 0;
- }
+ context->GetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
+ if (!compiled)
+ return 0u;
#endif
return shader;
}
-unsigned ProgramBindingBase::CreateShaderProgram(WebGraphicsContext3D* context,
+unsigned ProgramBindingBase::CreateShaderProgram(GLES2Interface* context,
unsigned vertex_shader,
unsigned fragment_shader) {
- unsigned program_object = context->createProgram();
- if (!program_object) {
- if (!IsContextLost(context))
- LOG(ERROR) << "Failed to create shader program";
+ unsigned program_object = context->CreateProgram();
+ if (!program_object)
return 0;
- }
- GLC(context, context->attachShader(program_object, vertex_shader));
- GLC(context, context->attachShader(program_object, fragment_shader));
+ context->AttachShader(program_object, vertex_shader);
+ context->AttachShader(program_object, fragment_shader);
// Bind the common attrib locations.
- GLC(context,
- context->bindAttribLocation(program_object,
- GeometryBinding::PositionAttribLocation(),
- "a_position"));
- GLC(context,
- context->bindAttribLocation(program_object,
- GeometryBinding::TexCoordAttribLocation(),
- "a_texCoord"));
- GLC(context,
- context->bindAttribLocation(
- program_object,
- GeometryBinding::TriangleIndexAttribLocation(),
- "a_index"));
+ context->BindAttribLocation(
+ program_object, GeometryBinding::PositionAttribLocation(), "a_position");
+ context->BindAttribLocation(
+ program_object, GeometryBinding::TexCoordAttribLocation(), "a_texCoord");
+ context->BindAttribLocation(program_object,
+ GeometryBinding::TriangleIndexAttribLocation(),
+ "a_index");
return program_object;
}
-void ProgramBindingBase::CleanupShaders(WebGraphicsContext3D* context) {
+void ProgramBindingBase::CleanupShaders(GLES2Interface* context) {
if (vertex_shader_id_) {
- GLC(context, context->deleteShader(vertex_shader_id_));
+ context->DeleteShader(vertex_shader_id_);
vertex_shader_id_ = 0;
}
if (fragment_shader_id_) {
- GLC(context, context->deleteShader(fragment_shader_id_));
+ context->DeleteShader(fragment_shader_id_);
fragment_shader_id_ = 0;
}
}
-bool ProgramBindingBase::IsContextLost(WebGraphicsContext3D* context) {
- return (context->getGraphicsResetStatusARB() != GL_NO_ERROR);
-}
-
} // namespace cc
diff --git a/chromium/cc/output/program_binding.h b/chromium/cc/output/program_binding.h
index ee9d284fa7f..912329ef6bf 100644
--- a/chromium/cc/output/program_binding.h
+++ b/chromium/cc/output/program_binding.h
@@ -8,9 +8,14 @@
#include <string>
#include "base/logging.h"
+#include "cc/output/context_provider.h"
#include "cc/output/shader.h"
-namespace WebKit { class WebGraphicsContext3D; }
+namespace gpu {
+namespace gles2 {
+class GLES2Interface;
+}
+}
namespace cc {
@@ -19,24 +24,23 @@ class ProgramBindingBase {
ProgramBindingBase();
~ProgramBindingBase();
- void Init(WebKit::WebGraphicsContext3D* context,
+ bool Init(gpu::gles2::GLES2Interface* context,
const std::string& vertex_shader,
const std::string& fragment_shader);
- void Link(WebKit::WebGraphicsContext3D* context);
- void Cleanup(WebKit::WebGraphicsContext3D* context);
+ bool Link(gpu::gles2::GLES2Interface* context);
+ void Cleanup(gpu::gles2::GLES2Interface* context);
unsigned program() const { return program_; }
bool initialized() const { return initialized_; }
protected:
- unsigned LoadShader(WebKit::WebGraphicsContext3D* context,
+ unsigned LoadShader(gpu::gles2::GLES2Interface* context,
unsigned type,
const std::string& shader_source);
- unsigned CreateShaderProgram(WebKit::WebGraphicsContext3D* context,
+ unsigned CreateShaderProgram(gpu::gles2::GLES2Interface* context,
unsigned vertex_shader,
unsigned fragment_shader);
- void CleanupShaders(WebKit::WebGraphicsContext3D* context);
- bool IsContextLost(WebKit::WebGraphicsContext3D* context);
+ void CleanupShaders(gpu::gles2::GLES2Interface* context);
unsigned program_;
unsigned vertex_shader_id_;
@@ -50,35 +54,36 @@ class ProgramBindingBase {
template <class VertexShader, class FragmentShader>
class ProgramBinding : public ProgramBindingBase {
public:
- explicit ProgramBinding(WebKit::WebGraphicsContext3D* context,
- TexCoordPrecision precision) {
- ProgramBindingBase::Init(
- context,
- vertex_shader_.GetShaderString(),
- fragment_shader_.GetShaderString(precision));
- }
+ ProgramBinding() {}
- void Initialize(WebKit::WebGraphicsContext3D* context,
- bool using_bind_uniform) {
- DCHECK(context);
+ void Initialize(ContextProvider* context_provider,
+ TexCoordPrecision precision,
+ SamplerType sampler) {
+ DCHECK(context_provider);
DCHECK(!initialized_);
- if (IsContextLost(context))
+ if (context_provider->IsContextLost())
return;
- // Need to bind uniforms before linking
- if (!using_bind_uniform)
- Link(context);
+ if (!ProgramBindingBase::Init(
+ context_provider->ContextGL(),
+ vertex_shader_.GetShaderString(),
+ fragment_shader_.GetShaderString(precision, sampler))) {
+ DCHECK(context_provider->IsContextLost());
+ return;
+ }
int base_uniform_index = 0;
- vertex_shader_.Init(
- context, program_, using_bind_uniform, &base_uniform_index);
- fragment_shader_.Init(
- context, program_, using_bind_uniform, &base_uniform_index);
+ vertex_shader_.Init(context_provider->ContextGL(),
+ program_, &base_uniform_index);
+ fragment_shader_.Init(context_provider->ContextGL(),
+ program_, &base_uniform_index);
// Link after binding uniforms
- if (using_bind_uniform)
- Link(context);
+ if (!Link(context_provider->ContextGL())) {
+ DCHECK(context_provider->IsContextLost());
+ return;
+ }
initialized_ = true;
}
diff --git a/chromium/cc/output/render_surface_filters.cc b/chromium/cc/output/render_surface_filters.cc
index 04d8c5ab9f7..e10ea885e7f 100644
--- a/chromium/cc/output/render_surface_filters.cc
+++ b/chromium/cc/output/render_surface_filters.cc
@@ -11,8 +11,13 @@
#include "cc/output/filter_operations.h"
#include "skia/ext/refptr.h"
#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkFlattenableBuffers.h"
+#include "third_party/skia/include/core/SkImageFilter.h"
#include "third_party/skia/include/effects/SkBlurImageFilter.h"
+#include "third_party/skia/include/effects/SkColorFilterImageFilter.h"
#include "third_party/skia/include/effects/SkColorMatrixFilter.h"
+#include "third_party/skia/include/effects/SkComposeImageFilter.h"
+#include "third_party/skia/include/effects/SkDropShadowImageFilter.h"
#include "third_party/skia/include/effects/SkMagnifierImageFilter.h"
#include "third_party/skia/include/gpu/SkGpuDevice.h"
#include "third_party/skia/include/gpu/SkGrPixelRef.h"
@@ -142,325 +147,122 @@ void GetSepiaMatrix(float amount, SkScalar matrix[20]) {
matrix[18] = 1.f;
}
-// The 5x4 matrix is really a "compressed" version of a 5x5 matrix that'd have
-// (0 0 0 0 1) as a last row, and that would be applied to a 5-vector extended
-// from the 4-vector color with a 1.
-void MultColorMatrix(SkScalar a[20], SkScalar b[20], SkScalar out[20]) {
- for (int j = 0; j < 4; ++j) {
- for (int i = 0; i < 5; ++i) {
- out[i+j*5] = i == 4 ? a[4+j*5] : 0.f;
- for (int k = 0; k < 4; ++k)
- out[i+j*5] += a[k+j*5] * b[i+k*5];
- }
- }
-}
-
-// To detect if we need to apply clamping after applying a matrix, we check if
-// any output component might go outside of [0, 255] for any combination of
-// input components in [0..255].
-// Each output component is an affine transformation of the input component, so
-// the minimum and maximum values are for any combination of minimum or maximum
-// values of input components (i.e. 0 or 255).
-// E.g. if R' = x*R + y*G + z*B + w*A + t
-// Then the maximum value will be for R=255 if x>0 or R=0 if x<0, and the
-// minimum value will be for R=0 if x>0 or R=255 if x<0.
-// Same goes for all components.
-bool ComponentNeedsClamping(SkScalar row[5]) {
- SkScalar max_value = row[4] / 255.f;
- SkScalar min_value = row[4] / 255.f;
- for (int i = 0; i < 4; ++i) {
- if (row[i] > 0)
- max_value += row[i];
- else
- min_value += row[i];
- }
- return (max_value > 1.f) || (min_value < 0.f);
+skia::RefPtr<SkImageFilter> CreateMatrixImageFilter(
+ const SkScalar matrix[20],
+ const skia::RefPtr<SkImageFilter>& input) {
+ skia::RefPtr<SkColorFilter> color_filter =
+ skia::AdoptRef(new SkColorMatrixFilter(matrix));
+ return skia::AdoptRef(
+ SkColorFilterImageFilter::Create(color_filter.get(), input.get()));
}
-bool MatrixNeedsClamping(SkScalar matrix[20]) {
- return ComponentNeedsClamping(matrix)
- || ComponentNeedsClamping(matrix+5)
- || ComponentNeedsClamping(matrix+10)
- || ComponentNeedsClamping(matrix+15);
-}
-
-bool GetColorMatrix(const FilterOperation& op, SkScalar matrix[20]) {
- switch (op.type()) {
- case FilterOperation::BRIGHTNESS: {
- GetBrightnessMatrix(op.amount(), matrix);
- return true;
- }
- case FilterOperation::SATURATING_BRIGHTNESS: {
- GetSaturatingBrightnessMatrix(op.amount(), matrix);
- return true;
- }
- case FilterOperation::CONTRAST: {
- GetContrastMatrix(op.amount(), matrix);
- return true;
- }
- case FilterOperation::GRAYSCALE: {
- GetGrayscaleMatrix(1.f - op.amount(), matrix);
- return true;
- }
- case FilterOperation::SEPIA: {
- GetSepiaMatrix(1.f - op.amount(), matrix);
- return true;
- }
- case FilterOperation::SATURATE: {
- GetSaturateMatrix(op.amount(), matrix);
- return true;
- }
- case FilterOperation::HUE_ROTATE: {
- GetHueRotateMatrix(op.amount(), matrix);
- return true;
- }
- case FilterOperation::INVERT: {
- GetInvertMatrix(op.amount(), matrix);
- return true;
- }
- case FilterOperation::OPACITY: {
- GetOpacityMatrix(op.amount(), matrix);
- return true;
- }
- case FilterOperation::COLOR_MATRIX: {
- memcpy(matrix, op.matrix(), sizeof(SkScalar[20]));
- return true;
- }
- case FilterOperation::BLUR:
- case FilterOperation::DROP_SHADOW:
- case FilterOperation::ZOOM:
- return false;
- }
- NOTREACHED();
- return false;
-}
-
-class FilterBufferState {
- public:
- FilterBufferState(GrContext* gr_context,
- gfx::SizeF size,
- unsigned texture_id)
- : gr_context_(gr_context),
- current_texture_(0) {
- // Wrap the source texture in a Ganesh platform texture.
- GrBackendTextureDesc backend_texture_description;
- backend_texture_description.fWidth = size.width();
- backend_texture_description.fHeight = size.height();
- backend_texture_description.fConfig = kSkia8888_GrPixelConfig;
- backend_texture_description.fTextureHandle = texture_id;
- skia::RefPtr<GrTexture> texture = skia::AdoptRef(
- gr_context->wrapBackendTexture(backend_texture_description));
- // Place the platform texture inside an SkBitmap.
- source_.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
- skia::RefPtr<SkGrPixelRef> pixel_ref =
- skia::AdoptRef(new SkGrPixelRef(texture.get()));
- source_.setPixelRef(pixel_ref.get());
- }
-
- ~FilterBufferState() {}
-
- bool Init(int filter_count) {
- int scratch_count = std::min(2, filter_count);
- GrTextureDesc desc;
- desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
- desc.fSampleCnt = 0;
- desc.fWidth = source_.width();
- desc.fHeight = source_.height();
- desc.fConfig = kSkia8888_GrPixelConfig;
- for (int i = 0; i < scratch_count; ++i) {
- GrAutoScratchTexture scratch_texture(
- gr_context_, desc, GrContext::kExact_ScratchTexMatch);
- scratch_textures_[i] = skia::AdoptRef(scratch_texture.detach());
- if (!scratch_textures_[i])
- return false;
- }
- return true;
- }
-
- SkCanvas* Canvas() {
- if (!canvas_)
- CreateCanvas();
- return canvas_.get();
- }
-
- const SkBitmap& Source() { return source_; }
-
- void Swap() {
- canvas_->flush();
- canvas_.clear();
- device_.clear();
-
- skia::RefPtr<SkGrPixelRef> pixel_ref = skia::AdoptRef(
- new SkGrPixelRef(scratch_textures_[current_texture_].get()));
- source_.setPixelRef(pixel_ref.get());
- current_texture_ = 1 - current_texture_;
- }
-
- private:
- void CreateCanvas() {
- DCHECK(scratch_textures_[current_texture_].get());
- device_ = skia::AdoptRef(new SkGpuDevice(
- gr_context_, scratch_textures_[current_texture_].get()));
- canvas_ = skia::AdoptRef(new SkCanvas(device_.get()));
- canvas_->clear(0x0);
- }
-
- GrContext* gr_context_;
- SkBitmap source_;
- skia::RefPtr<GrTexture> scratch_textures_[2];
- int current_texture_;
- skia::RefPtr<SkGpuDevice> device_;
- skia::RefPtr<SkCanvas> canvas_;
-};
-
} // namespace
-FilterOperations RenderSurfaceFilters::Optimize(
- const FilterOperations& filters) {
- FilterOperations new_list;
-
- SkScalar accumulated_color_matrix[20];
- bool have_accumulated_color_matrix = false;
- for (unsigned i = 0; i < filters.size(); ++i) {
+skia::RefPtr<SkImageFilter> RenderSurfaceFilters::BuildImageFilter(
+ const FilterOperations& filters,
+ gfx::SizeF size) {
+ skia::RefPtr<SkImageFilter> image_filter;
+ SkScalar matrix[20];
+ for (size_t i = 0; i < filters.size(); ++i) {
const FilterOperation& op = filters.at(i);
-
- // If the filter is a color matrix, we may be able to combine it with
- // following Filter(s) that also are color matrices.
- SkScalar matrix[20];
- if (GetColorMatrix(op, matrix)) {
- if (have_accumulated_color_matrix) {
- SkScalar new_matrix[20];
- MultColorMatrix(matrix, accumulated_color_matrix, new_matrix);
- memcpy(accumulated_color_matrix,
- new_matrix,
- sizeof(accumulated_color_matrix));
- } else {
- memcpy(accumulated_color_matrix,
- matrix,
- sizeof(accumulated_color_matrix));
- have_accumulated_color_matrix = true;
- }
-
- // We can only combine matrices if clamping of color components
- // would have no effect.
- if (!MatrixNeedsClamping(accumulated_color_matrix))
- continue;
- }
-
- if (have_accumulated_color_matrix) {
- new_list.Append(FilterOperation::CreateColorMatrixFilter(
- accumulated_color_matrix));
- }
- have_accumulated_color_matrix = false;
-
switch (op.type()) {
- case FilterOperation::BLUR:
- case FilterOperation::DROP_SHADOW:
- case FilterOperation::ZOOM:
- new_list.Append(op);
- break;
- case FilterOperation::BRIGHTNESS:
- case FilterOperation::SATURATING_BRIGHTNESS:
- case FilterOperation::CONTRAST:
case FilterOperation::GRAYSCALE:
+ GetGrayscaleMatrix(1.f - op.amount(), matrix);
+ image_filter = CreateMatrixImageFilter(matrix, image_filter);
+ break;
case FilterOperation::SEPIA:
+ GetSepiaMatrix(1.f - op.amount(), matrix);
+ image_filter = CreateMatrixImageFilter(matrix, image_filter);
+ break;
case FilterOperation::SATURATE:
+ GetSaturateMatrix(op.amount(), matrix);
+ image_filter = CreateMatrixImageFilter(matrix, image_filter);
+ break;
case FilterOperation::HUE_ROTATE:
+ GetHueRotateMatrix(op.amount(), matrix);
+ image_filter = CreateMatrixImageFilter(matrix, image_filter);
+ break;
case FilterOperation::INVERT:
+ GetInvertMatrix(op.amount(), matrix);
+ image_filter = CreateMatrixImageFilter(matrix, image_filter);
+ break;
case FilterOperation::OPACITY:
- case FilterOperation::COLOR_MATRIX:
+ GetOpacityMatrix(op.amount(), matrix);
+ image_filter = CreateMatrixImageFilter(matrix, image_filter);
break;
- }
- }
- if (have_accumulated_color_matrix) {
- new_list.Append(FilterOperation::CreateColorMatrixFilter(
- accumulated_color_matrix));
- }
- return new_list;
-}
-
-SkBitmap RenderSurfaceFilters::Apply(const FilterOperations& filters,
- unsigned texture_id,
- gfx::SizeF size,
- GrContext* gr_context) {
- DCHECK(gr_context);
-
- FilterBufferState state(gr_context, size, texture_id);
- if (!state.Init(filters.size()))
- return SkBitmap();
-
- for (unsigned i = 0; i < filters.size(); ++i) {
- const FilterOperation& op = filters.at(i);
- SkCanvas* canvas = state.Canvas();
- switch (op.type()) {
- case FilterOperation::COLOR_MATRIX: {
- SkPaint paint;
- skia::RefPtr<SkColorMatrixFilter> filter =
- skia::AdoptRef(new SkColorMatrixFilter(op.matrix()));
- paint.setColorFilter(filter.get());
- canvas->drawBitmap(state.Source(), 0, 0, &paint);
+ case FilterOperation::BRIGHTNESS:
+ GetBrightnessMatrix(op.amount(), matrix);
+ image_filter = CreateMatrixImageFilter(matrix, image_filter);
break;
- }
- case FilterOperation::BLUR: {
- float std_deviation = op.amount();
- skia::RefPtr<SkImageFilter> filter =
- skia::AdoptRef(new SkBlurImageFilter(std_deviation, std_deviation));
- SkPaint paint;
- paint.setImageFilter(filter.get());
- canvas->drawSprite(state.Source(), 0, 0, &paint);
+ case FilterOperation::CONTRAST:
+ GetContrastMatrix(op.amount(), matrix);
+ image_filter = CreateMatrixImageFilter(matrix, image_filter);
break;
- }
- case FilterOperation::DROP_SHADOW: {
- skia::RefPtr<SkImageFilter> blur_filter =
- skia::AdoptRef(new SkBlurImageFilter(op.amount(), op.amount()));
- skia::RefPtr<SkColorFilter> color_filter =
- skia::AdoptRef(SkColorFilter::CreateModeFilter(
- op.drop_shadow_color(), SkXfermode::kSrcIn_Mode));
- SkPaint paint;
- paint.setImageFilter(blur_filter.get());
- paint.setColorFilter(color_filter.get());
- paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
- canvas->saveLayer(NULL, &paint);
- canvas->drawBitmap(state.Source(),
- op.drop_shadow_offset().x(),
- op.drop_shadow_offset().y());
- canvas->restore();
- canvas->drawBitmap(state.Source(), 0, 0);
+ case FilterOperation::BLUR:
+ image_filter = skia::AdoptRef(new SkBlurImageFilter(
+ op.amount(), op.amount(), image_filter.get()));
+ break;
+ case FilterOperation::DROP_SHADOW:
+ image_filter = skia::AdoptRef(new SkDropShadowImageFilter(
+ SkIntToScalar(op.drop_shadow_offset().x()),
+ SkIntToScalar(op.drop_shadow_offset().y()),
+ SkIntToScalar(op.amount()),
+ op.drop_shadow_color(),
+ image_filter.get()));
+ break;
+ case FilterOperation::COLOR_MATRIX:
+ image_filter = CreateMatrixImageFilter(op.matrix(), image_filter);
break;
- }
case FilterOperation::ZOOM: {
- SkPaint paint;
- int width = state.Source().width();
- int height = state.Source().height();
skia::RefPtr<SkImageFilter> zoom_filter = skia::AdoptRef(
new SkMagnifierImageFilter(
SkRect::MakeXYWH(
- (width - (width / op.amount())) / 2.f,
- (height - (height / op.amount())) / 2.f,
- width / op.amount(),
- height / op.amount()),
+ (size.width() - (size.width() / op.amount())) / 2.f,
+ (size.height() - (size.height() / op.amount())) / 2.f,
+ size.width() / op.amount(),
+ size.height() / op.amount()),
op.zoom_inset()));
- paint.setImageFilter(zoom_filter.get());
- canvas->saveLayer(NULL, &paint);
- canvas->drawBitmap(state.Source(), 0, 0);
- canvas->restore();
+ if (image_filter.get()) {
+ // TODO(ajuma): When there's a 1-input version of
+ // SkMagnifierImageFilter, use that to handle the input filter
+ // instead of using an SkComposeImageFilter.
+ image_filter = skia::AdoptRef(new SkComposeImageFilter(
+ zoom_filter.get(), image_filter.get()));
+ } else {
+ image_filter = zoom_filter;
+ }
break;
}
- case FilterOperation::BRIGHTNESS:
case FilterOperation::SATURATING_BRIGHTNESS:
- case FilterOperation::CONTRAST:
- case FilterOperation::GRAYSCALE:
- case FilterOperation::SEPIA:
- case FilterOperation::SATURATE:
- case FilterOperation::HUE_ROTATE:
- case FilterOperation::INVERT:
- case FilterOperation::OPACITY:
- NOTREACHED();
+ GetSaturatingBrightnessMatrix(op.amount(), matrix);
+ image_filter = CreateMatrixImageFilter(matrix, image_filter);
break;
+ case FilterOperation::REFERENCE: {
+ if (!op.image_filter())
+ break;
+
+ skia::RefPtr<SkColorFilter> cf;
+
+ {
+ SkColorFilter* colorfilter_rawptr = NULL;
+ op.image_filter()->asColorFilter(&colorfilter_rawptr);
+ cf = skia::AdoptRef(colorfilter_rawptr);
+ }
+
+ if (cf && cf->asColorMatrix(matrix) &&
+ !op.image_filter()->getInput(0)) {
+ image_filter = CreateMatrixImageFilter(matrix, image_filter);
+ } else if (image_filter) {
+ image_filter = skia::AdoptRef(new SkComposeImageFilter(
+ op.image_filter().get(), image_filter.get()));
+ } else {
+ image_filter = op.image_filter();
+ }
+ break;
+ }
}
- state.Swap();
}
- return state.Source();
+ return image_filter;
}
} // namespace cc
diff --git a/chromium/cc/output/render_surface_filters.h b/chromium/cc/output/render_surface_filters.h
index 5ab78dc77e7..09d0f732a03 100644
--- a/chromium/cc/output/render_surface_filters.h
+++ b/chromium/cc/output/render_surface_filters.h
@@ -8,9 +8,11 @@
#include "base/basictypes.h"
#include "cc/base/cc_export.h"
+#include "skia/ext/refptr.h"
class GrContext;
class SkBitmap;
+class SkImageFilter;
namespace gfx {
class SizeF;
@@ -28,6 +30,10 @@ class CC_EXPORT RenderSurfaceFilters {
GrContext* gr_context);
static FilterOperations Optimize(const FilterOperations& filters);
+ static skia::RefPtr<SkImageFilter> BuildImageFilter(
+ const FilterOperations& filters,
+ gfx::SizeF size);
+
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(RenderSurfaceFilters);
};
diff --git a/chromium/cc/output/render_surface_filters_unittest.cc b/chromium/cc/output/render_surface_filters_unittest.cc
deleted file mode 100644
index 38c6cc343b1..00000000000
--- a/chromium/cc/output/render_surface_filters_unittest.cc
+++ /dev/null
@@ -1,140 +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/output/render_surface_filters.h"
-
-#include "cc/output/filter_operation.h"
-#include "cc/output/filter_operations.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace cc {
-namespace {
-
-// Checks whether op can be combined with a following color matrix.
-bool IsCombined(const FilterOperation& op) {
- FilterOperations filters;
- filters.Append(op);
- // brightness(0.0f) is identity.
- filters.Append(FilterOperation::CreateBrightnessFilter(0.0f));
- FilterOperations optimized = RenderSurfaceFilters::Optimize(filters);
- return optimized.size() == 1;
-}
-
-TEST(RenderSurfaceFiltersTest, TestColorMatrixFiltersCombined) {
- // Several filters should always combine for any amount between 0 and 1:
- // grayscale, saturate, invert, contrast, opacity.
- EXPECT_TRUE(IsCombined(FilterOperation::CreateGrayscaleFilter(0.0f)));
- // Note that we use 0.3f to avoid "argument is truncated from 'double' to
- // 'float'" warnings on Windows. 0.5f is exactly representable as a float, so
- // there is no warning.
- EXPECT_TRUE(IsCombined(FilterOperation::CreateGrayscaleFilter(0.3f)));
- EXPECT_TRUE(IsCombined(FilterOperation::CreateGrayscaleFilter(0.5f)));
- EXPECT_TRUE(IsCombined(FilterOperation::CreateGrayscaleFilter(1.0f)));
-
- EXPECT_TRUE(IsCombined(FilterOperation::CreateSaturateFilter(0.0f)));
- EXPECT_TRUE(IsCombined(FilterOperation::CreateSaturateFilter(0.3f)));
- EXPECT_TRUE(IsCombined(FilterOperation::CreateSaturateFilter(0.5)));
- EXPECT_TRUE(IsCombined(FilterOperation::CreateSaturateFilter(1.0f)));
-
- EXPECT_TRUE(IsCombined(FilterOperation::CreateInvertFilter(0.0f)));
- EXPECT_TRUE(IsCombined(FilterOperation::CreateInvertFilter(0.3f)));
- EXPECT_TRUE(IsCombined(FilterOperation::CreateInvertFilter(0.5)));
- EXPECT_TRUE(IsCombined(FilterOperation::CreateInvertFilter(1.0f)));
-
- EXPECT_TRUE(IsCombined(FilterOperation::CreateContrastFilter(0.0f)));
- EXPECT_TRUE(IsCombined(FilterOperation::CreateContrastFilter(0.3f)));
- EXPECT_TRUE(IsCombined(FilterOperation::CreateContrastFilter(0.5)));
- EXPECT_TRUE(IsCombined(FilterOperation::CreateContrastFilter(1.0f)));
-
- EXPECT_TRUE(IsCombined(FilterOperation::CreateOpacityFilter(0.0f)));
- EXPECT_TRUE(IsCombined(FilterOperation::CreateOpacityFilter(0.3f)));
- EXPECT_TRUE(IsCombined(FilterOperation::CreateOpacityFilter(0.5)));
- EXPECT_TRUE(IsCombined(FilterOperation::CreateOpacityFilter(1.0f)));
-
- // Brightness combines when amount <= 1
- EXPECT_TRUE(IsCombined(FilterOperation::CreateBrightnessFilter(0.5)));
- EXPECT_TRUE(IsCombined(FilterOperation::CreateBrightnessFilter(1.0f)));
- EXPECT_FALSE(IsCombined(FilterOperation::CreateBrightnessFilter(1.5)));
-
- // SaturatingBrightness combines only when amount == 0
- EXPECT_TRUE(
- IsCombined(FilterOperation::CreateSaturatingBrightnessFilter(0.0f)));
- EXPECT_FALSE(
- IsCombined(FilterOperation::CreateSaturatingBrightnessFilter(0.5)));
- EXPECT_FALSE(
- IsCombined(FilterOperation::CreateSaturatingBrightnessFilter(1.0f)));
-
- // Several filters should never combine: blur, drop-shadow.
- EXPECT_FALSE(IsCombined(FilterOperation::CreateBlurFilter(3.0f)));
- EXPECT_FALSE(IsCombined(FilterOperation::CreateDropShadowFilter(
- gfx::Point(2, 2), 3.0f, 0xffffffff)));
-
- // sepia and hue may or may not combine depending on the value.
- EXPECT_TRUE(IsCombined(FilterOperation::CreateSepiaFilter(0.0f)));
- EXPECT_FALSE(IsCombined(FilterOperation::CreateSepiaFilter(1.0f)));
- EXPECT_TRUE(IsCombined(FilterOperation::CreateHueRotateFilter(0.0f)));
- EXPECT_FALSE(IsCombined(FilterOperation::CreateHueRotateFilter(180.0f)));
-
- float matrix1[20] = { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, };
- EXPECT_TRUE(IsCombined(FilterOperation::CreateColorMatrixFilter(matrix1)));
-
- float matrix2[20] = { 1.0f, 1.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, };
- EXPECT_FALSE(
- IsCombined(FilterOperation::CreateColorMatrixFilter(matrix2)));
-
- float matrix3[20] = { 0.25f, 0.0f, 0.0f, 0.0f, 255.0f * 0.75f,
- 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, };
- EXPECT_TRUE(IsCombined(FilterOperation::CreateColorMatrixFilter(matrix3)));
-
- float matrix4[20] = { -0.25f, 0.75f, 0.0f, 0.0f, 255.0f * 0.25f,
- 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, };
- EXPECT_TRUE(IsCombined(FilterOperation::CreateColorMatrixFilter(matrix4)));
-}
-
-TEST(RenderSurfaceFiltersTest, TestOptimize) {
- FilterOperation combines(FilterOperation::CreateBrightnessFilter(1.0f));
- FilterOperation doesnt_combine(
- FilterOperation::CreateBrightnessFilter(1.5f));
-
- FilterOperations filters;
- FilterOperations optimized = RenderSurfaceFilters::Optimize(filters);
- EXPECT_EQ(0u, optimized.size());
-
- filters.Append(combines);
- optimized = RenderSurfaceFilters::Optimize(filters);
- EXPECT_EQ(1u, optimized.size());
-
- filters.Append(combines);
- optimized = RenderSurfaceFilters::Optimize(filters);
- EXPECT_EQ(1u, optimized.size());
-
- filters.Append(doesnt_combine);
- optimized = RenderSurfaceFilters::Optimize(filters);
- EXPECT_EQ(1u, optimized.size());
-
- filters.Append(combines);
- optimized = RenderSurfaceFilters::Optimize(filters);
- EXPECT_EQ(2u, optimized.size());
-
- filters.Append(doesnt_combine);
- optimized = RenderSurfaceFilters::Optimize(filters);
- EXPECT_EQ(2u, optimized.size());
-
- filters.Append(doesnt_combine);
- optimized = RenderSurfaceFilters::Optimize(filters);
- EXPECT_EQ(3u, optimized.size());
-}
-
-} // namespace
-} // namespace cc
diff --git a/chromium/cc/output/renderer.cc b/chromium/cc/output/renderer.cc
index 7627db7ab0a..2fe0ef75b5f 100644
--- a/chromium/cc/output/renderer.cc
+++ b/chromium/cc/output/renderer.cc
@@ -6,7 +6,7 @@
namespace cc {
-bool Renderer::HaveCachedResourcesForRenderPassId(RenderPass::Id id) const {
+bool Renderer::HasAllocatedResourcesForTesting(RenderPass::Id id) const {
return false;
}
diff --git a/chromium/cc/output/renderer.h b/chromium/cc/output/renderer.h
index 32a109fac85..147b535fd72 100644
--- a/chromium/cc/output/renderer.h
+++ b/chromium/cc/output/renderer.h
@@ -18,16 +18,7 @@ class ScopedResource;
class CC_EXPORT RendererClient {
public:
- // These return the draw viewport and clip in non-y-flipped window space.
- // Note that while a draw is in progress, these are guaranteed to be
- // contained within the output surface size.
- virtual gfx::Rect DeviceViewport() const = 0;
- virtual gfx::Rect DeviceClip() const = 0;
virtual void SetFullRootLayerDamage() = 0;
- virtual CompositorFrameMetadata MakeCompositorFrameMetadata() const = 0;
-
- protected:
- virtual ~RendererClient() {}
};
class CC_EXPORT Renderer {
@@ -36,21 +27,24 @@ class CC_EXPORT Renderer {
virtual const RendererCapabilities& Capabilities() const = 0;
- virtual void ViewportChanged() {}
-
virtual bool CanReadPixels() const = 0;
virtual void DecideRenderPassAllocationsForFrame(
const RenderPassList& render_passes_in_draw_order) {}
- virtual bool HaveCachedResourcesForRenderPassId(RenderPass::Id id) const;
+ virtual bool HasAllocatedResourcesForTesting(RenderPass::Id id) const;
// This passes ownership of the render passes to the renderer. It should
// consume them, and empty the list. The parameters here may change from frame
// to frame and should not be cached.
+ // The |device_viewport_rect| and |device_clip_rect| are in non-y-flipped
+ // window space.
virtual void DrawFrame(RenderPassList* render_passes_in_draw_order,
ContextProvider* offscreen_context_provider,
float device_scale_factor,
- bool allow_partial_swap) = 0;
+ gfx::Rect device_viewport_rect,
+ gfx::Rect device_clip_rect,
+ bool allow_partial_swap,
+ bool disable_picture_quad_image_filtering) = 0;
// Waits for rendering to finish.
virtual void Finish() = 0;
@@ -58,7 +52,7 @@ class CC_EXPORT Renderer {
virtual void DoNoOp() {}
// Puts backbuffer onscreen.
- virtual void SwapBuffers() = 0;
+ virtual void SwapBuffers(const CompositorFrameMetadata& metadata) = 0;
virtual void ReceiveSwapBuffersAck(const CompositorFrameAck& ack) {}
virtual void GetFramebufferPixels(void* pixels, gfx::Rect rect) = 0;
@@ -71,8 +65,6 @@ class CC_EXPORT Renderer {
size_t bytes_visible_and_nearby,
size_t bytes_allocated) = 0;
- virtual void SetDiscardBackBufferWhenNotVisible(bool discard) = 0;
-
protected:
explicit Renderer(RendererClient* client, const LayerTreeSettings* settings)
: client_(client), settings_(settings) {}
diff --git a/chromium/cc/output/renderer_pixeltest.cc b/chromium/cc/output/renderer_pixeltest.cc
index f0187aacdb3..24c6126755e 100644
--- a/chromium/cc/output/renderer_pixeltest.cc
+++ b/chromium/cc/output/renderer_pixeltest.cc
@@ -8,7 +8,6 @@
#include "cc/quads/draw_quad.h"
#include "cc/quads/picture_draw_quad.h"
#include "cc/quads/texture_draw_quad.h"
-#include "cc/resources/sync_point_helper.h"
#include "cc/test/fake_picture_pile_impl.h"
#include "cc/test/pixel_test.h"
#include "gpu/GLES2/gl2extchromium.h"
@@ -22,6 +21,7 @@
namespace cc {
namespace {
+#if !defined(OS_ANDROID)
scoped_ptr<RenderPass> CreateTestRootRenderPass(RenderPass::Id id,
gfx::Rect rect) {
scoped_ptr<RenderPass> pass = RenderPass::Create();
@@ -50,13 +50,15 @@ scoped_ptr<SharedQuadState> CreateTestSharedQuadState(
const gfx::Rect clip_rect = rect;
const bool is_clipped = false;
const float opacity = 1.0f;
+ const SkXfermode::Mode blend_mode = SkXfermode::kSrcOver_Mode;
scoped_ptr<SharedQuadState> shared_state = SharedQuadState::Create();
shared_state->SetAll(content_to_target_transform,
content_bounds,
visible_content_rect,
clip_rect,
is_clipped,
- opacity);
+ opacity,
+ blend_mode);
return shared_state.Pass();
}
@@ -68,13 +70,15 @@ scoped_ptr<SharedQuadState> CreateTestSharedQuadStateClipped(
const gfx::Rect visible_content_rect = clip_rect;
const bool is_clipped = true;
const float opacity = 1.0f;
+ const SkXfermode::Mode blend_mode = SkXfermode::kSrcOver_Mode;
scoped_ptr<SharedQuadState> shared_state = SharedQuadState::Create();
shared_state->SetAll(content_to_target_transform,
content_bounds,
visible_content_rect,
clip_rect,
is_clipped,
- opacity);
+ opacity,
+ blend_mode);
return shared_state.Pass();
}
@@ -84,13 +88,12 @@ scoped_ptr<DrawQuad> CreateTestRenderPassDrawQuad(
quad->SetNew(shared_state,
rect,
pass_id,
- false, // is_replica
- 0, // mask_resource_id
- rect, // contents_changed_since_last_frame
- gfx::RectF(), // mask_uv_rect
- FilterOperations(), // foreground filters
- skia::RefPtr<SkImageFilter>(), // foreground filter
- FilterOperations()); // background filters
+ false, // is_replica
+ 0, // mask_resource_id
+ rect, // contents_changed_since_last_frame
+ gfx::RectF(1.f, 1.f), // mask_uv_rect
+ FilterOperations(), // foreground filters
+ FilterOperations()); // background filters
return quad.PassAs<DrawQuad>();
}
@@ -144,16 +147,6 @@ typedef ::testing::Types<GLRenderer,
SoftwareRendererWithExpandedViewport> RendererTypes;
TYPED_TEST_CASE(RendererPixelTest, RendererTypes);
-typedef ::testing::Types<GLRenderer,
- GLRendererWithSkiaGPUBackend,
- SoftwareRenderer> RendererTypesWithSkiaGPUBackend;
-template <typename RendererType>
-class RendererPixelTestWithSkiaGPUBackend
- : public RendererPixelTest<RendererType> {
-};
-TYPED_TEST_CASE(RendererPixelTestWithSkiaGPUBackend,
- RendererTypesWithSkiaGPUBackend);
-
// All pixels can be off by one, but any more than that is an error.
class FuzzyPixelOffByOneComparator : public FuzzyPixelComparator {
public:
@@ -197,7 +190,6 @@ bool FuzzyForSoftwareOnlyPixelComparator<RendererType>::Compare(
return exact_.Compare(actual_bmp, expected_bmp);
}
-#if !defined(OS_ANDROID)
TYPED_TEST(RendererPixelTest, SimpleGreenRect) {
gfx::Rect rect(this->device_viewport_size_);
@@ -463,7 +455,7 @@ class VideoGLRendererPixelTest : public GLRendererPixelTest {
gfx::Vector2d());
}
- scoped_ptr<YUVVideoDrawQuad> yuv_quad = cc::YUVVideoDrawQuad::Create();
+ scoped_ptr<YUVVideoDrawQuad> yuv_quad = YUVVideoDrawQuad::Create();
yuv_quad->SetNew(shared_state, rect, opaque_rect, gfx::Size(),
y_resource, u_resource, v_resource, a_resource);
return yuv_quad.Pass();
@@ -623,6 +615,8 @@ TYPED_TEST(RendererPixelTest, FastPassColorFilterAlpha) {
new SkColorMatrixFilter(matrix)));
skia::RefPtr<SkImageFilter> filter =
skia::AdoptRef(SkColorFilterImageFilter::Create(colorFilter.get(), NULL));
+ FilterOperations filters;
+ filters.Append(FilterOperation::CreateReferenceFilter(filter));
scoped_ptr<RenderPassDrawQuad> render_pass_quad =
RenderPassDrawQuad::Create();
@@ -633,8 +627,7 @@ TYPED_TEST(RendererPixelTest, FastPassColorFilterAlpha) {
0,
pass_rect,
gfx::RectF(),
- FilterOperations(),
- filter,
+ filters,
FilterOperations());
root_pass->quad_list.push_back(render_pass_quad.PassAs<DrawQuad>());
@@ -652,6 +645,165 @@ TYPED_TEST(RendererPixelTest, FastPassColorFilterAlpha) {
FuzzyForSoftwareOnlyPixelComparator<TypeParam>(false)));
}
+TYPED_TEST(RendererPixelTest, FastPassSaturateFilter) {
+ gfx::Rect viewport_rect(this->device_viewport_size_);
+
+ RenderPass::Id root_pass_id(1, 1);
+ scoped_ptr<RenderPass> root_pass =
+ CreateTestRootRenderPass(root_pass_id, viewport_rect);
+
+ RenderPass::Id child_pass_id(2, 2);
+ gfx::Rect pass_rect(this->device_viewport_size_);
+ gfx::Transform transform_to_root;
+ scoped_ptr<RenderPass> child_pass =
+ CreateTestRenderPass(child_pass_id, pass_rect, transform_to_root);
+
+ gfx::Transform content_to_target_transform;
+ scoped_ptr<SharedQuadState> shared_state =
+ CreateTestSharedQuadState(content_to_target_transform, viewport_rect);
+ shared_state->opacity = 0.5f;
+
+ scoped_ptr<SolidColorDrawQuad> blue = SolidColorDrawQuad::Create();
+ blue->SetNew(shared_state.get(),
+ gfx::Rect(0,
+ 0,
+ this->device_viewport_size_.width(),
+ this->device_viewport_size_.height() / 2),
+ SK_ColorBLUE,
+ false);
+ scoped_ptr<SolidColorDrawQuad> yellow = SolidColorDrawQuad::Create();
+ yellow->SetNew(shared_state.get(),
+ gfx::Rect(0,
+ this->device_viewport_size_.height() / 2,
+ this->device_viewport_size_.width(),
+ this->device_viewport_size_.height() / 2),
+ SK_ColorYELLOW,
+ false);
+
+ scoped_ptr<SharedQuadState> blank_state =
+ CreateTestSharedQuadState(content_to_target_transform, viewport_rect);
+
+ scoped_ptr<SolidColorDrawQuad> white = SolidColorDrawQuad::Create();
+ white->SetNew(blank_state.get(),
+ viewport_rect,
+ SK_ColorWHITE,
+ false);
+
+ child_pass->quad_list.push_back(blue.PassAs<DrawQuad>());
+ child_pass->quad_list.push_back(yellow.PassAs<DrawQuad>());
+ child_pass->quad_list.push_back(white.PassAs<DrawQuad>());
+
+ scoped_ptr<SharedQuadState> pass_shared_state =
+ CreateTestSharedQuadState(gfx::Transform(), pass_rect);
+
+ FilterOperations filters;
+ filters.Append(FilterOperation::CreateSaturateFilter(0.5f));
+
+ scoped_ptr<RenderPassDrawQuad> render_pass_quad =
+ RenderPassDrawQuad::Create();
+ render_pass_quad->SetNew(pass_shared_state.get(),
+ pass_rect,
+ child_pass_id,
+ false,
+ 0,
+ pass_rect,
+ gfx::RectF(),
+ filters,
+ FilterOperations());
+
+ root_pass->quad_list.push_back(render_pass_quad.PassAs<DrawQuad>());
+
+ RenderPassList pass_list;
+ pass_list.push_back(child_pass.Pass());
+ pass_list.push_back(root_pass.Pass());
+
+ EXPECT_TRUE(this->RunPixelTest(
+ &pass_list,
+ PixelTest::NoOffscreenContext,
+ base::FilePath(FILE_PATH_LITERAL("blue_yellow_alpha.png")),
+ ExactPixelComparator(true)));
+}
+
+TYPED_TEST(RendererPixelTest, FastPassFilterChain) {
+ gfx::Rect viewport_rect(this->device_viewport_size_);
+
+ RenderPass::Id root_pass_id(1, 1);
+ scoped_ptr<RenderPass> root_pass =
+ CreateTestRootRenderPass(root_pass_id, viewport_rect);
+
+ RenderPass::Id child_pass_id(2, 2);
+ gfx::Rect pass_rect(this->device_viewport_size_);
+ gfx::Transform transform_to_root;
+ scoped_ptr<RenderPass> child_pass =
+ CreateTestRenderPass(child_pass_id, pass_rect, transform_to_root);
+
+ gfx::Transform content_to_target_transform;
+ scoped_ptr<SharedQuadState> shared_state =
+ CreateTestSharedQuadState(content_to_target_transform, viewport_rect);
+ shared_state->opacity = 0.5f;
+
+ scoped_ptr<SolidColorDrawQuad> blue = SolidColorDrawQuad::Create();
+ blue->SetNew(shared_state.get(),
+ gfx::Rect(0,
+ 0,
+ this->device_viewport_size_.width(),
+ this->device_viewport_size_.height() / 2),
+ SK_ColorBLUE,
+ false);
+ scoped_ptr<SolidColorDrawQuad> yellow = SolidColorDrawQuad::Create();
+ yellow->SetNew(shared_state.get(),
+ gfx::Rect(0,
+ this->device_viewport_size_.height() / 2,
+ this->device_viewport_size_.width(),
+ this->device_viewport_size_.height() / 2),
+ SK_ColorYELLOW,
+ false);
+
+ scoped_ptr<SharedQuadState> blank_state =
+ CreateTestSharedQuadState(content_to_target_transform, viewport_rect);
+
+ scoped_ptr<SolidColorDrawQuad> white = SolidColorDrawQuad::Create();
+ white->SetNew(blank_state.get(),
+ viewport_rect,
+ SK_ColorWHITE,
+ false);
+
+ child_pass->quad_list.push_back(blue.PassAs<DrawQuad>());
+ child_pass->quad_list.push_back(yellow.PassAs<DrawQuad>());
+ child_pass->quad_list.push_back(white.PassAs<DrawQuad>());
+
+ scoped_ptr<SharedQuadState> pass_shared_state =
+ CreateTestSharedQuadState(gfx::Transform(), pass_rect);
+
+ FilterOperations filters;
+ filters.Append(FilterOperation::CreateGrayscaleFilter(1.f));
+ filters.Append(FilterOperation::CreateBrightnessFilter(0.5f));
+
+ scoped_ptr<RenderPassDrawQuad> render_pass_quad =
+ RenderPassDrawQuad::Create();
+ render_pass_quad->SetNew(pass_shared_state.get(),
+ pass_rect,
+ child_pass_id,
+ false,
+ 0,
+ pass_rect,
+ gfx::RectF(),
+ filters,
+ FilterOperations());
+
+ root_pass->quad_list.push_back(render_pass_quad.PassAs<DrawQuad>());
+
+ RenderPassList pass_list;
+ pass_list.push_back(child_pass.Pass());
+ pass_list.push_back(root_pass.Pass());
+
+ EXPECT_TRUE(this->RunPixelTest(
+ &pass_list,
+ PixelTest::NoOffscreenContext,
+ base::FilePath(FILE_PATH_LITERAL("blue_yellow_filter_chain.png")),
+ ExactPixelComparator(true)));
+}
+
TYPED_TEST(RendererPixelTest, FastPassColorFilterAlphaTranslation) {
gfx::Rect viewport_rect(this->device_viewport_size_);
@@ -726,6 +878,8 @@ TYPED_TEST(RendererPixelTest, FastPassColorFilterAlphaTranslation) {
new SkColorMatrixFilter(matrix)));
skia::RefPtr<SkImageFilter> filter =
skia::AdoptRef(SkColorFilterImageFilter::Create(colorFilter.get(), NULL));
+ FilterOperations filters;
+ filters.Append(FilterOperation::CreateReferenceFilter(filter));
scoped_ptr<RenderPassDrawQuad> render_pass_quad =
RenderPassDrawQuad::Create();
@@ -736,8 +890,7 @@ TYPED_TEST(RendererPixelTest, FastPassColorFilterAlphaTranslation) {
0,
pass_rect,
gfx::RectF(),
- FilterOperations(),
- filter,
+ filters,
FilterOperations());
root_pass->quad_list.push_back(render_pass_quad.PassAs<DrawQuad>());
@@ -881,6 +1034,107 @@ TYPED_TEST(RendererPixelTest, EnlargedRenderPassTextureWithAntiAliasing) {
FuzzyPixelOffByOneComparator(true)));
}
+// This tests the case where we have a RenderPass with a mask, but the quad
+// for the masked surface does not include the full surface texture.
+TYPED_TEST(RendererPixelTest, RenderPassAndMaskWithPartialQuad) {
+ gfx::Rect viewport_rect(this->device_viewport_size_);
+
+ RenderPass::Id root_pass_id(1, 1);
+ scoped_ptr<RenderPass> root_pass =
+ CreateTestRootRenderPass(root_pass_id, viewport_rect);
+ scoped_ptr<SharedQuadState> root_pass_shared_state =
+ CreateTestSharedQuadState(gfx::Transform(), viewport_rect);
+
+ RenderPass::Id child_pass_id(2, 2);
+ gfx::Transform transform_to_root;
+ scoped_ptr<RenderPass> child_pass =
+ CreateTestRenderPass(child_pass_id, viewport_rect, transform_to_root);
+ scoped_ptr<SharedQuadState> child_pass_shared_state =
+ CreateTestSharedQuadState(gfx::Transform(), viewport_rect);
+
+ // The child render pass is just a green box.
+ static const SkColor kCSSGreen = 0xff008000;
+ scoped_ptr<SolidColorDrawQuad> green = SolidColorDrawQuad::Create();
+ green->SetNew(child_pass_shared_state.get(), viewport_rect, kCSSGreen, false);
+ child_pass->quad_list.push_back(green.PassAs<DrawQuad>());
+
+ // Make a mask.
+ gfx::Rect mask_rect = viewport_rect;
+ SkBitmap bitmap;
+ bitmap.setConfig(
+ SkBitmap::kARGB_8888_Config, mask_rect.width(), mask_rect.height());
+ bitmap.allocPixels();
+ SkBitmapDevice bitmap_device(bitmap);
+ skia::RefPtr<SkCanvas> canvas = skia::AdoptRef(new SkCanvas(&bitmap_device));
+ SkPaint paint;
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(SkIntToScalar(4));
+ paint.setColor(SK_ColorWHITE);
+ canvas->clear(SK_ColorTRANSPARENT);
+ gfx::Rect rect = mask_rect;
+ while (!rect.IsEmpty()) {
+ rect.Inset(6, 6, 4, 4);
+ canvas->drawRect(
+ SkRect::MakeXYWH(rect.x(), rect.y(), rect.width(), rect.height()),
+ paint);
+ rect.Inset(6, 6, 4, 4);
+ }
+
+ ResourceProvider::ResourceId mask_resource_id =
+ this->resource_provider_->CreateResource(
+ mask_rect.size(),
+ GL_CLAMP_TO_EDGE,
+ ResourceProvider::TextureUsageAny,
+ RGBA_8888);
+ {
+ SkAutoLockPixels lock(bitmap);
+ this->resource_provider_->SetPixels(
+ mask_resource_id,
+ reinterpret_cast<uint8_t*>(bitmap.getPixels()),
+ mask_rect,
+ mask_rect,
+ gfx::Vector2d());
+ }
+
+ // This RenderPassDrawQuad does not include the full |viewport_rect| which is
+ // the size of the child render pass.
+ gfx::Rect sub_rect = gfx::Rect(50, 50, 100, 100);
+ EXPECT_NE(sub_rect.x(), child_pass->output_rect.x());
+ EXPECT_NE(sub_rect.y(), child_pass->output_rect.y());
+ EXPECT_NE(sub_rect.right(), child_pass->output_rect.right());
+ EXPECT_NE(sub_rect.bottom(), child_pass->output_rect.bottom());
+ EXPECT_TRUE(child_pass->output_rect.Contains(sub_rect));
+
+ // Set up a mask on the RenderPassDrawQuad.
+ scoped_ptr<RenderPassDrawQuad> mask_quad = RenderPassDrawQuad::Create();
+ mask_quad->SetNew(root_pass_shared_state.get(),
+ sub_rect,
+ child_pass_id,
+ false, // is_replica
+ mask_resource_id,
+ sub_rect, // contents_changed_since_last_frame
+ gfx::RectF(1.f, 1.f), // mask_uv_rect
+ FilterOperations(), // foreground filters
+ FilterOperations()); // background filters
+ root_pass->quad_list.push_back(mask_quad.PassAs<DrawQuad>());
+
+ // White background behind the masked render pass.
+ scoped_ptr<SolidColorDrawQuad> white = SolidColorDrawQuad::Create();
+ white->SetNew(
+ root_pass_shared_state.get(), viewport_rect, SK_ColorWHITE, false);
+ root_pass->quad_list.push_back(white.PassAs<DrawQuad>());
+
+ RenderPassList pass_list;
+ pass_list.push_back(child_pass.Pass());
+ pass_list.push_back(root_pass.Pass());
+
+ EXPECT_TRUE(this->RunPixelTest(
+ &pass_list,
+ PixelTest::NoOffscreenContext,
+ base::FilePath(FILE_PATH_LITERAL("image_mask_of_layer.png")),
+ ExactPixelComparator(true)));
+}
+
template <typename RendererType>
class RendererPixelTestWithBackgroundFilter
: public RendererPixelTest<RendererType> {
@@ -931,7 +1185,6 @@ class RendererPixelTestWithBackgroundFilter
filter_pass_content_rect_, // contents_changed_since_last_frame
gfx::RectF(), // mask_uv_rect
FilterOperations(), // filters
- skia::RefPtr<SkImageFilter>(), // filter
this->background_filters_);
root_pass->quad_list.push_back(filter_pass_quad.PassAs<DrawQuad>());
root_pass->shared_quad_state_list.push_back(shared_state.Pass());
@@ -1024,7 +1277,7 @@ TEST_F(GLRendererPixelTestWithBackgroundFilter, InvertFilter) {
class ExternalStencilPixelTest : public GLRendererPixelTest {
protected:
void ClearBackgroundToGreen() {
- WebKit::WebGraphicsContext3D* context3d =
+ blink::WebGraphicsContext3D* context3d =
output_surface_->context_provider()->Context3d();
output_surface_->EnsureBackbuffer();
output_surface_->Reshape(device_viewport_size_, 1);
@@ -1034,7 +1287,7 @@ class ExternalStencilPixelTest : public GLRendererPixelTest {
void PopulateStencilBuffer() {
// Set two quadrants of the stencil buffer to 1.
- WebKit::WebGraphicsContext3D* context3d =
+ blink::WebGraphicsContext3D* context3d =
output_surface_->context_provider()->Context3d();
ASSERT_TRUE(context3d->getContextAttributes().stencil);
output_surface_->EnsureBackbuffer();
@@ -1329,10 +1582,10 @@ TEST_F(GLRendererPixelTest, AntiAliasingPerspective) {
gfx::Rect red_rect(0, 0, 180, 500);
gfx::Transform red_content_to_target_transform(
- 1.0, 2.4520, 10.6206, 19.0,
- 0.0, 0.3528, 5.9737, 9.5,
- 0.0, -0.2250, -0.9744, 0.0,
- 0.0, 0.0225, 0.0974, 1.0);
+ 1.0f, 2.4520f, 10.6206f, 19.0f,
+ 0.0f, 0.3528f, 5.9737f, 9.5f,
+ 0.0f, -0.2250f, -0.9744f, 0.0f,
+ 0.0f, 0.0225f, 0.0974f, 1.0f);
scoped_ptr<SharedQuadState> red_shared_state =
CreateTestSharedQuadState(red_content_to_target_transform, red_rect);
scoped_ptr<SolidColorDrawQuad> red = SolidColorDrawQuad::Create();
@@ -1362,10 +1615,9 @@ TEST_F(GLRendererPixelTest, AntiAliasingPerspective) {
FuzzyPixelOffByOneComparator(true)));
}
-TYPED_TEST(RendererPixelTestWithSkiaGPUBackend, PictureDrawQuadIdentityScale) {
+TYPED_TEST(RendererPixelTest, PictureDrawQuadIdentityScale) {
gfx::Size pile_tile_size(1000, 1000);
gfx::Rect viewport(this->device_viewport_size_);
- bool use_skia_gpu_backend = this->UseSkiaGPUBackend();
// TODO(enne): the renderer should figure this out on its own.
ResourceFormat texture_format = RGBA_8888;
@@ -1408,7 +1660,6 @@ TYPED_TEST(RendererPixelTestWithSkiaGPUBackend, PictureDrawQuadIdentityScale) {
texture_format,
viewport,
1.f,
- use_skia_gpu_backend,
blue_pile);
pass->quad_list.push_back(blue_quad.PassAs<DrawQuad>());
@@ -1433,7 +1684,6 @@ TYPED_TEST(RendererPixelTestWithSkiaGPUBackend, PictureDrawQuadIdentityScale) {
texture_format,
viewport,
1.f,
- use_skia_gpu_backend,
green_pile);
pass->quad_list.push_back(green_quad.PassAs<DrawQuad>());
@@ -1451,7 +1701,6 @@ TYPED_TEST(RendererPixelTestWithSkiaGPUBackend, PictureDrawQuadIdentityScale) {
TYPED_TEST(RendererPixelTest, PictureDrawQuadOpacity) {
gfx::Size pile_tile_size(1000, 1000);
gfx::Rect viewport(this->device_viewport_size_);
- bool use_skia_gpu_backend = this->UseSkiaGPUBackend();
ResourceFormat texture_format = RGBA_8888;
RenderPass::Id id(1, 1);
@@ -1481,7 +1730,6 @@ TYPED_TEST(RendererPixelTest, PictureDrawQuadOpacity) {
texture_format,
viewport,
1.f,
- use_skia_gpu_backend,
green_pile);
pass->quad_list.push_back(green_quad.PassAs<DrawQuad>());
@@ -1506,7 +1754,6 @@ TYPED_TEST(RendererPixelTest, PictureDrawQuadOpacity) {
texture_format,
viewport,
1.f,
- use_skia_gpu_backend,
white_pile);
pass->quad_list.push_back(white_quad.PassAs<DrawQuad>());
@@ -1520,11 +1767,87 @@ TYPED_TEST(RendererPixelTest, PictureDrawQuadOpacity) {
FuzzyPixelOffByOneComparator(true)));
}
-TYPED_TEST(RendererPixelTestWithSkiaGPUBackend,
- PictureDrawQuadNonIdentityScale) {
+template<typename TypeParam> bool IsSoftwareRenderer() {
+ return false;
+}
+
+template<>
+bool IsSoftwareRenderer<SoftwareRenderer>() {
+ return true;
+}
+
+template<>
+bool IsSoftwareRenderer<SoftwareRendererWithExpandedViewport>() {
+ return true;
+}
+
+// If we disable image filtering, then a 2x2 bitmap should appear as four
+// huge sharp squares.
+TYPED_TEST(RendererPixelTest, PictureDrawQuadDisableImageFiltering) {
+ // We only care about this in software mode since bilinear filtering is
+ // cheap in hardware.
+ if (!IsSoftwareRenderer<TypeParam>())
+ return;
+
+ gfx::Size pile_tile_size(1000, 1000);
+ gfx::Rect viewport(this->device_viewport_size_);
+ ResourceFormat texture_format = RGBA_8888;
+
+ RenderPass::Id id(1, 1);
+ gfx::Transform transform_to_root;
+ scoped_ptr<RenderPass> pass =
+ CreateTestRenderPass(id, viewport, transform_to_root);
+
+ SkBitmap bitmap;
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config, 2, 2);
+ bitmap.allocPixels();
+ {
+ 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_refptr<FakePicturePileImpl> pile =
+ FakePicturePileImpl::CreateFilledPile(pile_tile_size, viewport.size());
+ SkPaint paint;
+ paint.setFilterLevel(SkPaint::kLow_FilterLevel);
+ pile->add_draw_bitmap_with_paint(bitmap, gfx::Point(), paint);
+ pile->RerecordPile();
+
+ gfx::Transform content_to_target_transform;
+ scoped_ptr<SharedQuadState> shared_state =
+ CreateTestSharedQuadState(content_to_target_transform, viewport);
+
+ scoped_ptr<PictureDrawQuad> quad = PictureDrawQuad::Create();
+ quad->SetNew(shared_state.get(),
+ viewport,
+ gfx::Rect(),
+ gfx::RectF(0, 0, 2, 2),
+ viewport.size(),
+ texture_format,
+ viewport,
+ 1.f,
+ pile);
+ pass->quad_list.push_back(quad.PassAs<DrawQuad>());
+
+ RenderPassList pass_list;
+ pass_list.push_back(pass.Pass());
+
+ this->disable_picture_quad_image_filtering_ = true;
+
+ EXPECT_TRUE(this->RunPixelTest(
+ &pass_list,
+ PixelTest::NoOffscreenContext,
+ base::FilePath(FILE_PATH_LITERAL("four_blue_green_checkers.png")),
+ ExactPixelComparator(true)));
+}
+
+TYPED_TEST(RendererPixelTest, PictureDrawQuadNonIdentityScale) {
gfx::Size pile_tile_size(1000, 1000);
gfx::Rect viewport(this->device_viewport_size_);
- bool use_skia_gpu_backend = this->UseSkiaGPUBackend();
// TODO(enne): the renderer should figure this out on its own.
ResourceFormat texture_format = RGBA_8888;
@@ -1563,7 +1886,6 @@ TYPED_TEST(RendererPixelTestWithSkiaGPUBackend,
texture_format,
green_rect1,
1.f,
- use_skia_gpu_backend,
green_pile);
pass->quad_list.push_back(green_quad1.PassAs<DrawQuad>());
@@ -1576,7 +1898,6 @@ TYPED_TEST(RendererPixelTestWithSkiaGPUBackend,
texture_format,
green_rect2,
1.f,
- use_skia_gpu_backend,
green_pile);
pass->quad_list.push_back(green_quad2.PassAs<DrawQuad>());
@@ -1648,7 +1969,6 @@ TYPED_TEST(RendererPixelTestWithSkiaGPUBackend,
texture_format,
content_union_rect,
contents_scale,
- use_skia_gpu_backend,
pile);
pass->quad_list.push_back(blue_quad.PassAs<DrawQuad>());
@@ -1672,6 +1992,69 @@ TYPED_TEST(RendererPixelTestWithSkiaGPUBackend,
base::FilePath(FILE_PATH_LITERAL("four_blue_green_checkers.png")),
ExactPixelComparator(true)));
}
+
+TYPED_TEST(RendererPixelTest, WrapModeRepeat) {
+ gfx::Rect rect(this->device_viewport_size_);
+
+ RenderPass::Id id(1, 1);
+ scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
+
+ scoped_ptr<SharedQuadState> shared_state =
+ CreateTestSharedQuadState(gfx::Transform(), rect);
+
+ gfx::Rect texture_rect(4, 4);
+ SkPMColor colors[4] = {
+ SkPreMultiplyColor(SkColorSetARGB(255, 0, 255, 0)),
+ SkPreMultiplyColor(SkColorSetARGB(255, 0, 128, 0)),
+ SkPreMultiplyColor(SkColorSetARGB(255, 0, 64, 0)),
+ SkPreMultiplyColor(SkColorSetARGB(255, 0, 0, 0)),
+ };
+ uint32_t pixels[16] = {
+ colors[0], colors[0], colors[1], colors[1],
+ colors[0], colors[0], colors[1], colors[1],
+ colors[2], colors[2], colors[3], colors[3],
+ colors[2], colors[2], colors[3], colors[3],
+ };
+ ResourceProvider::ResourceId resource =
+ this->resource_provider_->CreateResource(
+ texture_rect.size(),
+ GL_REPEAT,
+ ResourceProvider::TextureUsageAny,
+ RGBA_8888);
+ this->resource_provider_->SetPixels(
+ resource,
+ reinterpret_cast<uint8_t*>(pixels),
+ texture_rect,
+ texture_rect,
+ gfx::Vector2d());
+
+ float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+ scoped_ptr<TextureDrawQuad> texture_quad = TextureDrawQuad::Create();
+ texture_quad->SetNew(
+ shared_state.get(),
+ gfx::Rect(this->device_viewport_size_),
+ gfx::Rect(),
+ resource,
+ true, // premultiplied_alpha
+ gfx::PointF(0.0f, 0.0f), // uv_top_left
+ gfx::PointF( // uv_bottom_right
+ this->device_viewport_size_.width() / texture_rect.width(),
+ this->device_viewport_size_.height() / texture_rect.height()),
+ SK_ColorWHITE,
+ vertex_opacity,
+ false); // flipped
+ pass->quad_list.push_back(texture_quad.PassAs<DrawQuad>());
+
+ RenderPassList pass_list;
+ pass_list.push_back(pass.Pass());
+
+ EXPECT_TRUE(this->RunPixelTest(
+ &pass_list,
+ PixelTest::NoOffscreenContext,
+ base::FilePath(FILE_PATH_LITERAL("wrap_mode_repeat.png")),
+ FuzzyPixelOffByOneComparator(true)));
+}
+
#endif // !defined(OS_ANDROID)
} // namespace
diff --git a/chromium/cc/output/shader.cc b/chromium/cc/output/shader.cc
index beabf8db755..b752f46134d 100644
--- a/chromium/cc/output/shader.cc
+++ b/chromium/cc/output/shader.cc
@@ -9,38 +9,33 @@
#include "base/basictypes.h"
#include "base/logging.h"
#include "cc/output/gl_renderer.h" // For the GLC() macro.
-#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
#include "third_party/khronos/GLES2/gl2.h"
#define SHADER0(Src) #Src
#define VERTEX_SHADER(Src) SetVertexTexCoordPrecision(SHADER0(Src))
-#define FRAGMENT_SHADER(Src) SetFragTexCoordPrecision(precision, SHADER0(Src))
+#define FRAGMENT_SHADER(Src) SetFragmentTexCoordPrecision( \
+ precision, SetFragmentSamplerType(sampler, SHADER0(Src)))
-using WebKit::WebGraphicsContext3D;
+using gpu::gles2::GLES2Interface;
namespace cc {
namespace {
-static void GetProgramUniformLocations(WebGraphicsContext3D* context,
+static void GetProgramUniformLocations(GLES2Interface* context,
unsigned program,
size_t count,
const char** uniforms,
int* locations,
- bool using_bind_uniform,
int* base_uniform_index) {
for (size_t i = 0; i < count; i++) {
- if (using_bind_uniform) {
- locations[i] = (*base_uniform_index)++;
- context->bindUniformLocationCHROMIUM(program, locations[i], uniforms[i]);
- } else {
- locations[i] = context->getUniformLocation(program, uniforms[i]);
- DCHECK_NE(locations[i], -1);
- }
+ locations[i] = (*base_uniform_index)++;
+ context->BindUniformLocationCHROMIUM(program, locations[i], uniforms[i]);
}
}
-static std::string SetFragTexCoordPrecision(
+static std::string SetFragmentTexCoordPrecision(
TexCoordPrecision requested_precision, std::string shader_string) {
switch (requested_precision) {
case TexCoordPrecisionHigh:
@@ -59,7 +54,11 @@ static std::string SetFragTexCoordPrecision(
case TexCoordPrecisionNA:
DCHECK_EQ(shader_string.find("TexCoordPrecision"), std::string::npos);
DCHECK_EQ(shader_string.find("texture2D"), std::string::npos);
+ DCHECK_EQ(shader_string.find("texture2DRect"), std::string::npos);
return shader_string;
+ default:
+ NOTREACHED();
+ break;
}
return shader_string;
}
@@ -73,7 +72,7 @@ static std::string SetVertexTexCoordPrecision(const char* shader_string) {
std::string(shader_string);
}
-TexCoordPrecision TexCoordPrecisionRequired(WebGraphicsContext3D* context,
+TexCoordPrecision TexCoordPrecisionRequired(GLES2Interface* context,
int *highp_threshold_cache,
int highp_threshold_min,
int x, int y) {
@@ -84,7 +83,7 @@ TexCoordPrecision TexCoordPrecisionRequired(WebGraphicsContext3D* context,
// everywhere.
GLint range[2] = { 14, 14 };
GLint precision = 10;
- GLC(context, context->getShaderPrecisionFormat(GL_FRAGMENT_SHADER,
+ GLC(context, context->GetShaderPrecisionFormat(GL_FRAGMENT_SHADER,
GL_MEDIUM_FLOAT,
range, &precision));
*highp_threshold_cache = 1 << precision;
@@ -96,9 +95,46 @@ TexCoordPrecision TexCoordPrecisionRequired(WebGraphicsContext3D* context,
return TexCoordPrecisionMedium;
}
+static std::string SetFragmentSamplerType(
+ SamplerType requested_type, std::string shader_string) {
+ switch (requested_type) {
+ case SamplerType2D:
+ DCHECK_NE(shader_string.find("SamplerType"), std::string::npos);
+ DCHECK_NE(shader_string.find("TextureLookup"), std::string::npos);
+ return
+ "#define SamplerType sampler2D\n"
+ "#define TextureLookup texture2D\n" +
+ shader_string;
+ case SamplerType2DRect:
+ DCHECK_NE(shader_string.find("SamplerType"), std::string::npos);
+ DCHECK_NE(shader_string.find("TextureLookup"), std::string::npos);
+ return
+ "#extension GL_ARB_texture_rectangle : require\n"
+ "#define SamplerType sampler2DRect\n"
+ "#define TextureLookup texture2DRect\n" +
+ shader_string;
+ case SamplerTypeExternalOES:
+ DCHECK_NE(shader_string.find("SamplerType"), std::string::npos);
+ DCHECK_NE(shader_string.find("TextureLookup"), std::string::npos);
+ return
+ "#extension GL_OES_EGL_image_external : require\n"
+ "#define SamplerType samplerExternalOES\n"
+ "#define TextureLookup texture2D\n" +
+ shader_string;
+ case SamplerTypeNA:
+ DCHECK_EQ(shader_string.find("SamplerType"), std::string::npos);
+ DCHECK_EQ(shader_string.find("TextureLookup"), std::string::npos);
+ return shader_string;
+ default:
+ NOTREACHED();
+ break;
+ }
+ return shader_string;
+}
+
} // namespace
-TexCoordPrecision TexCoordPrecisionRequired(WebGraphicsContext3D* context,
+TexCoordPrecision TexCoordPrecisionRequired(GLES2Interface* context,
int *highp_threshold_cache,
int highp_threshold_min,
gfx::Point max_coordinate) {
@@ -107,7 +143,7 @@ TexCoordPrecision TexCoordPrecisionRequired(WebGraphicsContext3D* context,
max_coordinate.x(), max_coordinate.y());
}
-TexCoordPrecision TexCoordPrecisionRequired(WebGraphicsContext3D* context,
+TexCoordPrecision TexCoordPrecisionRequired(GLES2Interface* context,
int *highp_threshold_cache,
int highp_threshold_min,
gfx::Size max_size) {
@@ -119,9 +155,8 @@ TexCoordPrecision TexCoordPrecisionRequired(WebGraphicsContext3D* context,
VertexShaderPosTex::VertexShaderPosTex()
: matrix_location_(-1) {}
-void VertexShaderPosTex::Init(WebGraphicsContext3D* context,
+void VertexShaderPosTex::Init(GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index) {
static const char* uniforms[] = {
"matrix",
@@ -133,7 +168,6 @@ void VertexShaderPosTex::Init(WebGraphicsContext3D* context,
arraysize(uniforms),
uniforms,
locations,
- using_bind_uniform,
base_uniform_index);
matrix_location_ = locations[0];
}
@@ -155,9 +189,8 @@ VertexShaderPosTexYUVStretch::VertexShaderPosTexYUVStretch()
: matrix_location_(-1),
tex_scale_location_(-1) {}
-void VertexShaderPosTexYUVStretch::Init(WebGraphicsContext3D* context,
+void VertexShaderPosTexYUVStretch::Init(GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index) {
static const char* uniforms[] = {
"matrix",
@@ -170,7 +203,6 @@ void VertexShaderPosTexYUVStretch::Init(WebGraphicsContext3D* context,
arraysize(uniforms),
uniforms,
locations,
- using_bind_uniform,
base_uniform_index);
matrix_location_ = locations[0];
tex_scale_location_ = locations[1];
@@ -194,9 +226,8 @@ std::string VertexShaderPosTexYUVStretch::GetShaderString() const {
VertexShaderPos::VertexShaderPos()
: matrix_location_(-1) {}
-void VertexShaderPos::Init(WebGraphicsContext3D* context,
+void VertexShaderPos::Init(GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index) {
static const char* uniforms[] = {
"matrix",
@@ -208,7 +239,6 @@ void VertexShaderPos::Init(WebGraphicsContext3D* context,
arraysize(uniforms),
uniforms,
locations,
- using_bind_uniform,
base_uniform_index);
matrix_location_ = locations[0];
}
@@ -228,9 +258,8 @@ VertexShaderPosTexTransform::VertexShaderPosTexTransform()
tex_transform_location_(-1),
vertex_opacity_location_(-1) {}
-void VertexShaderPosTexTransform::Init(WebGraphicsContext3D* context,
+void VertexShaderPosTexTransform::Init(GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index) {
static const char* uniforms[] = {
"matrix",
@@ -244,7 +273,6 @@ void VertexShaderPosTexTransform::Init(WebGraphicsContext3D* context,
arraysize(uniforms),
uniforms,
locations,
- using_bind_uniform,
base_uniform_index);
matrix_location_ = locations[0];
tex_transform_location_ = locations[1];
@@ -286,9 +314,8 @@ VertexShaderQuad::VertexShaderQuad()
: matrix_location_(-1),
quad_location_(-1) {}
-void VertexShaderQuad::Init(WebGraphicsContext3D* context,
+void VertexShaderQuad::Init(GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index) {
static const char* uniforms[] = {
"matrix",
@@ -301,7 +328,6 @@ void VertexShaderQuad::Init(WebGraphicsContext3D* context,
arraysize(uniforms),
uniforms,
locations,
- using_bind_uniform,
base_uniform_index);
matrix_location_ = locations[0];
quad_location_ = locations[1];
@@ -345,9 +371,8 @@ VertexShaderQuadAA::VertexShaderQuadAA()
quad_location_(-1),
edge_location_(-1) {}
-void VertexShaderQuadAA::Init(WebGraphicsContext3D* context,
+void VertexShaderQuadAA::Init(GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index) {
static const char* uniforms[] = {
"matrix",
@@ -362,7 +387,6 @@ void VertexShaderQuadAA::Init(WebGraphicsContext3D* context,
arraysize(uniforms),
uniforms,
locations,
- using_bind_uniform,
base_uniform_index);
matrix_location_ = locations[0];
viewport_location_ = locations[1];
@@ -404,9 +428,8 @@ VertexShaderQuadTexTransformAA::VertexShaderQuadTexTransformAA()
edge_location_(-1),
tex_transform_location_(-1) {}
-void VertexShaderQuadTexTransformAA::Init(WebGraphicsContext3D* context,
+void VertexShaderQuadTexTransformAA::Init(GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index) {
static const char* uniforms[] = {
"matrix",
@@ -422,7 +445,6 @@ void VertexShaderQuadTexTransformAA::Init(WebGraphicsContext3D* context,
arraysize(uniforms),
uniforms,
locations,
- using_bind_uniform,
base_uniform_index);
matrix_location_ = locations[0];
viewport_location_ = locations[1];
@@ -466,9 +488,8 @@ VertexShaderTile::VertexShaderTile()
quad_location_(-1),
vertex_tex_transform_location_(-1) {}
-void VertexShaderTile::Init(WebGraphicsContext3D* context,
+void VertexShaderTile::Init(GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index) {
static const char* uniforms[] = {
"matrix",
@@ -482,7 +503,6 @@ void VertexShaderTile::Init(WebGraphicsContext3D* context,
arraysize(uniforms),
uniforms,
locations,
- using_bind_uniform,
base_uniform_index);
matrix_location_ = locations[0];
quad_location_ = locations[1];
@@ -512,9 +532,8 @@ VertexShaderTileAA::VertexShaderTileAA()
edge_location_(-1),
vertex_tex_transform_location_(-1) {}
-void VertexShaderTileAA::Init(WebGraphicsContext3D* context,
+void VertexShaderTileAA::Init(GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index) {
static const char* uniforms[] = {
"matrix",
@@ -530,7 +549,6 @@ void VertexShaderTileAA::Init(WebGraphicsContext3D* context,
arraysize(uniforms),
uniforms,
locations,
- using_bind_uniform,
base_uniform_index);
matrix_location_ = locations[0];
viewport_location_ = locations[1];
@@ -573,9 +591,8 @@ VertexShaderVideoTransform::VertexShaderVideoTransform()
: matrix_location_(-1),
tex_matrix_location_(-1) {}
-void VertexShaderVideoTransform::Init(WebGraphicsContext3D* context,
+void VertexShaderVideoTransform::Init(GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index) {
static const char* uniforms[] = {
"matrix",
@@ -588,7 +605,6 @@ void VertexShaderVideoTransform::Init(WebGraphicsContext3D* context,
arraysize(uniforms),
uniforms,
locations,
- using_bind_uniform,
base_uniform_index);
matrix_location_ = locations[0];
tex_matrix_location_ = locations[1];
@@ -613,9 +629,8 @@ FragmentTexAlphaBinding::FragmentTexAlphaBinding()
: sampler_location_(-1),
alpha_location_(-1) {}
-void FragmentTexAlphaBinding::Init(WebGraphicsContext3D* context,
+void FragmentTexAlphaBinding::Init(GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index) {
static const char* uniforms[] = {
"s_texture",
@@ -628,7 +643,6 @@ void FragmentTexAlphaBinding::Init(WebGraphicsContext3D* context,
arraysize(uniforms),
uniforms,
locations,
- using_bind_uniform,
base_uniform_index);
sampler_location_ = locations[0];
alpha_location_ = locations[1];
@@ -640,9 +654,8 @@ FragmentTexColorMatrixAlphaBinding::FragmentTexColorMatrixAlphaBinding()
color_matrix_location_(-1),
color_offset_location_(-1) {}
-void FragmentTexColorMatrixAlphaBinding::Init(WebGraphicsContext3D* context,
+void FragmentTexColorMatrixAlphaBinding::Init(GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index) {
static const char* uniforms[] = {
"s_texture",
@@ -657,7 +670,6 @@ void FragmentTexColorMatrixAlphaBinding::Init(WebGraphicsContext3D* context,
arraysize(uniforms),
uniforms,
locations,
- using_bind_uniform,
base_uniform_index);
sampler_location_ = locations[0];
alpha_location_ = locations[1];
@@ -668,9 +680,8 @@ void FragmentTexColorMatrixAlphaBinding::Init(WebGraphicsContext3D* context,
FragmentTexOpaqueBinding::FragmentTexOpaqueBinding()
: sampler_location_(-1) {}
-void FragmentTexOpaqueBinding::Init(WebGraphicsContext3D* context,
+void FragmentTexOpaqueBinding::Init(GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index) {
static const char* uniforms[] = {
"s_texture",
@@ -682,73 +693,35 @@ void FragmentTexOpaqueBinding::Init(WebGraphicsContext3D* context,
arraysize(uniforms),
uniforms,
locations,
- using_bind_uniform,
- base_uniform_index);
- sampler_location_ = locations[0];
-}
-
-FragmentShaderOESImageExternal::FragmentShaderOESImageExternal()
- : sampler_location_(-1) {}
-
-void FragmentShaderOESImageExternal::Init(WebGraphicsContext3D* context,
- unsigned program,
- bool using_bind_uniform,
- int* base_uniform_index) {
- static const char* uniforms[] = {
- "s_texture",
- };
- int locations[arraysize(uniforms)];
-
- GetProgramUniformLocations(context,
- program,
- arraysize(uniforms),
- uniforms,
- locations,
- using_bind_uniform,
base_uniform_index);
sampler_location_ = locations[0];
}
-std::string FragmentShaderOESImageExternal::GetShaderString(
- TexCoordPrecision precision) const {
- // Cannot use the SHADER() macro because of the '#' char
- return "#extension GL_OES_EGL_image_external : require\n" +
- FRAGMENT_SHADER(
- precision mediump float;
- varying TexCoordPrecision vec2 v_texCoord;
- uniform samplerExternalOES s_texture;
- void main() {
- vec4 texColor = texture2D(s_texture, v_texCoord);
- gl_FragColor = texColor;
- }
- ); // NOLINT(whitespace/parens)
-}
-
std::string FragmentShaderRGBATexAlpha::GetShaderString(
- TexCoordPrecision precision) const {
+ TexCoordPrecision precision, SamplerType sampler) const {
return FRAGMENT_SHADER(
precision mediump float;
varying TexCoordPrecision vec2 v_texCoord;
- uniform sampler2D s_texture;
+ uniform SamplerType s_texture;
uniform float alpha;
void main() {
- vec4 texColor = texture2D(s_texture, v_texCoord);
+ vec4 texColor = TextureLookup(s_texture, v_texCoord);
gl_FragColor = texColor * alpha;
}
); // NOLINT(whitespace/parens)
}
std::string FragmentShaderRGBATexColorMatrixAlpha::GetShaderString(
- TexCoordPrecision precision) const {
+ TexCoordPrecision precision, SamplerType sampler) const {
return FRAGMENT_SHADER(
precision mediump float;
varying TexCoordPrecision vec2 v_texCoord;
- uniform sampler2D s_texture;
+ uniform SamplerType s_texture;
uniform float alpha;
uniform mat4 colorMatrix;
uniform vec4 colorOffset;
void main() {
- vec4 texColor = texture2D(s_texture, v_texCoord);
+ vec4 texColor = TextureLookup(s_texture, v_texCoord);
float nonZeroAlpha = max(texColor.a, 0.00001);
texColor = vec4(texColor.rgb / nonZeroAlpha, nonZeroAlpha);
texColor = colorMatrix * texColor + colorOffset;
@@ -760,28 +733,28 @@ std::string FragmentShaderRGBATexColorMatrixAlpha::GetShaderString(
}
std::string FragmentShaderRGBATexVaryingAlpha::GetShaderString(
- TexCoordPrecision precision) const {
+ TexCoordPrecision precision, SamplerType sampler) const {
return FRAGMENT_SHADER(
precision mediump float;
varying TexCoordPrecision vec2 v_texCoord;
varying float v_alpha;
- uniform sampler2D s_texture;
+ uniform SamplerType s_texture;
void main() {
- vec4 texColor = texture2D(s_texture, v_texCoord);
+ vec4 texColor = TextureLookup(s_texture, v_texCoord);
gl_FragColor = texColor * v_alpha;
}
); // NOLINT(whitespace/parens)
}
std::string FragmentShaderRGBATexPremultiplyAlpha::GetShaderString(
- TexCoordPrecision precision) const {
+ TexCoordPrecision precision, SamplerType sampler) const {
return FRAGMENT_SHADER(
precision mediump float;
varying TexCoordPrecision vec2 v_texCoord;
varying float v_alpha;
- uniform sampler2D s_texture;
+ uniform SamplerType s_texture;
void main() {
- vec4 texColor = texture2D(s_texture, v_texCoord);
+ vec4 texColor = TextureLookup(s_texture, v_texCoord);
texColor.rgb *= texColor.a;
gl_FragColor = texColor * v_alpha;
}
@@ -793,9 +766,8 @@ FragmentTexBackgroundBinding::FragmentTexBackgroundBinding()
sampler_location_(-1) {
}
-void FragmentTexBackgroundBinding::Init(WebGraphicsContext3D* context,
+void FragmentTexBackgroundBinding::Init(GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index) {
static const char* uniforms[] = {
"s_texture",
@@ -808,7 +780,6 @@ void FragmentTexBackgroundBinding::Init(WebGraphicsContext3D* context,
arraysize(uniforms),
uniforms,
locations,
- using_bind_uniform,
base_uniform_index);
sampler_location_ = locations[0];
@@ -819,15 +790,15 @@ void FragmentTexBackgroundBinding::Init(WebGraphicsContext3D* context,
}
std::string FragmentShaderTexBackgroundVaryingAlpha::GetShaderString(
- TexCoordPrecision precision) const {
+ TexCoordPrecision precision, SamplerType sampler) const {
return FRAGMENT_SHADER(
precision mediump float;
varying TexCoordPrecision vec2 v_texCoord;
varying float v_alpha;
uniform vec4 background_color;
- uniform sampler2D s_texture;
+ uniform SamplerType s_texture;
void main() {
- vec4 texColor = texture2D(s_texture, v_texCoord);
+ vec4 texColor = TextureLookup(s_texture, v_texCoord);
texColor += background_color * (1.0 - texColor.a);
gl_FragColor = texColor * v_alpha;
}
@@ -835,15 +806,15 @@ std::string FragmentShaderTexBackgroundVaryingAlpha::GetShaderString(
}
std::string FragmentShaderTexBackgroundPremultiplyAlpha::GetShaderString(
- TexCoordPrecision precision) const {
+ TexCoordPrecision precision, SamplerType sampler) const {
return FRAGMENT_SHADER(
precision mediump float;
varying TexCoordPrecision vec2 v_texCoord;
varying float v_alpha;
uniform vec4 background_color;
- uniform sampler2D s_texture;
+ uniform SamplerType s_texture;
void main() {
- vec4 texColor = texture2D(s_texture, v_texCoord);
+ vec4 texColor = TextureLookup(s_texture, v_texCoord);
texColor.rgb *= texColor.a;
texColor += background_color * (1.0 - texColor.a);
gl_FragColor = texColor * v_alpha;
@@ -851,55 +822,40 @@ std::string FragmentShaderTexBackgroundPremultiplyAlpha::GetShaderString(
); // NOLINT(whitespace/parens)
}
-std::string FragmentShaderRGBATexRectVaryingAlpha::GetShaderString(
- TexCoordPrecision precision) const {
- return "#extension GL_ARB_texture_rectangle : require\n" +
- FRAGMENT_SHADER(
- precision mediump float;
- varying TexCoordPrecision vec2 v_texCoord;
- varying float v_alpha;
- uniform sampler2DRect s_texture;
- void main() {
- vec4 texColor = texture2DRect(s_texture, v_texCoord);
- gl_FragColor = texColor * v_alpha;
- }
- ); // NOLINT(whitespace/parens)
-}
-
std::string FragmentShaderRGBATexOpaque::GetShaderString(
- TexCoordPrecision precision) const {
+ TexCoordPrecision precision, SamplerType sampler) const {
return FRAGMENT_SHADER(
precision mediump float;
varying TexCoordPrecision vec2 v_texCoord;
- uniform sampler2D s_texture;
+ uniform SamplerType s_texture;
void main() {
- vec4 texColor = texture2D(s_texture, v_texCoord);
+ vec4 texColor = TextureLookup(s_texture, v_texCoord);
gl_FragColor = vec4(texColor.rgb, 1.0);
}
); // NOLINT(whitespace/parens)
}
std::string FragmentShaderRGBATex::GetShaderString(
- TexCoordPrecision precision) const {
+ TexCoordPrecision precision, SamplerType sampler) const {
return FRAGMENT_SHADER(
precision mediump float;
varying TexCoordPrecision vec2 v_texCoord;
- uniform sampler2D s_texture;
+ uniform SamplerType s_texture;
void main() {
- gl_FragColor = texture2D(s_texture, v_texCoord);
+ gl_FragColor = TextureLookup(s_texture, v_texCoord);
}
); // NOLINT(whitespace/parens)
}
std::string FragmentShaderRGBATexSwizzleAlpha::GetShaderString(
- TexCoordPrecision precision) const {
+ TexCoordPrecision precision, SamplerType sampler) const {
return FRAGMENT_SHADER(
precision mediump float;
varying TexCoordPrecision vec2 v_texCoord;
- uniform sampler2D s_texture;
+ uniform SamplerType s_texture;
uniform float alpha;
void main() {
- vec4 texColor = texture2D(s_texture, v_texCoord);
+ vec4 texColor = TextureLookup(s_texture, v_texCoord);
gl_FragColor =
vec4(texColor.z, texColor.y, texColor.x, texColor.w) * alpha;
}
@@ -907,13 +863,13 @@ std::string FragmentShaderRGBATexSwizzleAlpha::GetShaderString(
}
std::string FragmentShaderRGBATexSwizzleOpaque::GetShaderString(
- TexCoordPrecision precision) const {
+ TexCoordPrecision precision, SamplerType sampler) const {
return FRAGMENT_SHADER(
precision mediump float;
varying TexCoordPrecision vec2 v_texCoord;
- uniform sampler2D s_texture;
+ uniform SamplerType s_texture;
void main() {
- vec4 texColor = texture2D(s_texture, v_texCoord);
+ vec4 texColor = TextureLookup(s_texture, v_texCoord);
gl_FragColor = vec4(texColor.z, texColor.y, texColor.x, 1.0);
}
); // NOLINT(whitespace/parens)
@@ -923,9 +879,8 @@ FragmentShaderRGBATexAlphaAA::FragmentShaderRGBATexAlphaAA()
: sampler_location_(-1),
alpha_location_(-1) {}
-void FragmentShaderRGBATexAlphaAA::Init(WebGraphicsContext3D* context,
+void FragmentShaderRGBATexAlphaAA::Init(GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index) {
static const char* uniforms[] = {
"s_texture",
@@ -938,23 +893,22 @@ void FragmentShaderRGBATexAlphaAA::Init(WebGraphicsContext3D* context,
arraysize(uniforms),
uniforms,
locations,
- using_bind_uniform,
base_uniform_index);
sampler_location_ = locations[0];
alpha_location_ = locations[1];
}
std::string FragmentShaderRGBATexAlphaAA::GetShaderString(
- TexCoordPrecision precision) const {
+ TexCoordPrecision precision, SamplerType sampler) const {
return FRAGMENT_SHADER(
precision mediump float;
- uniform sampler2D s_texture;
+ uniform SamplerType s_texture;
uniform float alpha;
varying TexCoordPrecision vec2 v_texCoord;
varying TexCoordPrecision vec4 edge_dist[2]; // 8 edge distances.
void main() {
- vec4 texColor = texture2D(s_texture, v_texCoord);
+ vec4 texColor = TextureLookup(s_texture, v_texCoord);
vec4 d4 = min(edge_dist[0], edge_dist[1]);
vec2 d2 = min(d4.xz, d4.yw);
float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
@@ -968,9 +922,8 @@ FragmentTexClampAlphaAABinding::FragmentTexClampAlphaAABinding()
alpha_location_(-1),
fragment_tex_transform_location_(-1) {}
-void FragmentTexClampAlphaAABinding::Init(WebGraphicsContext3D* context,
+void FragmentTexClampAlphaAABinding::Init(GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index) {
static const char* uniforms[] = {
"s_texture",
@@ -984,7 +937,6 @@ void FragmentTexClampAlphaAABinding::Init(WebGraphicsContext3D* context,
arraysize(uniforms),
uniforms,
locations,
- using_bind_uniform,
base_uniform_index);
sampler_location_ = locations[0];
alpha_location_ = locations[1];
@@ -992,10 +944,10 @@ void FragmentTexClampAlphaAABinding::Init(WebGraphicsContext3D* context,
}
std::string FragmentShaderRGBATexClampAlphaAA::GetShaderString(
- TexCoordPrecision precision) const {
+ TexCoordPrecision precision, SamplerType sampler) const {
return FRAGMENT_SHADER(
precision mediump float;
- uniform sampler2D s_texture;
+ uniform SamplerType s_texture;
uniform float alpha;
uniform TexCoordPrecision vec4 fragmentTexTransform;
varying TexCoordPrecision vec2 v_texCoord;
@@ -1005,7 +957,7 @@ std::string FragmentShaderRGBATexClampAlphaAA::GetShaderString(
TexCoordPrecision vec2 texCoord =
clamp(v_texCoord, 0.0, 1.0) * fragmentTexTransform.zw +
fragmentTexTransform.xy;
- vec4 texColor = texture2D(s_texture, texCoord);
+ vec4 texColor = TextureLookup(s_texture, texCoord);
vec4 d4 = min(edge_dist[0], edge_dist[1]);
vec2 d2 = min(d4.xz, d4.yw);
float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
@@ -1015,10 +967,10 @@ std::string FragmentShaderRGBATexClampAlphaAA::GetShaderString(
}
std::string FragmentShaderRGBATexClampSwizzleAlphaAA::GetShaderString(
- TexCoordPrecision precision) const {
+ TexCoordPrecision precision, SamplerType sampler) const {
return FRAGMENT_SHADER(
precision mediump float;
- uniform sampler2D s_texture;
+ uniform SamplerType s_texture;
uniform float alpha;
uniform TexCoordPrecision vec4 fragmentTexTransform;
varying TexCoordPrecision vec2 v_texCoord;
@@ -1028,7 +980,7 @@ std::string FragmentShaderRGBATexClampSwizzleAlphaAA::GetShaderString(
TexCoordPrecision vec2 texCoord =
clamp(v_texCoord, 0.0, 1.0) * fragmentTexTransform.zw +
fragmentTexTransform.xy;
- vec4 texColor = texture2D(s_texture, texCoord);
+ vec4 texColor = TextureLookup(s_texture, texCoord);
vec4 d4 = min(edge_dist[0], edge_dist[1]);
vec2 d2 = min(d4.xz, d4.yw);
float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
@@ -1044,9 +996,8 @@ FragmentShaderRGBATexAlphaMask::FragmentShaderRGBATexAlphaMask()
alpha_location_(-1),
mask_tex_coord_scale_location_(-1) {}
-void FragmentShaderRGBATexAlphaMask::Init(WebGraphicsContext3D* context,
+void FragmentShaderRGBATexAlphaMask::Init(GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index) {
static const char* uniforms[] = {
"s_texture",
@@ -1062,7 +1013,6 @@ void FragmentShaderRGBATexAlphaMask::Init(WebGraphicsContext3D* context,
arraysize(uniforms),
uniforms,
locations,
- using_bind_uniform,
base_uniform_index);
sampler_location_ = locations[0];
mask_sampler_location_ = locations[1];
@@ -1072,21 +1022,21 @@ void FragmentShaderRGBATexAlphaMask::Init(WebGraphicsContext3D* context,
}
std::string FragmentShaderRGBATexAlphaMask::GetShaderString(
- TexCoordPrecision precision) const {
+ TexCoordPrecision precision, SamplerType sampler) const {
return FRAGMENT_SHADER(
precision mediump float;
varying TexCoordPrecision vec2 v_texCoord;
- uniform sampler2D s_texture;
- uniform sampler2D s_mask;
+ uniform SamplerType s_texture;
+ uniform SamplerType s_mask;
uniform TexCoordPrecision vec2 maskTexCoordScale;
uniform TexCoordPrecision vec2 maskTexCoordOffset;
uniform float alpha;
void main() {
- vec4 texColor = texture2D(s_texture, v_texCoord);
+ vec4 texColor = TextureLookup(s_texture, v_texCoord);
TexCoordPrecision vec2 maskTexCoord =
vec2(maskTexCoordOffset.x + v_texCoord.x * maskTexCoordScale.x,
maskTexCoordOffset.y + v_texCoord.y * maskTexCoordScale.y);
- vec4 maskColor = texture2D(s_mask, maskTexCoord);
+ vec4 maskColor = TextureLookup(s_mask, maskTexCoord);
gl_FragColor = texColor * alpha * maskColor.w;
}
); // NOLINT(whitespace/parens)
@@ -1099,9 +1049,8 @@ FragmentShaderRGBATexAlphaMaskAA::FragmentShaderRGBATexAlphaMaskAA()
mask_tex_coord_scale_location_(-1),
mask_tex_coord_offset_location_(-1) {}
-void FragmentShaderRGBATexAlphaMaskAA::Init(WebGraphicsContext3D* context,
+void FragmentShaderRGBATexAlphaMaskAA::Init(GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index) {
static const char* uniforms[] = {
"s_texture",
@@ -1117,7 +1066,6 @@ void FragmentShaderRGBATexAlphaMaskAA::Init(WebGraphicsContext3D* context,
arraysize(uniforms),
uniforms,
locations,
- using_bind_uniform,
base_uniform_index);
sampler_location_ = locations[0];
mask_sampler_location_ = locations[1];
@@ -1127,11 +1075,11 @@ void FragmentShaderRGBATexAlphaMaskAA::Init(WebGraphicsContext3D* context,
}
std::string FragmentShaderRGBATexAlphaMaskAA::GetShaderString(
- TexCoordPrecision precision) const {
+ TexCoordPrecision precision, SamplerType sampler) const {
return FRAGMENT_SHADER(
precision mediump float;
- uniform sampler2D s_texture;
- uniform sampler2D s_mask;
+ uniform SamplerType s_texture;
+ uniform SamplerType s_mask;
uniform TexCoordPrecision vec2 maskTexCoordScale;
uniform TexCoordPrecision vec2 maskTexCoordOffset;
uniform float alpha;
@@ -1139,11 +1087,11 @@ std::string FragmentShaderRGBATexAlphaMaskAA::GetShaderString(
varying TexCoordPrecision vec4 edge_dist[2]; // 8 edge distances.
void main() {
- vec4 texColor = texture2D(s_texture, v_texCoord);
+ vec4 texColor = TextureLookup(s_texture, v_texCoord);
TexCoordPrecision vec2 maskTexCoord =
vec2(maskTexCoordOffset.x + v_texCoord.x * maskTexCoordScale.x,
maskTexCoordOffset.y + v_texCoord.y * maskTexCoordScale.y);
- vec4 maskColor = texture2D(s_mask, maskTexCoord);
+ vec4 maskColor = TextureLookup(s_mask, maskTexCoord);
vec4 d4 = min(edge_dist[0], edge_dist[1]);
vec2 d2 = min(d4.xz, d4.yw);
float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
@@ -1162,9 +1110,8 @@ FragmentShaderRGBATexAlphaMaskColorMatrixAA::
color_offset_location_(-1) {}
void FragmentShaderRGBATexAlphaMaskColorMatrixAA::Init(
- WebGraphicsContext3D* context,
+ GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index) {
static const char* uniforms[] = {
"s_texture",
@@ -1182,7 +1129,6 @@ void FragmentShaderRGBATexAlphaMaskColorMatrixAA::Init(
arraysize(uniforms),
uniforms,
locations,
- using_bind_uniform,
base_uniform_index);
sampler_location_ = locations[0];
mask_sampler_location_ = locations[1];
@@ -1194,11 +1140,11 @@ void FragmentShaderRGBATexAlphaMaskColorMatrixAA::Init(
}
std::string FragmentShaderRGBATexAlphaMaskColorMatrixAA::GetShaderString(
- TexCoordPrecision precision) const {
+ TexCoordPrecision precision, SamplerType sampler) const {
return FRAGMENT_SHADER(
precision mediump float;
- uniform sampler2D s_texture;
- uniform sampler2D s_mask;
+ uniform SamplerType s_texture;
+ uniform SamplerType s_mask;
uniform vec2 maskTexCoordScale;
uniform vec2 maskTexCoordOffset;
uniform mat4 colorMatrix;
@@ -1208,7 +1154,7 @@ std::string FragmentShaderRGBATexAlphaMaskColorMatrixAA::GetShaderString(
varying TexCoordPrecision vec4 edge_dist[2]; // 8 edge distances.
void main() {
- vec4 texColor = texture2D(s_texture, v_texCoord);
+ vec4 texColor = TextureLookup(s_texture, v_texCoord);
float nonZeroAlpha = max(texColor.a, 0.00001);
texColor = vec4(texColor.rgb / nonZeroAlpha, nonZeroAlpha);
texColor = colorMatrix * texColor + colorOffset;
@@ -1217,7 +1163,7 @@ std::string FragmentShaderRGBATexAlphaMaskColorMatrixAA::GetShaderString(
TexCoordPrecision vec2 maskTexCoord =
vec2(maskTexCoordOffset.x + v_texCoord.x * maskTexCoordScale.x,
maskTexCoordOffset.y + v_texCoord.y * maskTexCoordScale.y);
- vec4 maskColor = texture2D(s_mask, maskTexCoord);
+ vec4 maskColor = TextureLookup(s_mask, maskTexCoord);
vec4 d4 = min(edge_dist[0], edge_dist[1]);
vec2 d2 = min(d4.xz, d4.yw);
float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
@@ -1234,9 +1180,8 @@ FragmentShaderRGBATexAlphaColorMatrixAA::
color_offset_location_(-1) {}
void FragmentShaderRGBATexAlphaColorMatrixAA::Init(
- WebGraphicsContext3D* context,
+ GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index) {
static const char* uniforms[] = {
"s_texture",
@@ -1251,7 +1196,6 @@ void FragmentShaderRGBATexAlphaColorMatrixAA::Init(
arraysize(uniforms),
uniforms,
locations,
- using_bind_uniform,
base_uniform_index);
sampler_location_ = locations[0];
alpha_location_ = locations[1];
@@ -1260,10 +1204,10 @@ void FragmentShaderRGBATexAlphaColorMatrixAA::Init(
}
std::string FragmentShaderRGBATexAlphaColorMatrixAA::GetShaderString(
- TexCoordPrecision precision) const {
+ TexCoordPrecision precision, SamplerType sampler) const {
return FRAGMENT_SHADER(
precision mediump float;
- uniform sampler2D s_texture;
+ uniform SamplerType s_texture;
uniform float alpha;
uniform mat4 colorMatrix;
uniform vec4 colorOffset;
@@ -1271,7 +1215,7 @@ std::string FragmentShaderRGBATexAlphaColorMatrixAA::GetShaderString(
varying TexCoordPrecision vec4 edge_dist[2]; // 8 edge distances.
void main() {
- vec4 texColor = texture2D(s_texture, v_texCoord);
+ vec4 texColor = TextureLookup(s_texture, v_texCoord);
float nonZeroAlpha = max(texColor.a, 0.00001);
texColor = vec4(texColor.rgb / nonZeroAlpha, nonZeroAlpha);
texColor = colorMatrix * texColor + colorOffset;
@@ -1293,9 +1237,8 @@ FragmentShaderRGBATexAlphaMaskColorMatrix::
mask_tex_coord_scale_location_(-1) {}
void FragmentShaderRGBATexAlphaMaskColorMatrix::Init(
- WebGraphicsContext3D* context,
+ GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index) {
static const char* uniforms[] = {
"s_texture",
@@ -1313,7 +1256,6 @@ void FragmentShaderRGBATexAlphaMaskColorMatrix::Init(
arraysize(uniforms),
uniforms,
locations,
- using_bind_uniform,
base_uniform_index);
sampler_location_ = locations[0];
mask_sampler_location_ = locations[1];
@@ -1325,19 +1267,19 @@ void FragmentShaderRGBATexAlphaMaskColorMatrix::Init(
}
std::string FragmentShaderRGBATexAlphaMaskColorMatrix::GetShaderString(
- TexCoordPrecision precision) const {
+ TexCoordPrecision precision, SamplerType sampler) const {
return FRAGMENT_SHADER(
precision mediump float;
varying TexCoordPrecision vec2 v_texCoord;
- uniform sampler2D s_texture;
- uniform sampler2D s_mask;
+ uniform SamplerType s_texture;
+ uniform SamplerType s_mask;
uniform vec2 maskTexCoordScale;
uniform vec2 maskTexCoordOffset;
uniform mat4 colorMatrix;
uniform vec4 colorOffset;
uniform float alpha;
void main() {
- vec4 texColor = texture2D(s_texture, v_texCoord);
+ vec4 texColor = TextureLookup(s_texture, v_texCoord);
float nonZeroAlpha = max(texColor.a, 0.00001);
texColor = vec4(texColor.rgb / nonZeroAlpha, nonZeroAlpha);
texColor = colorMatrix * texColor + colorOffset;
@@ -1346,7 +1288,7 @@ std::string FragmentShaderRGBATexAlphaMaskColorMatrix::GetShaderString(
TexCoordPrecision vec2 maskTexCoord =
vec2(maskTexCoordOffset.x + v_texCoord.x * maskTexCoordScale.x,
maskTexCoordOffset.y + v_texCoord.y * maskTexCoordScale.y);
- vec4 maskColor = texture2D(s_mask, maskTexCoord);
+ vec4 maskColor = TextureLookup(s_mask, maskTexCoord);
gl_FragColor = texColor * alpha * maskColor.w;
}
); // NOLINT(whitespace/parens)
@@ -1360,9 +1302,8 @@ FragmentShaderYUVVideo::FragmentShaderYUVVideo()
yuv_matrix_location_(-1),
yuv_adj_location_(-1) {}
-void FragmentShaderYUVVideo::Init(WebGraphicsContext3D* context,
+void FragmentShaderYUVVideo::Init(GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index) {
static const char* uniforms[] = {
"y_texture",
@@ -1379,7 +1320,6 @@ void FragmentShaderYUVVideo::Init(WebGraphicsContext3D* context,
arraysize(uniforms),
uniforms,
locations,
- using_bind_uniform,
base_uniform_index);
y_texture_location_ = locations[0];
u_texture_location_ = locations[1];
@@ -1390,21 +1330,21 @@ void FragmentShaderYUVVideo::Init(WebGraphicsContext3D* context,
}
std::string FragmentShaderYUVVideo::GetShaderString(
- TexCoordPrecision precision) const {
+ TexCoordPrecision precision, SamplerType sampler) const {
return FRAGMENT_SHADER(
precision mediump float;
precision mediump int;
varying TexCoordPrecision vec2 v_texCoord;
- uniform sampler2D y_texture;
- uniform sampler2D u_texture;
- uniform sampler2D v_texture;
+ uniform SamplerType y_texture;
+ uniform SamplerType u_texture;
+ uniform SamplerType v_texture;
uniform float alpha;
uniform vec3 yuv_adj;
uniform mat3 yuv_matrix;
void main() {
- float y_raw = texture2D(y_texture, v_texCoord).x;
- float u_unsigned = texture2D(u_texture, v_texCoord).x;
- float v_unsigned = texture2D(v_texture, v_texCoord).x;
+ float y_raw = TextureLookup(y_texture, v_texCoord).x;
+ float u_unsigned = TextureLookup(u_texture, v_texCoord).x;
+ float v_unsigned = TextureLookup(v_texture, v_texCoord).x;
vec3 yuv = vec3(y_raw, u_unsigned, v_unsigned) + yuv_adj;
vec3 rgb = yuv_matrix * yuv;
gl_FragColor = vec4(rgb, 1.0) * alpha;
@@ -1422,9 +1362,8 @@ FragmentShaderYUVAVideo::FragmentShaderYUVAVideo()
yuv_adj_location_(-1) {
}
-void FragmentShaderYUVAVideo::Init(WebGraphicsContext3D* context,
+void FragmentShaderYUVAVideo::Init(GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index) {
static const char* uniforms[] = {
"y_texture",
@@ -1442,7 +1381,6 @@ void FragmentShaderYUVAVideo::Init(WebGraphicsContext3D* context,
arraysize(uniforms),
uniforms,
locations,
- using_bind_uniform,
base_uniform_index);
y_texture_location_ = locations[0];
u_texture_location_ = locations[1];
@@ -1454,23 +1392,23 @@ void FragmentShaderYUVAVideo::Init(WebGraphicsContext3D* context,
}
std::string FragmentShaderYUVAVideo::GetShaderString(
- TexCoordPrecision precision) const {
+ TexCoordPrecision precision, SamplerType sampler) const {
return FRAGMENT_SHADER(
precision mediump float;
precision mediump int;
varying TexCoordPrecision vec2 v_texCoord;
- uniform sampler2D y_texture;
- uniform sampler2D u_texture;
- uniform sampler2D v_texture;
- uniform sampler2D a_texture;
+ uniform SamplerType y_texture;
+ uniform SamplerType u_texture;
+ uniform SamplerType v_texture;
+ uniform SamplerType a_texture;
uniform float alpha;
uniform vec3 yuv_adj;
uniform mat3 yuv_matrix;
void main() {
- float y_raw = texture2D(y_texture, v_texCoord).x;
- float u_unsigned = texture2D(u_texture, v_texCoord).x;
- float v_unsigned = texture2D(v_texture, v_texCoord).x;
- float a_raw = texture2D(a_texture, v_texCoord).x;
+ float y_raw = TextureLookup(y_texture, v_texCoord).x;
+ float u_unsigned = TextureLookup(u_texture, v_texCoord).x;
+ float v_unsigned = TextureLookup(v_texture, v_texCoord).x;
+ float a_raw = TextureLookup(a_texture, v_texCoord).x;
vec3 yuv = vec3(y_raw, u_unsigned, v_unsigned) + yuv_adj;
vec3 rgb = yuv_matrix * yuv;
gl_FragColor = vec4(rgb, 1.0) * (alpha * a_raw);
@@ -1481,9 +1419,8 @@ std::string FragmentShaderYUVAVideo::GetShaderString(
FragmentShaderColor::FragmentShaderColor()
: color_location_(-1) {}
-void FragmentShaderColor::Init(WebGraphicsContext3D* context,
+void FragmentShaderColor::Init(GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index) {
static const char* uniforms[] = {
"color",
@@ -1495,13 +1432,12 @@ void FragmentShaderColor::Init(WebGraphicsContext3D* context,
arraysize(uniforms),
uniforms,
locations,
- using_bind_uniform,
base_uniform_index);
color_location_ = locations[0];
}
std::string FragmentShaderColor::GetShaderString(
- TexCoordPrecision precision) const {
+ TexCoordPrecision precision, SamplerType sampler) const {
return FRAGMENT_SHADER(
precision mediump float;
uniform vec4 color;
@@ -1514,9 +1450,8 @@ std::string FragmentShaderColor::GetShaderString(
FragmentShaderColorAA::FragmentShaderColorAA()
: color_location_(-1) {}
-void FragmentShaderColorAA::Init(WebGraphicsContext3D* context,
+void FragmentShaderColorAA::Init(GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index) {
static const char* uniforms[] = {
"color",
@@ -1528,13 +1463,12 @@ void FragmentShaderColorAA::Init(WebGraphicsContext3D* context,
arraysize(uniforms),
uniforms,
locations,
- using_bind_uniform,
base_uniform_index);
color_location_ = locations[0];
}
std::string FragmentShaderColorAA::GetShaderString(
- TexCoordPrecision precision) const {
+ TexCoordPrecision precision, SamplerType sampler) const {
return FRAGMENT_SHADER(
precision mediump float;
uniform vec4 color;
@@ -1554,9 +1488,8 @@ FragmentShaderCheckerboard::FragmentShaderCheckerboard()
tex_transform_location_(-1),
frequency_location_(-1) {}
-void FragmentShaderCheckerboard::Init(WebGraphicsContext3D* context,
+void FragmentShaderCheckerboard::Init(GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index) {
static const char* uniforms[] = {
"alpha",
@@ -1571,7 +1504,6 @@ void FragmentShaderCheckerboard::Init(WebGraphicsContext3D* context,
arraysize(uniforms),
uniforms,
locations,
- using_bind_uniform,
base_uniform_index);
alpha_location_ = locations[0];
tex_transform_location_ = locations[1];
@@ -1580,7 +1512,7 @@ void FragmentShaderCheckerboard::Init(WebGraphicsContext3D* context,
}
std::string FragmentShaderCheckerboard::GetShaderString(
- TexCoordPrecision precision) const {
+ TexCoordPrecision precision, SamplerType sampler) const {
// Shader based on Example 13-17 of "OpenGL ES 2.0 Programming Guide"
// by Munshi, Ginsburg, Shreiner.
return FRAGMENT_SHADER(
diff --git a/chromium/cc/output/shader.h b/chromium/cc/output/shader.h
index 7135befd389..9473ce8da38 100644
--- a/chromium/cc/output/shader.h
+++ b/chromium/cc/output/shader.h
@@ -16,14 +16,27 @@ class Point;
class Size;
}
-namespace WebKit { class WebGraphicsContext3D; }
+namespace gpu {
+namespace gles2 {
+class GLES2Interface;
+}
+}
namespace cc {
enum TexCoordPrecision {
- TexCoordPrecisionNA,
- TexCoordPrecisionMedium,
- TexCoordPrecisionHigh,
+ TexCoordPrecisionNA = 0,
+ TexCoordPrecisionMedium = 1,
+ TexCoordPrecisionHigh = 2,
+ NumTexCoordPrecisions = 3
+};
+
+enum SamplerType {
+ SamplerTypeNA = 0,
+ SamplerType2D = 1,
+ SamplerType2DRect = 2,
+ SamplerTypeExternalOES = 3,
+ NumSamplerTypes = 4
};
// Note: The highp_threshold_cache must be provided by the caller to make
@@ -31,13 +44,13 @@ enum TexCoordPrecision {
// The caller must make sure to clear highp_threshold_cache to 0, so it can be
// reinitialized, if a new or different context is used.
CC_EXPORT TexCoordPrecision TexCoordPrecisionRequired(
- WebKit::WebGraphicsContext3D* context,
+ gpu::gles2::GLES2Interface* context,
int *highp_threshold_cache,
int highp_threshold_min,
gfx::Point max_coordinate);
CC_EXPORT TexCoordPrecision TexCoordPrecisionRequired(
- WebKit::WebGraphicsContext3D* context,
+ gpu::gles2::GLES2Interface* context,
int *highp_threshold_cache,
int highp_threshold_min,
gfx::Size max_size);
@@ -46,9 +59,8 @@ class VertexShaderPosTex {
public:
VertexShaderPosTex();
- void Init(WebKit::WebGraphicsContext3D* context,
+ void Init(gpu::gles2::GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index);
std::string GetShaderString() const;
@@ -64,9 +76,8 @@ class VertexShaderPosTexYUVStretch {
public:
VertexShaderPosTexYUVStretch();
- void Init(WebKit::WebGraphicsContext3D* context,
+ void Init(gpu::gles2::GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index);
std::string GetShaderString() const;
@@ -84,9 +95,8 @@ class VertexShaderPos {
public:
VertexShaderPos();
- void Init(WebKit::WebGraphicsContext3D* context,
+ void Init(gpu::gles2::GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index);
std::string GetShaderString() const;
@@ -100,9 +110,8 @@ class VertexShaderPos {
class VertexShaderPosTexIdentity {
public:
- void Init(WebKit::WebGraphicsContext3D* context,
+ void Init(gpu::gles2::GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index) {}
std::string GetShaderString() const;
};
@@ -111,9 +120,8 @@ class VertexShaderPosTexTransform {
public:
VertexShaderPosTexTransform();
- void Init(WebKit::WebGraphicsContext3D* context,
+ void Init(gpu::gles2::GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index);
std::string GetShaderString() const;
@@ -133,9 +141,8 @@ class VertexShaderQuad {
public:
VertexShaderQuad();
- void Init(WebKit::WebGraphicsContext3D* context,
+ void Init(gpu::gles2::GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index);
std::string GetShaderString() const;
@@ -155,9 +162,8 @@ class VertexShaderQuadAA {
public:
VertexShaderQuadAA();
- void Init(WebKit::WebGraphicsContext3D* context,
+ void Init(gpu::gles2::GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index);
std::string GetShaderString() const;
@@ -180,9 +186,8 @@ class VertexShaderQuadTexTransformAA {
public:
VertexShaderQuadTexTransformAA();
- void Init(WebKit::WebGraphicsContext3D* context,
+ void Init(gpu::gles2::GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index);
std::string GetShaderString() const;
@@ -206,9 +211,8 @@ class VertexShaderTile {
public:
VertexShaderTile();
- void Init(WebKit::WebGraphicsContext3D* context,
+ void Init(gpu::gles2::GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index);
std::string GetShaderString() const;
@@ -232,9 +236,8 @@ class VertexShaderTileAA {
public:
VertexShaderTileAA();
- void Init(WebKit::WebGraphicsContext3D* context,
+ void Init(gpu::gles2::GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index);
std::string GetShaderString() const;
@@ -260,9 +263,8 @@ class VertexShaderVideoTransform {
public:
VertexShaderVideoTransform();
- void Init(WebKit::WebGraphicsContext3D* context,
+ void Init(gpu::gles2::GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index);
std::string GetShaderString() const;
@@ -280,9 +282,8 @@ class FragmentTexAlphaBinding {
public:
FragmentTexAlphaBinding();
- void Init(WebKit::WebGraphicsContext3D* context,
+ void Init(gpu::gles2::GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index);
int alpha_location() const { return alpha_location_; }
int fragment_tex_transform_location() const { return -1; }
@@ -299,10 +300,9 @@ class FragmentTexColorMatrixAlphaBinding {
public:
FragmentTexColorMatrixAlphaBinding();
- void Init(WebKit::WebGraphicsContext3D* context,
+ void Init(gpu::gles2::GLES2Interface* context,
unsigned program,
- bool usingBindUniform,
- int* baseUniformIndex);
+ int* base_uniform_index);
int alpha_location() const { return alpha_location_; }
int color_matrix_location() const { return color_matrix_location_; }
int color_offset_location() const { return color_offset_location_; }
@@ -320,9 +320,8 @@ class FragmentTexOpaqueBinding {
public:
FragmentTexOpaqueBinding();
- void Init(WebKit::WebGraphicsContext3D* context,
+ void Init(gpu::gles2::GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index);
int alpha_location() const { return -1; }
int fragment_tex_transform_location() const { return -1; }
@@ -339,9 +338,8 @@ class FragmentTexBackgroundBinding {
public:
FragmentTexBackgroundBinding();
- void Init(WebKit::WebGraphicsContext3D* context,
+ void Init(gpu::gles2::GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index);
int background_color_location() const { return background_color_location_; }
int sampler_location() const { return sampler_location_; }
@@ -355,89 +353,78 @@ class FragmentTexBackgroundBinding {
class FragmentShaderRGBATexVaryingAlpha : public FragmentTexOpaqueBinding {
public:
- std::string GetShaderString(TexCoordPrecision precision) const;
+ std::string GetShaderString(
+ TexCoordPrecision precision, SamplerType sampler) const;
};
class FragmentShaderRGBATexPremultiplyAlpha : public FragmentTexOpaqueBinding {
public:
- std::string GetShaderString(TexCoordPrecision precision) const;
+ std::string GetShaderString(
+ TexCoordPrecision precision, SamplerType sampler) const;
};
class FragmentShaderTexBackgroundVaryingAlpha
: public FragmentTexBackgroundBinding {
public:
- std::string GetShaderString(TexCoordPrecision precision) const;
+ std::string GetShaderString(
+ TexCoordPrecision precision, SamplerType sampler) const;
};
class FragmentShaderTexBackgroundPremultiplyAlpha
: public FragmentTexBackgroundBinding {
public:
- std::string GetShaderString(TexCoordPrecision precision) const;
+ std::string GetShaderString(
+ TexCoordPrecision precision, SamplerType sampler) const;
};
class FragmentShaderRGBATexAlpha : public FragmentTexAlphaBinding {
public:
- std::string GetShaderString(TexCoordPrecision precision) const;
+ std::string GetShaderString(
+ TexCoordPrecision precision, SamplerType sampler) const;
};
class FragmentShaderRGBATexColorMatrixAlpha
: public FragmentTexColorMatrixAlphaBinding {
public:
- std::string GetShaderString(TexCoordPrecision precision) const;
-};
-
-class FragmentShaderRGBATexRectVaryingAlpha : public FragmentTexOpaqueBinding {
- public:
- std::string GetShaderString(TexCoordPrecision precision) const;
+ std::string GetShaderString(
+ TexCoordPrecision precision, SamplerType sampler) const;
};
class FragmentShaderRGBATexOpaque : public FragmentTexOpaqueBinding {
public:
- std::string GetShaderString(TexCoordPrecision precision) const;
+ std::string GetShaderString(
+ TexCoordPrecision precision, SamplerType sampler) const;
};
class FragmentShaderRGBATex : public FragmentTexOpaqueBinding {
public:
- std::string GetShaderString(TexCoordPrecision precision) const;
+ std::string GetShaderString(
+ TexCoordPrecision precision, SamplerType sampler) const;
};
// Swizzles the red and blue component of sampled texel with alpha.
class FragmentShaderRGBATexSwizzleAlpha : public FragmentTexAlphaBinding {
public:
- std::string GetShaderString(TexCoordPrecision precision) const;
+ std::string GetShaderString(
+ TexCoordPrecision precision, SamplerType sampler) const;
};
// Swizzles the red and blue component of sampled texel without alpha.
class FragmentShaderRGBATexSwizzleOpaque : public FragmentTexOpaqueBinding {
public:
- std::string GetShaderString(TexCoordPrecision precision) const;
-};
-
-// Fragment shader for external textures.
-class FragmentShaderOESImageExternal : public FragmentTexAlphaBinding {
- public:
- FragmentShaderOESImageExternal();
-
- std::string GetShaderString(TexCoordPrecision precision) const;
- void Init(WebKit::WebGraphicsContext3D* context,
- unsigned program,
- bool using_bind_uniform,
- int* base_uniform_index);
- private:
- int sampler_location_;
-
- DISALLOW_COPY_AND_ASSIGN(FragmentShaderOESImageExternal);
+ std::string GetShaderString(
+ TexCoordPrecision precision, SamplerType sampler) const;
};
class FragmentShaderRGBATexAlphaAA {
public:
FragmentShaderRGBATexAlphaAA();
- void Init(WebKit::WebGraphicsContext3D* context,
+ void Init(gpu::gles2::GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index);
- std::string GetShaderString(TexCoordPrecision precision) const;
+ std::string GetShaderString(
+ TexCoordPrecision precision, SamplerType sampler) const;
int alpha_location() const { return alpha_location_; }
int sampler_location() const { return sampler_location_; }
@@ -453,9 +440,8 @@ class FragmentTexClampAlphaAABinding {
public:
FragmentTexClampAlphaAABinding();
- void Init(WebKit::WebGraphicsContext3D* context,
+ void Init(gpu::gles2::GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index);
int alpha_location() const { return alpha_location_; }
int sampler_location() const { return sampler_location_; }
@@ -474,24 +460,26 @@ class FragmentTexClampAlphaAABinding {
class FragmentShaderRGBATexClampAlphaAA
: public FragmentTexClampAlphaAABinding {
public:
- std::string GetShaderString(TexCoordPrecision precision) const;
+ std::string GetShaderString(
+ TexCoordPrecision precision, SamplerType sampler) const;
};
// Swizzles the red and blue component of sampled texel.
class FragmentShaderRGBATexClampSwizzleAlphaAA
: public FragmentTexClampAlphaAABinding {
public:
- std::string GetShaderString(TexCoordPrecision precision) const;
+ std::string GetShaderString(
+ TexCoordPrecision precision, SamplerType sampler) const;
};
class FragmentShaderRGBATexAlphaMask {
public:
FragmentShaderRGBATexAlphaMask();
- std::string GetShaderString(TexCoordPrecision precision) const;
+ std::string GetShaderString(
+ TexCoordPrecision precision, SamplerType sampler) const;
- void Init(WebKit::WebGraphicsContext3D* context,
+ void Init(gpu::gles2::GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index);
int alpha_location() const { return alpha_location_; }
int sampler_location() const { return sampler_location_; }
@@ -516,11 +504,11 @@ class FragmentShaderRGBATexAlphaMask {
class FragmentShaderRGBATexAlphaMaskAA {
public:
FragmentShaderRGBATexAlphaMaskAA();
- std::string GetShaderString(TexCoordPrecision precision) const;
+ std::string GetShaderString(
+ TexCoordPrecision precision, SamplerType sampler) const;
- void Init(WebKit::WebGraphicsContext3D* context,
+ void Init(gpu::gles2::GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index);
int alpha_location() const { return alpha_location_; }
int sampler_location() const { return sampler_location_; }
@@ -545,11 +533,11 @@ class FragmentShaderRGBATexAlphaMaskAA {
class FragmentShaderRGBATexAlphaMaskColorMatrixAA {
public:
FragmentShaderRGBATexAlphaMaskColorMatrixAA();
- std::string GetShaderString(TexCoordPrecision precision) const;
+ std::string GetShaderString(
+ TexCoordPrecision precision, SamplerType sampler) const;
- void Init(WebKit::WebGraphicsContext3D* context,
+ void Init(gpu::gles2::GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index);
int alpha_location() const { return alpha_location_; }
int sampler_location() const { return sampler_location_; }
@@ -576,11 +564,11 @@ class FragmentShaderRGBATexAlphaMaskColorMatrixAA {
class FragmentShaderRGBATexAlphaColorMatrixAA {
public:
FragmentShaderRGBATexAlphaColorMatrixAA();
- std::string GetShaderString(TexCoordPrecision precision) const;
+ std::string GetShaderString(
+ TexCoordPrecision precision, SamplerType sampler) const;
- void Init(WebKit::WebGraphicsContext3D* context,
+ void Init(gpu::gles2::GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index);
int alpha_location() const { return alpha_location_; }
int sampler_location() const { return sampler_location_; }
@@ -597,11 +585,11 @@ class FragmentShaderRGBATexAlphaColorMatrixAA {
class FragmentShaderRGBATexAlphaMaskColorMatrix {
public:
FragmentShaderRGBATexAlphaMaskColorMatrix();
- std::string GetShaderString(TexCoordPrecision precision) const;
+ std::string GetShaderString(
+ TexCoordPrecision precision, SamplerType sampler) const;
- void Init(WebKit::WebGraphicsContext3D* context,
+ void Init(gpu::gles2::GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index);
int alpha_location() const { return alpha_location_; }
int sampler_location() const { return sampler_location_; }
@@ -628,11 +616,11 @@ class FragmentShaderRGBATexAlphaMaskColorMatrix {
class FragmentShaderYUVVideo {
public:
FragmentShaderYUVVideo();
- std::string GetShaderString(TexCoordPrecision precision) const;
+ std::string GetShaderString(
+ TexCoordPrecision precision, SamplerType sampler) const;
- void Init(WebKit::WebGraphicsContext3D* context,
+ void Init(gpu::gles2::GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index);
int y_texture_location() const { return y_texture_location_; }
int u_texture_location() const { return u_texture_location_; }
@@ -656,11 +644,11 @@ class FragmentShaderYUVVideo {
class FragmentShaderYUVAVideo {
public:
FragmentShaderYUVAVideo();
- std::string GetShaderString(TexCoordPrecision precision) const;
+ std::string GetShaderString(
+ TexCoordPrecision precision, SamplerType sampler) const;
- void Init(WebKit::WebGraphicsContext3D* context,
+ void Init(gpu::gles2::GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index);
int y_texture_location() const { return y_texture_location_; }
@@ -686,11 +674,11 @@ class FragmentShaderYUVAVideo {
class FragmentShaderColor {
public:
FragmentShaderColor();
- std::string GetShaderString(TexCoordPrecision precision) const;
+ std::string GetShaderString(
+ TexCoordPrecision precision, SamplerType sampler) const;
- void Init(WebKit::WebGraphicsContext3D* context,
+ void Init(gpu::gles2::GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index);
int color_location() const { return color_location_; }
@@ -703,11 +691,11 @@ class FragmentShaderColor {
class FragmentShaderColorAA {
public:
FragmentShaderColorAA();
- std::string GetShaderString(TexCoordPrecision precision) const;
+ std::string GetShaderString(
+ TexCoordPrecision precision, SamplerType sampler) const;
- void Init(WebKit::WebGraphicsContext3D* context,
+ void Init(gpu::gles2::GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index);
int color_location() const { return color_location_; }
@@ -720,11 +708,11 @@ class FragmentShaderColorAA {
class FragmentShaderCheckerboard {
public:
FragmentShaderCheckerboard();
- std::string GetShaderString(TexCoordPrecision precision) const;
+ std::string GetShaderString(
+ TexCoordPrecision precision, SamplerType sampler) const;
- void Init(WebKit::WebGraphicsContext3D* context,
+ void Init(gpu::gles2::GLES2Interface* context,
unsigned program,
- bool using_bind_uniform,
int* base_uniform_index);
int alpha_location() const { return alpha_location_; }
int tex_transform_location() const { return tex_transform_location_; }
diff --git a/chromium/cc/output/shader_unittest.cc b/chromium/cc/output/shader_unittest.cc
index 33cc13cd56c..4aacbf7180f 100644
--- a/chromium/cc/output/shader_unittest.cc
+++ b/chromium/cc/output/shader_unittest.cc
@@ -4,7 +4,8 @@
#include "cc/output/shader.h"
-#include "cc/debug/fake_web_graphics_context_3d.h"
+#include "cc/test/test_gles2_interface.h"
+#include "cc/test/test_web_graphics_context_3d.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/point.h"
#include "ui/gfx/size.h"
@@ -12,9 +13,11 @@
namespace cc {
TEST(ShaderTest, HighpThresholds) {
- // The FakeWebGraphicsContext3D always uses a mediump precision of 10 bits
- // which corresponds to a native highp threshold of 2^10 = 1024
- FakeWebGraphicsContext3D context;
+ // The test context always uses a mediump precision of 10 bits which
+ // corresponds to a native highp threshold of 2^10 = 1024
+ scoped_ptr<TestWebGraphicsContext3D> stub_context =
+ TestWebGraphicsContext3D::Create();
+ TestGLES2Interface stub_gl(stub_context.get());
int threshold_cache = 0;
int threshold_min;
@@ -25,23 +28,23 @@ TEST(ShaderTest, HighpThresholds) {
threshold_min = 0;
EXPECT_EQ(TexCoordPrecisionMedium, TexCoordPrecisionRequired(
- &context, &threshold_cache, threshold_min, closePoint));
+ &stub_gl, &threshold_cache, threshold_min, closePoint));
EXPECT_EQ(TexCoordPrecisionMedium, TexCoordPrecisionRequired(
- &context, &threshold_cache, threshold_min, smallSize));
+ &stub_gl, &threshold_cache, threshold_min, smallSize));
EXPECT_EQ(TexCoordPrecisionHigh, TexCoordPrecisionRequired(
- &context, &threshold_cache, threshold_min, farPoint));
+ &stub_gl, &threshold_cache, threshold_min, farPoint));
EXPECT_EQ(TexCoordPrecisionHigh, TexCoordPrecisionRequired(
- &context, &threshold_cache, threshold_min, bigSize));
+ &stub_gl, &threshold_cache, threshold_min, bigSize));
threshold_min = 3000;
EXPECT_EQ(TexCoordPrecisionMedium, TexCoordPrecisionRequired(
- &context, &threshold_cache, threshold_min, closePoint));
+ &stub_gl, &threshold_cache, threshold_min, closePoint));
EXPECT_EQ(TexCoordPrecisionMedium, TexCoordPrecisionRequired(
- &context, &threshold_cache, threshold_min, smallSize));
+ &stub_gl, &threshold_cache, threshold_min, smallSize));
EXPECT_EQ(TexCoordPrecisionMedium, TexCoordPrecisionRequired(
- &context, &threshold_cache, threshold_min, farPoint));
+ &stub_gl, &threshold_cache, threshold_min, farPoint));
EXPECT_EQ(TexCoordPrecisionMedium, TexCoordPrecisionRequired(
- &context, &threshold_cache, threshold_min, bigSize));
+ &stub_gl, &threshold_cache, threshold_min, bigSize));
}
} // namespace cc
diff --git a/chromium/cc/output/software_output_device.cc b/chromium/cc/output/software_output_device.cc
index 03f977e7426..17ef63f6d57 100644
--- a/chromium/cc/output/software_output_device.cc
+++ b/chromium/cc/output/software_output_device.cc
@@ -9,6 +9,7 @@
#include "third_party/skia/include/core/SkBitmapDevice.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "ui/gfx/skia_util.h"
+#include "ui/gfx/vsync_provider.h"
namespace cc {
@@ -56,4 +57,8 @@ void SoftwareOutputDevice::ReclaimSoftwareFrame(unsigned id) {
NOTIMPLEMENTED();
}
+gfx::VSyncProvider* SoftwareOutputDevice::GetVSyncProvider() {
+ return vsync_provider_.get();
+}
+
} // namespace cc
diff --git a/chromium/cc/output/software_output_device.h b/chromium/cc/output/software_output_device.h
index 9e2de88b048..4ecf1fedd8e 100644
--- a/chromium/cc/output/software_output_device.h
+++ b/chromium/cc/output/software_output_device.h
@@ -6,6 +6,7 @@
#define CC_OUTPUT_SOFTWARE_OUTPUT_DEVICE_H_
#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
#include "cc/base/cc_export.h"
#include "skia/ext/refptr.h"
// TODO(robertphillips): change this to "class SkBaseDevice;"
@@ -17,6 +18,10 @@
class SkBitmap;
class SkCanvas;
+namespace gfx {
+class VSyncProvider;
+}
+
namespace cc {
class SoftwareFrameData;
@@ -65,11 +70,16 @@ class CC_EXPORT SoftwareOutputDevice {
// 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();
+
protected:
gfx::Size viewport_size_;
gfx::Rect damage_rect_;
skia::RefPtr<SkBaseDevice> device_;
skia::RefPtr<SkCanvas> canvas_;
+ scoped_ptr<gfx::VSyncProvider> vsync_provider_;
private:
DISALLOW_COPY_AND_ASSIGN(SoftwareOutputDevice);
diff --git a/chromium/cc/output/software_renderer.cc b/chromium/cc/output/software_renderer.cc
index fa8c178df35..421e541da7d 100644
--- a/chromium/cc/output/software_renderer.cc
+++ b/chromium/cc/output/software_renderer.cc
@@ -11,6 +11,7 @@
#include "cc/output/compositor_frame_metadata.h"
#include "cc/output/copy_output_request.h"
#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"
@@ -48,6 +49,17 @@ bool IsScaleAndIntegerTranslate(const SkMatrix& matrix) {
SkScalarNearlyZero(matrix[SkMatrix::kMPersp2] - 1.0f);
}
+static SkShader::TileMode WrapModeToTileMode(GLint wrap_mode) {
+ switch (wrap_mode) {
+ case GL_REPEAT:
+ return SkShader::kRepeat_TileMode;
+ case GL_CLAMP_TO_EDGE:
+ return SkShader::kClamp_TileMode;
+ }
+ NOTREACHED();
+ return SkShader::kClamp_TileMode;
+}
+
} // anonymous namespace
scoped_ptr<SoftwareRenderer> SoftwareRenderer::Create(
@@ -74,7 +86,6 @@ SoftwareRenderer::SoftwareRenderer(RendererClient* client,
capabilities_.best_texture_format =
resource_provider_->best_texture_format();
}
- capabilities_.using_set_visibility = true;
// The updater can access bitmaps while the SoftwareRenderer is using them.
capabilities_.allow_partial_texture_updates = true;
capabilities_.using_partial_swap = true;
@@ -105,9 +116,9 @@ void SoftwareRenderer::FinishDrawingFrame(DrawingFrame* frame) {
output_device_->EndPaint(current_frame_data_.get());
}
-void SoftwareRenderer::SwapBuffers() {
+void SoftwareRenderer::SwapBuffers(const CompositorFrameMetadata& metadata) {
CompositorFrame compositor_frame;
- compositor_frame.metadata = client_->MakeCompositorFrameMetadata();
+ compositor_frame.metadata = metadata;
compositor_frame.software_frame_data = current_frame_data_.Pass();
output_surface_->SwapBuffers(&compositor_frame);
}
@@ -323,7 +334,8 @@ void SoftwareRenderer::DrawPictureQuad(const DrawingFrame* frame,
// cases and fall back to a persistent bitmap backing
// (http://crbug.com/280374).
skia::RefPtr<SkDrawFilter> opacity_filter =
- skia::AdoptRef(new skia::OpacityDrawFilter(quad->opacity(), true));
+ skia::AdoptRef(new skia::OpacityDrawFilter(
+ quad->opacity(), frame->disable_picture_quad_image_filtering));
DCHECK(!current_canvas_->getDrawFilter());
current_canvas_->setDrawFilter(opacity_filter.get());
@@ -382,11 +394,23 @@ void SoftwareRenderer::DrawTextureQuad(const DrawingFrame* frame,
background_paint.setColor(quad->background_color);
current_canvas_->drawRect(quad_rect, background_paint);
}
-
- current_canvas_->drawBitmapRectToRect(*bitmap,
- &sk_uv_rect,
- quad_rect,
- &current_paint_);
+ SkShader::TileMode tile_mode = WrapModeToTileMode(lock.wrap_mode());
+ if (tile_mode != SkShader::kClamp_TileMode) {
+ SkMatrix matrix;
+ matrix.setRectToRect(sk_uv_rect, quad_rect, SkMatrix::kFill_ScaleToFit);
+ skia::RefPtr<SkShader> shader = skia::AdoptRef(
+ SkShader::CreateBitmapShader(*bitmap, tile_mode, tile_mode));
+ shader->setLocalMatrix(matrix);
+ SkPaint paint;
+ paint.setStyle(SkPaint::kFill_Style);
+ paint.setShader(shader.get());
+ current_canvas_->drawRect(quad_rect, paint);
+ } else {
+ current_canvas_->drawBitmapRectToRect(*bitmap,
+ &sk_uv_rect,
+ quad_rect,
+ &current_paint_);
+ }
if (needs_layer)
current_canvas_->restore();
@@ -396,8 +420,11 @@ void SoftwareRenderer::DrawTileQuad(const DrawingFrame* frame,
const TileDrawQuad* quad) {
DCHECK(!output_surface_->ForcedDrawToSoftwareDevice());
DCHECK(IsSoftwareResource(quad->resource_id));
+
ResourceProvider::ScopedReadLockSoftware lock(resource_provider_,
quad->resource_id);
+ 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);
gfx::RectF visible_quad_vertex_rect = MathUtil::ScaleRectProportional(
@@ -414,7 +441,7 @@ void SoftwareRenderer::DrawTileQuad(const DrawingFrame* frame,
void SoftwareRenderer::DrawRenderPassQuad(const DrawingFrame* frame,
const RenderPassDrawQuad* quad) {
- CachedResource* content_texture =
+ ScopedResource* content_texture =
render_pass_textures_.get(quad->render_pass_id);
if (!content_texture || !content_texture->id())
return;
@@ -422,6 +449,7 @@ void SoftwareRenderer::DrawRenderPassQuad(const DrawingFrame* frame,
DCHECK(IsSoftwareResource(content_texture->id()));
ResourceProvider::ScopedReadLockSoftware lock(resource_provider_,
content_texture->id());
+ SkShader::TileMode content_tile_mode = WrapModeToTileMode(lock.wrap_mode());
SkRect dest_rect = gfx::RectFToSkRect(QuadVertexRect());
SkRect dest_visible_rect = gfx::RectFToSkRect(MathUtil::ScaleRectProportional(
@@ -433,20 +461,51 @@ void SoftwareRenderer::DrawRenderPassQuad(const DrawingFrame* frame,
SkMatrix::kFill_ScaleToFit);
const SkBitmap* content = lock.sk_bitmap();
- skia::RefPtr<SkShader> shader = skia::AdoptRef(
- SkShader::CreateBitmapShader(*content,
- SkShader::kClamp_TileMode,
- SkShader::kClamp_TileMode));
+
+ SkBitmap filter_bitmap;
+ if (!quad->filters.IsEmpty()) {
+ skia::RefPtr<SkImageFilter> filter = RenderSurfaceFilters::BuildImageFilter(
+ quad->filters, content_texture->size());
+ // TODO(ajuma): In addition origin translation, the canvas should also be
+ // scaled to accomodate device pixel ratio and pinch zoom. See
+ // crbug.com/281516 and crbug.com/281518.
+ // 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) {
+ bool is_opaque = false;
+ skia::RefPtr<SkBaseDevice> device =
+ skia::AdoptRef(new SkBitmapDevice(SkBitmap::kARGB_8888_Config,
+ content_texture->size().width(),
+ content_texture->size().height(),
+ is_opaque));
+ SkCanvas canvas(device.get());
+ SkPaint paint;
+ paint.setImageFilter(filter.get());
+ canvas.clear(SK_ColorTRANSPARENT);
+ canvas.translate(SkIntToScalar(-quad->rect.origin().x()),
+ SkIntToScalar(-quad->rect.origin().y()));
+ canvas.drawSprite(*content, 0, 0, &paint);
+ bool will_change_pixels = false;
+ filter_bitmap = device->accessBitmap(will_change_pixels);
+ }
+ }
+
+ skia::RefPtr<SkShader> shader;
+ if (filter_bitmap.isNull()) {
+ shader = skia::AdoptRef(SkShader::CreateBitmapShader(
+ *content, content_tile_mode, content_tile_mode));
+ } else {
+ shader = skia::AdoptRef(SkShader::CreateBitmapShader(
+ filter_bitmap, content_tile_mode, content_tile_mode));
+ }
shader->setLocalMatrix(content_mat);
current_paint_.setShader(shader.get());
- SkImageFilter* filter = quad->filter.get();
- if (filter)
- current_paint_.setImageFilter(filter);
-
if (quad->mask_resource_id) {
ResourceProvider::ScopedReadLockSoftware mask_lock(resource_provider_,
quad->mask_resource_id);
+ SkShader::TileMode mask_tile_mode = WrapModeToTileMode(
+ mask_lock.wrap_mode());
const SkBitmap* mask = mask_lock.sk_bitmap();
@@ -460,9 +519,7 @@ void SoftwareRenderer::DrawRenderPassQuad(const DrawingFrame* frame,
mask_mat.setRectToRect(mask_rect, dest_rect, SkMatrix::kFill_ScaleToFit);
skia::RefPtr<SkShader> mask_shader = skia::AdoptRef(
- SkShader::CreateBitmapShader(*mask,
- SkShader::kClamp_TileMode,
- SkShader::kClamp_TileMode));
+ SkShader::CreateBitmapShader(*mask, mask_tile_mode, mask_tile_mode));
mask_shader->setLocalMatrix(mask_mat);
SkPaint mask_paint;
@@ -551,8 +608,4 @@ void SoftwareRenderer::SetVisible(bool visible) {
DiscardBackbuffer();
}
-void SoftwareRenderer::SetDiscardBackBufferWhenNotVisible(bool discard) {
- // The software renderer always discards the backbuffer when not visible.
-}
-
} // namespace cc
diff --git a/chromium/cc/output/software_renderer.h b/chromium/cc/output/software_renderer.h
index 5a8780e043c..18fb2a3fc33 100644
--- a/chromium/cc/output/software_renderer.h
+++ b/chromium/cc/output/software_renderer.h
@@ -36,7 +36,7 @@ class CC_EXPORT SoftwareRenderer : public DirectRenderer {
virtual ~SoftwareRenderer();
virtual const RendererCapabilities& Capabilities() const OVERRIDE;
virtual void Finish() OVERRIDE;
- virtual void SwapBuffers() OVERRIDE;
+ virtual void SwapBuffers(const CompositorFrameMetadata& metadata) OVERRIDE;
virtual void GetFramebufferPixels(void* pixels, gfx::Rect rect) OVERRIDE;
virtual void SetVisible(bool visible) OVERRIDE;
virtual void SendManagedMemoryStats(
@@ -45,7 +45,6 @@ class CC_EXPORT SoftwareRenderer : public DirectRenderer {
size_t bytes_allocated) OVERRIDE {}
virtual void ReceiveSwapBuffersAck(
const CompositorFrameAck& ack) OVERRIDE;
- virtual void SetDiscardBackBufferWhenNotVisible(bool discard) OVERRIDE;
virtual void DiscardBackbuffer() OVERRIDE;
virtual void EnsureBackbuffer() OVERRIDE;
diff --git a/chromium/cc/output/software_renderer_unittest.cc b/chromium/cc/output/software_renderer_unittest.cc
index 03f1635084b..fc1c7070cb4 100644
--- a/chromium/cc/output/software_renderer_unittest.cc
+++ b/chromium/cc/output/software_renderer_unittest.cc
@@ -34,7 +34,7 @@ class SoftwareRendererTest : public testing::Test, public RendererClient {
CHECK(output_surface_->BindToClient(&output_surface_client_));
resource_provider_ =
- ResourceProvider::Create(output_surface_.get(), 0, false);
+ ResourceProvider::Create(output_surface_.get(), NULL, 0, false, 1);
renderer_ = SoftwareRenderer::Create(
this, &settings_, output_surface_.get(), resource_provider());
}
@@ -45,19 +45,8 @@ class SoftwareRendererTest : public testing::Test, public RendererClient {
SoftwareRenderer* renderer() const { return renderer_.get(); }
- void set_viewport(gfx::Rect viewport) {
- viewport_ = viewport;
- }
-
// RendererClient implementation.
- virtual gfx::Rect DeviceViewport() const OVERRIDE {
- return viewport_;
- }
- virtual gfx::Rect DeviceClip() const OVERRIDE { return DeviceViewport(); }
virtual void SetFullRootLayerDamage() OVERRIDE {}
- virtual CompositorFrameMetadata MakeCompositorFrameMetadata() const OVERRIDE {
- return CompositorFrameMetadata();
- }
protected:
LayerTreeSettings settings_;
@@ -65,7 +54,6 @@ class SoftwareRendererTest : public testing::Test, public RendererClient {
scoped_ptr<FakeOutputSurface> output_surface_;
scoped_ptr<ResourceProvider> resource_provider_;
scoped_ptr<SoftwareRenderer> renderer_;
- gfx::Rect viewport_;
};
TEST_F(SoftwareRendererTest, SolidColorQuad) {
@@ -74,13 +62,17 @@ TEST_F(SoftwareRendererTest, SolidColorQuad) {
gfx::Rect outer_rect(outer_size);
gfx::Rect inner_rect(gfx::Point(1, 1), inner_size);
gfx::Rect visible_rect(gfx::Point(1, 2), gfx::Size(98, 97));
- set_viewport(gfx::Rect(outer_size));
InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
scoped_ptr<SharedQuadState> shared_quad_state = SharedQuadState::Create();
- shared_quad_state->SetAll(
- gfx::Transform(), outer_size, outer_rect, outer_rect, false, 1.0);
+ shared_quad_state->SetAll(gfx::Transform(),
+ outer_size,
+ outer_rect,
+ outer_rect,
+ false,
+ 1.0,
+ SkXfermode::kSrcOver_Mode);
RenderPass::Id root_render_pass_id = RenderPass::Id(1, 1);
scoped_ptr<TestRenderPass> root_render_pass = TestRenderPass::Create();
root_render_pass->SetNew(
@@ -98,12 +90,18 @@ TEST_F(SoftwareRendererTest, SolidColorQuad) {
list.push_back(root_render_pass.PassAs<RenderPass>());
float device_scale_factor = 1.f;
- renderer()->DrawFrame(&list, NULL, device_scale_factor, true);
+ gfx::Rect device_viewport_rect(outer_size);
+ renderer()->DrawFrame(&list,
+ NULL,
+ device_scale_factor,
+ device_viewport_rect,
+ device_viewport_rect,
+ true,
+ false);
SkBitmap output;
- output.setConfig(SkBitmap::kARGB_8888_Config,
- DeviceViewport().width(),
- DeviceViewport().height());
+ output.setConfig(
+ SkBitmap::kARGB_8888_Config, outer_rect.width(), outer_rect.height());
output.allocPixels();
renderer()->GetFramebufferPixels(output.getPixels(), outer_rect);
@@ -121,7 +119,6 @@ TEST_F(SoftwareRendererTest, TileQuad) {
gfx::Size inner_size(98, 98);
gfx::Rect outer_rect(outer_size);
gfx::Rect inner_rect(gfx::Point(1, 1), inner_size);
- set_viewport(gfx::Rect(outer_size));
InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
ResourceProvider::ResourceId resource_yellow =
@@ -159,11 +156,16 @@ TEST_F(SoftwareRendererTest, TileQuad) {
gfx::Rect(inner_size),
gfx::Vector2d());
- gfx::Rect root_rect = DeviceViewport();
+ gfx::Rect root_rect = outer_rect;
scoped_ptr<SharedQuadState> shared_quad_state = SharedQuadState::Create();
- shared_quad_state->SetAll(
- gfx::Transform(), outer_size, outer_rect, outer_rect, false, 1.0);
+ shared_quad_state->SetAll(gfx::Transform(),
+ outer_size,
+ outer_rect,
+ outer_rect,
+ false,
+ 1.0,
+ SkXfermode::kSrcOver_Mode);
RenderPass::Id root_render_pass_id = RenderPass::Id(1, 1);
scoped_ptr<TestRenderPass> root_render_pass = TestRenderPass::Create();
root_render_pass->SetNew(
@@ -191,12 +193,18 @@ TEST_F(SoftwareRendererTest, TileQuad) {
list.push_back(root_render_pass.PassAs<RenderPass>());
float device_scale_factor = 1.f;
- renderer()->DrawFrame(&list, NULL, device_scale_factor, true);
+ gfx::Rect device_viewport_rect(outer_size);
+ renderer()->DrawFrame(&list,
+ NULL,
+ device_scale_factor,
+ device_viewport_rect,
+ device_viewport_rect,
+ true,
+ false);
SkBitmap output;
- output.setConfig(SkBitmap::kARGB_8888_Config,
- DeviceViewport().width(),
- DeviceViewport().height());
+ output.setConfig(
+ SkBitmap::kARGB_8888_Config, outer_size.width(), outer_size.height());
output.allocPixels();
renderer()->GetFramebufferPixels(output.getPixels(), outer_rect);
@@ -213,7 +221,6 @@ TEST_F(SoftwareRendererTest, TileQuadVisibleRect) {
gfx::Rect tile_rect(tile_size);
gfx::Rect visible_rect = tile_rect;
visible_rect.Inset(1, 2, 3, 4);
- set_viewport(gfx::Rect(tile_size));
InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
ResourceProvider::ResourceId resource_cyan =
@@ -238,11 +245,16 @@ TEST_F(SoftwareRendererTest, TileQuadVisibleRect) {
gfx::Rect(tile_size),
gfx::Vector2d());
- gfx::Rect root_rect = DeviceViewport();
+ gfx::Rect root_rect(tile_size);
scoped_ptr<SharedQuadState> shared_quad_state = SharedQuadState::Create();
- shared_quad_state->SetAll(
- gfx::Transform(), tile_size, tile_rect, tile_rect, false, 1.0);
+ shared_quad_state->SetAll(gfx::Transform(),
+ tile_size,
+ tile_rect,
+ tile_rect,
+ false,
+ 1.0,
+ SkXfermode::kSrcOver_Mode);
RenderPass::Id root_render_pass_id = RenderPass::Id(1, 1);
scoped_ptr<TestRenderPass> root_render_pass = TestRenderPass::Create();
root_render_pass->SetNew(
@@ -262,12 +274,18 @@ TEST_F(SoftwareRendererTest, TileQuadVisibleRect) {
list.push_back(root_render_pass.PassAs<RenderPass>());
float device_scale_factor = 1.f;
- renderer()->DrawFrame(&list, NULL, device_scale_factor, true);
+ gfx::Rect device_viewport_rect(tile_size);
+ renderer()->DrawFrame(&list,
+ NULL,
+ device_scale_factor,
+ device_viewport_rect,
+ device_viewport_rect,
+ true,
+ false);
SkBitmap output;
- output.setConfig(SkBitmap::kARGB_8888_Config,
- DeviceViewport().width(),
- DeviceViewport().height());
+ output.setConfig(
+ SkBitmap::kARGB_8888_Config, tile_size.width(), tile_size.height());
output.allocPixels();
renderer()->GetFramebufferPixels(output.getPixels(), tile_rect);
@@ -294,7 +312,6 @@ TEST_F(SoftwareRendererTest, TileQuadVisibleRect) {
TEST_F(SoftwareRendererTest, ShouldClearRootRenderPass) {
float device_scale_factor = 1.f;
gfx::Rect viewport_rect(0, 0, 100, 100);
- set_viewport(viewport_rect);
settings_.should_clear_root_render_pass = false;
InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
@@ -314,7 +331,13 @@ TEST_F(SoftwareRendererTest, ShouldClearRootRenderPass) {
AddQuad(root_clear_pass, viewport_rect, SK_ColorGREEN);
renderer()->DecideRenderPassAllocationsForFrame(list);
- renderer()->DrawFrame(&list, NULL, device_scale_factor, true);
+ renderer()->DrawFrame(&list,
+ NULL,
+ device_scale_factor,
+ viewport_rect,
+ viewport_rect,
+ true,
+ false);
renderer()->GetFramebufferPixels(output.getPixels(), viewport_rect);
EXPECT_EQ(SK_ColorGREEN, output.getColor(0, 0));
@@ -333,7 +356,13 @@ TEST_F(SoftwareRendererTest, ShouldClearRootRenderPass) {
AddQuad(root_smaller_pass, smaller_rect, SK_ColorMAGENTA);
renderer()->DecideRenderPassAllocationsForFrame(list);
- renderer()->DrawFrame(&list, NULL, device_scale_factor, true);
+ renderer()->DrawFrame(&list,
+ NULL,
+ device_scale_factor,
+ viewport_rect,
+ viewport_rect,
+ true,
+ false);
renderer()->GetFramebufferPixels(output.getPixels(), viewport_rect);
// If we didn't clear, the borders should still be green.
@@ -350,7 +379,6 @@ TEST_F(SoftwareRendererTest, ShouldClearRootRenderPass) {
TEST_F(SoftwareRendererTest, RenderPassVisibleRect) {
float device_scale_factor = 1.f;
gfx::Rect viewport_rect(0, 0, 100, 100);
- set_viewport(viewport_rect);
InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
RenderPassList list;
@@ -380,7 +408,13 @@ TEST_F(SoftwareRendererTest, RenderPassVisibleRect) {
root_clear_pass->quad_list[0]->visible_rect = interior_visible_rect;
renderer()->DecideRenderPassAllocationsForFrame(list);
- renderer()->DrawFrame(&list, NULL, device_scale_factor, true);
+ renderer()->DrawFrame(&list,
+ NULL,
+ device_scale_factor,
+ viewport_rect,
+ viewport_rect,
+ true,
+ false);
renderer()->GetFramebufferPixels(output.getPixels(), viewport_rect);
EXPECT_EQ(SK_ColorGREEN, output.getColor(0, 0));
diff --git a/chromium/cc/quads/draw_quad.cc b/chromium/cc/quads/draw_quad.cc
index 0d021d92083..f3cd8189545 100644
--- a/chromium/cc/quads/draw_quad.cc
+++ b/chromium/cc/quads/draw_quad.cc
@@ -40,6 +40,13 @@ void DrawQuad::SetAll(const SharedQuadState* shared_quad_state,
gfx::Rect opaque_rect,
gfx::Rect visible_rect,
bool needs_blending) {
+ DCHECK(rect.Contains(visible_rect)) << "rect: " << rect.ToString()
+ << " visible_rect: "
+ << visible_rect.ToString();
+ DCHECK(opaque_rect.IsEmpty() || rect.Contains(opaque_rect))
+ << "rect: " << rect.ToString() << "opaque_rect "
+ << opaque_rect.ToString();
+
this->material = material;
this->rect = rect;
this->opaque_rect = opaque_rect;
diff --git a/chromium/cc/quads/draw_quad_unittest.cc b/chromium/cc/quads/draw_quad_unittest.cc
index 5705ce7bf24..876c0461b37 100644
--- a/chromium/cc/quads/draw_quad_unittest.cc
+++ b/chromium/cc/quads/draw_quad_unittest.cc
@@ -36,6 +36,7 @@ TEST(DrawQuadTest, CopySharedQuadState) {
gfx::Rect clip_rect(19, 21, 23, 25);
bool is_clipped = true;
float opacity = 0.25f;
+ SkXfermode::Mode blend_mode = SkXfermode::kMultiply_Mode;
scoped_ptr<SharedQuadState> state(SharedQuadState::Create());
state->SetAll(quad_transform,
@@ -43,7 +44,8 @@ TEST(DrawQuadTest, CopySharedQuadState) {
visible_content_rect,
clip_rect,
is_clipped,
- opacity);
+ opacity,
+ blend_mode);
scoped_ptr<SharedQuadState> copy(state->Copy());
EXPECT_EQ(quad_transform, copy->content_to_target_transform);
@@ -51,6 +53,7 @@ TEST(DrawQuadTest, CopySharedQuadState) {
EXPECT_EQ(opacity, copy->opacity);
EXPECT_RECT_EQ(clip_rect, copy->clip_rect);
EXPECT_EQ(is_clipped, copy->is_clipped);
+ EXPECT_EQ(blend_mode, copy->blend_mode);
}
scoped_ptr<SharedQuadState> CreateSharedQuadState() {
@@ -60,6 +63,7 @@ scoped_ptr<SharedQuadState> CreateSharedQuadState() {
gfx::Rect clip_rect(19, 21, 23, 25);
bool is_clipped = false;
float opacity = 1.f;
+ SkXfermode::Mode blend_mode = SkXfermode::kSrcOver_Mode;
scoped_ptr<SharedQuadState> state(SharedQuadState::Create());
state->SetAll(quad_transform,
@@ -67,7 +71,8 @@ scoped_ptr<SharedQuadState> CreateSharedQuadState() {
visible_content_rect,
clip_rect,
is_clipped,
- opacity);
+ opacity,
+ blend_mode);
return state.Pass();
}
@@ -249,6 +254,24 @@ void CompareDrawQuad(DrawQuad* quad,
} \
SETUP_AND_COPY_QUAD_ALL(Type, quad_all);
+#define CREATE_QUAD_7_NEW_1(Type, a, b, c, d, e, f, g, copy_a) \
+ scoped_ptr<Type> quad_new(Type::Create()); \
+ { \
+ QUAD_DATA \
+ quad_new->SetNew(shared_state.get(), quad_rect, a, b, c, d, e, f, g); \
+ } \
+ SETUP_AND_COPY_QUAD_NEW_1(Type, quad_new, copy_a);
+
+#define CREATE_QUAD_7_ALL_1(Type, a, b, c, d, e, f, g, copy_a) \
+ scoped_ptr<Type> quad_all(Type::Create()); \
+ { \
+ QUAD_DATA \
+ quad_all->SetAll(shared_state.get(), quad_rect, quad_opaque_rect, \
+ quad_visible_rect, needs_blending, \
+ a, b, c, d, e, f, g); \
+ } \
+ SETUP_AND_COPY_QUAD_ALL_1(Type, quad_all, copy_a);
+
#define CREATE_QUAD_8_NEW(Type, a, b, c, d, e, f, g, h) \
scoped_ptr<Type> quad_new(Type::Create()); \
{ \
@@ -334,7 +357,7 @@ TEST(DrawQuadTest, CopyDebugBorderDrawQuad) {
}
TEST(DrawQuadTest, CopyIOSurfaceDrawQuad) {
- gfx::Rect opaque_rect(3, 7, 10, 12);
+ gfx::Rect opaque_rect(33, 47, 10, 12);
gfx::Size size(58, 95);
ResourceProvider::ResourceId resource_id = 72;
IOSurfaceDrawQuad::Orientation orientation = IOSurfaceDrawQuad::UNFLIPPED;
@@ -366,20 +389,17 @@ TEST(DrawQuadTest, CopyRenderPassDrawQuad) {
FilterOperations background_filters;
background_filters.Append(
FilterOperation::CreateGrayscaleFilter(1.f));
- skia::RefPtr<SkImageFilter> filter =
- skia::AdoptRef(new SkBlurImageFilter(SK_Scalar1, SK_Scalar1));
RenderPass::Id copied_render_pass_id(235, 11);
CREATE_SHARED_STATE();
- CREATE_QUAD_8_NEW_1(RenderPassDrawQuad,
+ CREATE_QUAD_7_NEW_1(RenderPassDrawQuad,
render_pass_id,
is_replica,
mask_resource_id,
contents_changed_since_last_frame,
mask_u_v_rect,
filters,
- filter,
background_filters,
copied_render_pass_id);
EXPECT_EQ(DrawQuad::RENDER_PASS, copy_quad->material);
@@ -390,17 +410,15 @@ TEST(DrawQuadTest, CopyRenderPassDrawQuad) {
copy_quad->contents_changed_since_last_frame);
EXPECT_EQ(mask_u_v_rect.ToString(), copy_quad->mask_uv_rect.ToString());
EXPECT_EQ(filters, copy_quad->filters);
- EXPECT_EQ(filter, copy_quad->filter);
EXPECT_EQ(background_filters, copy_quad->background_filters);
- CREATE_QUAD_8_ALL_1(RenderPassDrawQuad,
+ CREATE_QUAD_7_ALL_1(RenderPassDrawQuad,
render_pass_id,
is_replica,
mask_resource_id,
contents_changed_since_last_frame,
mask_u_v_rect,
filters,
- filter,
background_filters,
copied_render_pass_id);
EXPECT_EQ(DrawQuad::RENDER_PASS, copy_quad->material);
@@ -411,7 +429,6 @@ TEST(DrawQuadTest, CopyRenderPassDrawQuad) {
copy_quad->contents_changed_since_last_frame);
EXPECT_EQ(mask_u_v_rect.ToString(), copy_quad->mask_uv_rect.ToString());
EXPECT_EQ(filters, copy_quad->filters);
- EXPECT_EQ(filter, copy_quad->filter);
EXPECT_EQ(background_filters, copy_quad->background_filters);
}
@@ -432,7 +449,7 @@ TEST(DrawQuadTest, CopySolidColorDrawQuad) {
}
TEST(DrawQuadTest, CopyStreamVideoDrawQuad) {
- gfx::Rect opaque_rect(3, 7, 10, 12);
+ gfx::Rect opaque_rect(33, 47, 10, 12);
ResourceProvider::ResourceId resource_id = 64;
gfx::Transform matrix = gfx::Transform(0.5, 0.25, 1, 0.75, 0, 1);
CREATE_SHARED_STATE();
@@ -450,7 +467,7 @@ TEST(DrawQuadTest, CopyStreamVideoDrawQuad) {
}
TEST(DrawQuadTest, CopyTextureDrawQuad) {
- gfx::Rect opaque_rect(3, 7, 10, 12);
+ gfx::Rect opaque_rect(33, 47, 10, 12);
unsigned resource_id = 82;
bool premultiplied_alpha = true;
gfx::PointF uv_top_left(0.5f, 224.f);
@@ -494,102 +511,6 @@ TEST(DrawQuadTest, CopyTextureDrawQuad) {
EXPECT_EQ(flipped, copy_quad->flipped);
}
-TEST(DrawQuadTest, ClipTextureDrawQuad) {
- gfx::Rect opaque_rect(3, 7, 10, 12);
- unsigned resource_id = 82;
- bool premultiplied_alpha = true;
- bool flipped = true;
- CREATE_SHARED_STATE();
- // The original quad position is (30, 40) its size is 50*60.
- shared_state->content_to_target_transform =
- gfx::Transform(1.f, 0.f, 0.f, 1.f, 10.f, 20.f);
- // After transformation, the quad position is (40, 60) its size is 50*60.
- shared_state->clip_rect = gfx::Rect(50, 70, 30, 20);
-
- // The original quad is 'ABCD', the clipped quad is 'abcd':
- // 40 50 90
- // B--:-------C 60
- // | b----c -|-70
- // | | | |
- // | a----d -|-90
- // | |
- // A----------D 120
- // UV and vertex opacity are stored per vertex on the parent rectangle 'ABCD'.
-
- // This is the UV value for vertex 'B'.
- gfx::PointF uv_top_left(0.1f, 0.2f);
- // This is the UV value for vertex 'D'.
- gfx::PointF uv_bottom_right(0.9f, 0.8f);
- // This the vertex opacity for the vertices 'ABCD'.
- const float vertex_opacity[] = { 0.3f, 0.4f, 0.7f, 0.8f };
- {
- CREATE_QUAD_8_NEW(TextureDrawQuad,
- opaque_rect,
- resource_id,
- premultiplied_alpha,
- uv_top_left,
- uv_bottom_right,
- SK_ColorTRANSPARENT,
- vertex_opacity,
- flipped);
- CREATE_QUAD_7_ALL(TextureDrawQuad,
- resource_id,
- premultiplied_alpha,
- uv_top_left,
- uv_bottom_right,
- SK_ColorTRANSPARENT,
- vertex_opacity,
- flipped);
- EXPECT_TRUE(quad_all->PerformClipping());
-
- // This is the expected UV value for vertex 'b'.
- // uv(b) = uv(B) + (Bb / BD) * (uv(D) - uv(B))
- // 0.3 = 0.2 + (10 / 60) * (0.8 - 0.2)
- gfx::PointF uv_top_left_clipped(0.26f, 0.3f);
- // This is the expected UV value for vertex 'd'.
- // uv(d) = uv(B) + (Bd / BD) * (uv(D) - uv(B))
- gfx::PointF uv_bottom_right_clipped(0.74f, 0.5f);
- // This the expected vertex opacity for the vertices 'abcd'.
- // They are computed with a bilinear interpolation of the corner values.
- const float vertex_opacity_clipped[] = { 0.43f, 0.45f, 0.65f, 0.67f };
-
- EXPECT_EQ(uv_top_left_clipped, quad_all->uv_top_left);
- EXPECT_EQ(uv_bottom_right_clipped, quad_all->uv_bottom_right);
- EXPECT_FLOAT_ARRAY_EQ(vertex_opacity_clipped, quad_all->vertex_opacity, 4);
- }
-
- uv_top_left = gfx::PointF(0.8f, 0.7f);
- uv_bottom_right = gfx::PointF(0.2f, 0.1f);
- {
- CREATE_QUAD_8_NEW(TextureDrawQuad,
- opaque_rect,
- resource_id,
- premultiplied_alpha,
- uv_top_left,
- uv_bottom_right,
- SK_ColorTRANSPARENT,
- vertex_opacity,
- flipped);
- CREATE_QUAD_7_ALL(TextureDrawQuad,
- resource_id,
- premultiplied_alpha,
- uv_top_left,
- uv_bottom_right,
- SK_ColorTRANSPARENT,
- vertex_opacity,
- flipped);
- EXPECT_TRUE(quad_all->PerformClipping());
-
- // This is the expected UV value for vertex 'b'.
- gfx::PointF uv_top_left_clipped(0.68f, 0.6f);
- // This is the expected UV value for vertex 'd'.
- gfx::PointF uv_bottom_right_clipped(0.32f, 0.4f);
-
- EXPECT_EQ(uv_top_left_clipped, quad_all->uv_top_left);
- EXPECT_EQ(uv_bottom_right_clipped, quad_all->uv_bottom_right);
- }
-}
-
TEST(DrawQuadTest, CopyTileDrawQuad) {
gfx::Rect opaque_rect(33, 44, 22, 33);
unsigned resource_id = 104;
@@ -624,7 +545,7 @@ TEST(DrawQuadTest, CopyTileDrawQuad) {
}
TEST(DrawQuadTest, CopyYUVVideoDrawQuad) {
- gfx::Rect opaque_rect(3, 7, 10, 12);
+ gfx::Rect opaque_rect(33, 47, 10, 12);
gfx::SizeF tex_scale(0.75f, 0.5f);
ResourceProvider::ResourceId y_plane_resource_id = 45;
ResourceProvider::ResourceId u_plane_resource_id = 532;
@@ -668,18 +589,16 @@ TEST(DrawQuadTest, CopyPictureDrawQuad) {
ResourceFormat texture_format = RGBA_8888;
gfx::Rect content_rect(30, 40, 20, 30);
float contents_scale = 3.141592f;
- bool can_draw_direct_to_backbuffer = true;
scoped_refptr<PicturePileImpl> picture_pile = PicturePileImpl::Create();
CREATE_SHARED_STATE();
- CREATE_QUAD_8_NEW(PictureDrawQuad,
+ CREATE_QUAD_7_NEW(PictureDrawQuad,
opaque_rect,
tex_coord_rect,
texture_size,
texture_format,
content_rect,
contents_scale,
- can_draw_direct_to_backbuffer,
picture_pile);
EXPECT_EQ(DrawQuad::PICTURE_CONTENT, copy_quad->material);
EXPECT_RECT_EQ(opaque_rect, copy_quad->opaque_rect);
@@ -688,17 +607,14 @@ TEST(DrawQuadTest, CopyPictureDrawQuad) {
EXPECT_EQ(texture_format, copy_quad->texture_format);
EXPECT_RECT_EQ(content_rect, copy_quad->content_rect);
EXPECT_EQ(contents_scale, copy_quad->contents_scale);
- EXPECT_EQ(can_draw_direct_to_backbuffer,
- copy_quad->can_draw_direct_to_backbuffer);
EXPECT_EQ(picture_pile, copy_quad->picture_pile);
- CREATE_QUAD_7_ALL(PictureDrawQuad,
+ CREATE_QUAD_6_ALL(PictureDrawQuad,
tex_coord_rect,
texture_size,
texture_format,
content_rect,
contents_scale,
- can_draw_direct_to_backbuffer,
picture_pile);
EXPECT_EQ(DrawQuad::PICTURE_CONTENT, copy_quad->material);
EXPECT_EQ(tex_coord_rect, copy_quad->tex_coord_rect);
@@ -706,8 +622,6 @@ TEST(DrawQuadTest, CopyPictureDrawQuad) {
EXPECT_EQ(texture_format, copy_quad->texture_format);
EXPECT_RECT_EQ(content_rect, copy_quad->content_rect);
EXPECT_EQ(contents_scale, copy_quad->contents_scale);
- EXPECT_EQ(can_draw_direct_to_backbuffer,
- copy_quad->can_draw_direct_to_backbuffer);
EXPECT_EQ(picture_pile, copy_quad->picture_pile);
}
@@ -748,7 +662,7 @@ TEST_F(DrawQuadIteratorTest, DebugBorderDrawQuad) {
}
TEST_F(DrawQuadIteratorTest, IOSurfaceDrawQuad) {
- gfx::Rect opaque_rect(3, 7, 10, 12);
+ gfx::Rect opaque_rect(33, 47, 10, 12);
gfx::Size size(58, 95);
ResourceProvider::ResourceId resource_id = 72;
IOSurfaceDrawQuad::Orientation orientation = IOSurfaceDrawQuad::UNFLIPPED;
@@ -772,20 +686,17 @@ TEST_F(DrawQuadIteratorTest, RenderPassDrawQuad) {
FilterOperations background_filters;
background_filters.Append(
FilterOperation::CreateGrayscaleFilter(1.f));
- skia::RefPtr<SkImageFilter> filter =
- skia::AdoptRef(new SkBlurImageFilter(SK_Scalar1, SK_Scalar1));
RenderPass::Id copied_render_pass_id(235, 11);
CREATE_SHARED_STATE();
- CREATE_QUAD_8_NEW_1(RenderPassDrawQuad,
+ CREATE_QUAD_7_NEW_1(RenderPassDrawQuad,
render_pass_id,
is_replica,
mask_resource_id,
contents_changed_since_last_frame,
mask_u_v_rect,
filters,
- filter,
background_filters,
copied_render_pass_id);
EXPECT_EQ(mask_resource_id, quad_new->mask_resource_id);
@@ -806,7 +717,7 @@ TEST_F(DrawQuadIteratorTest, SolidColorDrawQuad) {
}
TEST_F(DrawQuadIteratorTest, StreamVideoDrawQuad) {
- gfx::Rect opaque_rect(3, 7, 10, 12);
+ gfx::Rect opaque_rect(33, 47, 10, 12);
ResourceProvider::ResourceId resource_id = 64;
gfx::Transform matrix = gfx::Transform(0.5, 0.25, 1, 0.75, 0, 1);
@@ -818,7 +729,7 @@ TEST_F(DrawQuadIteratorTest, StreamVideoDrawQuad) {
}
TEST_F(DrawQuadIteratorTest, TextureDrawQuad) {
- gfx::Rect opaque_rect(3, 7, 10, 12);
+ gfx::Rect opaque_rect(33, 47, 10, 12);
unsigned resource_id = 82;
bool premultiplied_alpha = true;
gfx::PointF uv_top_left(0.5f, 224.f);
@@ -861,7 +772,7 @@ TEST_F(DrawQuadIteratorTest, TileDrawQuad) {
}
TEST_F(DrawQuadIteratorTest, YUVVideoDrawQuad) {
- gfx::Rect opaque_rect(3, 7, 10, 12);
+ gfx::Rect opaque_rect(33, 47, 10, 12);
gfx::SizeF tex_scale(0.75f, 0.5f);
ResourceProvider::ResourceId y_plane_resource_id = 45;
ResourceProvider::ResourceId u_plane_resource_id = 532;
@@ -896,18 +807,16 @@ TEST_F(DrawQuadIteratorTest, DISABLED_PictureDrawQuad) {
ResourceFormat texture_format = RGBA_8888;
gfx::Rect content_rect(30, 40, 20, 30);
float contents_scale = 3.141592f;
- bool can_draw_direct_to_backbuffer = true;
scoped_refptr<PicturePileImpl> picture_pile = PicturePileImpl::Create();
CREATE_SHARED_STATE();
- CREATE_QUAD_8_NEW(PictureDrawQuad,
+ CREATE_QUAD_7_NEW(PictureDrawQuad,
opaque_rect,
tex_coord_rect,
texture_size,
texture_format,
content_rect,
contents_scale,
- can_draw_direct_to_backbuffer,
picture_pile);
EXPECT_EQ(0, IterateAndCount(quad_new.get()));
}
diff --git a/chromium/cc/quads/picture_draw_quad.cc b/chromium/cc/quads/picture_draw_quad.cc
index e566b247f72..bdb12e64d7a 100644
--- a/chromium/cc/quads/picture_draw_quad.cc
+++ b/chromium/cc/quads/picture_draw_quad.cc
@@ -28,7 +28,6 @@ void PictureDrawQuad::SetNew(const SharedQuadState* shared_quad_state,
ResourceFormat texture_format,
gfx::Rect content_rect,
float contents_scale,
- bool can_draw_direct_to_backbuffer,
scoped_refptr<PicturePileImpl> picture_pile) {
ContentDrawQuadBase::SetNew(shared_quad_state,
DrawQuad::PICTURE_CONTENT,
@@ -40,7 +39,6 @@ void PictureDrawQuad::SetNew(const SharedQuadState* shared_quad_state,
texture_format));
this->content_rect = content_rect;
this->contents_scale = contents_scale;
- this->can_draw_direct_to_backbuffer = can_draw_direct_to_backbuffer;
this->picture_pile = picture_pile;
this->texture_format = texture_format;
}
@@ -55,7 +53,6 @@ void PictureDrawQuad::SetAll(const SharedQuadState* shared_quad_state,
ResourceFormat texture_format,
gfx::Rect content_rect,
float contents_scale,
- bool can_draw_direct_to_backbuffer,
scoped_refptr<PicturePileImpl> picture_pile) {
ContentDrawQuadBase::SetAll(shared_quad_state,
DrawQuad::PICTURE_CONTENT,
@@ -69,7 +66,6 @@ void PictureDrawQuad::SetAll(const SharedQuadState* shared_quad_state,
texture_format));
this->content_rect = content_rect;
this->contents_scale = contents_scale;
- this->can_draw_direct_to_backbuffer = can_draw_direct_to_backbuffer;
this->picture_pile = picture_pile;
this->texture_format = texture_format;
}
@@ -89,8 +85,6 @@ void PictureDrawQuad::ExtendValue(base::DictionaryValue* value) const {
ContentDrawQuadBase::ExtendValue(value);
value->Set("content_rect", MathUtil::AsValue(content_rect).release());
value->SetDouble("contents_scale", contents_scale);
- value->SetBoolean("can_draw_direct_to_backbuffer",
- can_draw_direct_to_backbuffer);
value->SetInteger("texture_format", texture_format);
// TODO(piman): picture_pile?
}
diff --git a/chromium/cc/quads/picture_draw_quad.h b/chromium/cc/quads/picture_draw_quad.h
index 756482a610b..9bea70b4609 100644
--- a/chromium/cc/quads/picture_draw_quad.h
+++ b/chromium/cc/quads/picture_draw_quad.h
@@ -30,7 +30,6 @@ class CC_EXPORT PictureDrawQuad : public ContentDrawQuadBase {
ResourceFormat texture_format,
gfx::Rect content_rect,
float contents_scale,
- bool can_draw_direct_to_backbuffer,
scoped_refptr<PicturePileImpl> picture_pile);
void SetAll(const SharedQuadState* shared_quad_state,
@@ -43,12 +42,10 @@ class CC_EXPORT PictureDrawQuad : public ContentDrawQuadBase {
ResourceFormat texture_format,
gfx::Rect content_rect,
float contents_scale,
- bool can_draw_direct_to_backbuffer,
scoped_refptr<PicturePileImpl> picture_pile);
gfx::Rect content_rect;
float contents_scale;
- bool can_draw_direct_to_backbuffer;
scoped_refptr<PicturePileImpl> picture_pile;
ResourceFormat texture_format;
diff --git a/chromium/cc/quads/render_pass.cc b/chromium/cc/quads/render_pass.cc
index 50d502884b4..53cb83703a3 100644
--- a/chromium/cc/quads/render_pass.cc
+++ b/chromium/cc/quads/render_pass.cc
@@ -9,23 +9,45 @@
#include "cc/debug/traced_value.h"
#include "cc/output/copy_output_request.h"
#include "cc/quads/draw_quad.h"
+#include "cc/quads/render_pass_draw_quad.h"
#include "cc/quads/shared_quad_state.h"
+namespace {
+const size_t kDefaultNumSharedQuadStatesToReserve = 32;
+const size_t kDefaultNumQuadsToReserve = 128;
+}
+
namespace cc {
void* RenderPass::Id::AsTracingId() const {
- COMPILE_ASSERT(sizeof(size_t) <= sizeof(void*), size_t_bigger_than_pointer);
+ COMPILE_ASSERT(sizeof(size_t) <= sizeof(void*), // NOLINT(runtime/sizeof)
+ size_t_bigger_than_pointer);
return reinterpret_cast<void*>(base::HashPair(layer_id, index));
}
scoped_ptr<RenderPass> RenderPass::Create() {
- return make_scoped_ptr(new RenderPass);
+ return make_scoped_ptr(new RenderPass());
+}
+
+scoped_ptr<RenderPass> RenderPass::Create(size_t num_layers) {
+ return make_scoped_ptr(new RenderPass(num_layers));
}
RenderPass::RenderPass()
: id(Id(-1, -1)),
- has_transparent_background(true),
- has_occlusion_from_outside_target_surface(false) {}
+ has_transparent_background(true) {
+ shared_quad_state_list.reserve(kDefaultNumSharedQuadStatesToReserve);
+ quad_list.reserve(kDefaultNumQuadsToReserve);
+}
+
+RenderPass::RenderPass(size_t num_layers)
+ : id(Id(-1, -1)),
+ has_transparent_background(true) {
+ // Each layer usually produces one shared quad state, so the number of layers
+ // is a good hint for what to reserve here.
+ shared_quad_state_list.reserve(num_layers);
+ quad_list.reserve(kDefaultNumQuadsToReserve);
+}
RenderPass::~RenderPass() {
TRACE_EVENT_OBJECT_DELETED_WITH_ID(
@@ -39,11 +61,56 @@ scoped_ptr<RenderPass> RenderPass::Copy(Id new_id) const {
output_rect,
damage_rect,
transform_to_root_target,
- has_transparent_background,
- has_occlusion_from_outside_target_surface);
+ has_transparent_background);
return copy_pass.Pass();
}
+// static
+void RenderPass::CopyAll(const ScopedPtrVector<RenderPass>& in,
+ ScopedPtrVector<RenderPass>* out) {
+ for (size_t i = 0; i < in.size(); ++i) {
+ RenderPass* source = in[i];
+
+ // Since we can't copy these, it's wrong to use CopyAll in a situation where
+ // you may have copy_requests present.
+ DCHECK_EQ(source->copy_requests.size(), 0u);
+
+ scoped_ptr<RenderPass> copy_pass(Create());
+ copy_pass->SetAll(source->id,
+ source->output_rect,
+ source->damage_rect,
+ source->transform_to_root_target,
+ source->has_transparent_background);
+ for (size_t i = 0; i < source->shared_quad_state_list.size(); ++i) {
+ copy_pass->shared_quad_state_list.push_back(
+ source->shared_quad_state_list[i]->Copy());
+ }
+ for (size_t i = 0, sqs_i = 0; i < source->quad_list.size(); ++i) {
+ while (source->quad_list[i]->shared_quad_state !=
+ source->shared_quad_state_list[sqs_i]) {
+ ++sqs_i;
+ DCHECK_LT(sqs_i, source->shared_quad_state_list.size());
+ }
+ DCHECK(source->quad_list[i]->shared_quad_state ==
+ source->shared_quad_state_list[sqs_i]);
+
+ DrawQuad* quad = source->quad_list[i];
+
+ if (quad->material == DrawQuad::RENDER_PASS) {
+ const RenderPassDrawQuad* pass_quad =
+ RenderPassDrawQuad::MaterialCast(quad);
+ copy_pass->quad_list.push_back(
+ pass_quad->Copy(copy_pass->shared_quad_state_list[sqs_i],
+ pass_quad->render_pass_id).PassAs<DrawQuad>());
+ } else {
+ copy_pass->quad_list.push_back(source->quad_list[i]->Copy(
+ copy_pass->shared_quad_state_list[sqs_i]));
+ }
+ }
+ out->push_back(copy_pass.Pass());
+ }
+}
+
void RenderPass::SetNew(Id id,
gfx::Rect output_rect,
gfx::RectF damage_rect,
@@ -64,8 +131,7 @@ void RenderPass::SetAll(Id id,
gfx::Rect output_rect,
gfx::RectF damage_rect,
const gfx::Transform& transform_to_root_target,
- bool has_transparent_background,
- bool has_occlusion_from_outside_target_surface) {
+ bool has_transparent_background) {
DCHECK_GT(id.layer_id, 0);
DCHECK_GE(id.index, 0);
@@ -74,8 +140,6 @@ void RenderPass::SetAll(Id id,
this->damage_rect = damage_rect;
this->transform_to_root_target = transform_to_root_target;
this->has_transparent_background = has_transparent_background;
- this->has_occlusion_from_outside_target_surface =
- has_occlusion_from_outside_target_surface;
DCHECK(quad_list.empty());
DCHECK(shared_quad_state_list.empty());
@@ -86,8 +150,6 @@ scoped_ptr<base::Value> RenderPass::AsValue() const {
value->Set("output_rect", MathUtil::AsValue(output_rect).release());
value->Set("damage_rect", MathUtil::AsValue(damage_rect).release());
value->SetBoolean("has_transparent_background", has_transparent_background);
- value->SetBoolean("has_occlusion_from_outside_target_surface",
- has_occlusion_from_outside_target_surface);
value->SetInteger("copy_requests", copy_requests.size());
scoped_ptr<base::ListValue> shared_states_value(new base::ListValue());
for (size_t i = 0; i < shared_quad_state_list.size(); ++i) {
diff --git a/chromium/cc/quads/render_pass.h b/chromium/cc/quads/render_pass.h
index cf2a02d4a3c..407381fb172 100644
--- a/chromium/cc/quads/render_pass.h
+++ b/chromium/cc/quads/render_pass.h
@@ -65,10 +65,16 @@ class CC_EXPORT RenderPass {
~RenderPass();
static scoped_ptr<RenderPass> Create();
+ static scoped_ptr<RenderPass> Create(size_t num_layers);
- // A shallow copy of the render pass, which does not include its quads.
+ // A shallow copy of the render pass, which does not include its quads or copy
+ // requests.
scoped_ptr<RenderPass> Copy(Id new_id) const;
+ // A deep copy of the render passes in the list including the quads.
+ static void CopyAll(const ScopedPtrVector<RenderPass>& in,
+ ScopedPtrVector<RenderPass>* out);
+
void SetNew(Id id,
gfx::Rect output_rect,
gfx::RectF damage_rect,
@@ -78,8 +84,7 @@ class CC_EXPORT RenderPass {
gfx::Rect output_rect,
gfx::RectF damage_rect,
const gfx::Transform& transform_to_root_target,
- bool has_transparent_background,
- bool has_occlusion_from_outside_target_surface);
+ bool has_transparent_background);
scoped_ptr<base::Value> AsValue() const;
@@ -97,10 +102,6 @@ class CC_EXPORT RenderPass {
// If false, the pixels in the render pass' texture are all opaque.
bool has_transparent_background;
- // If true, then there may be pixels in the render pass' texture that are not
- // complete, since they are occluded.
- bool has_occlusion_from_outside_target_surface;
-
// If non-empty, the renderer should produce a copy of the render pass'
// contents as a bitmap, and give a copy of the bitmap to each callback in
// this list. This property should not be serialized between compositors, as
@@ -111,6 +112,7 @@ class CC_EXPORT RenderPass {
SharedQuadStateList shared_quad_state_list;
protected:
+ explicit RenderPass(size_t num_layers);
RenderPass();
private:
diff --git a/chromium/cc/quads/render_pass_draw_quad.cc b/chromium/cc/quads/render_pass_draw_quad.cc
index 73b2553e209..af8cd8c492c 100644
--- a/chromium/cc/quads/render_pass_draw_quad.cc
+++ b/chromium/cc/quads/render_pass_draw_quad.cc
@@ -43,7 +43,6 @@ void RenderPassDrawQuad::SetNew(
gfx::Rect contents_changed_since_last_frame,
gfx::RectF mask_uv_rect,
const FilterOperations& filters,
- skia::RefPtr<SkImageFilter> filter,
const FilterOperations& background_filters) {
DCHECK_GT(render_pass_id.layer_id, 0);
DCHECK_GE(render_pass_id.index, 0);
@@ -53,7 +52,7 @@ void RenderPassDrawQuad::SetNew(
bool needs_blending = false;
SetAll(shared_quad_state, rect, opaque_rect, visible_rect, needs_blending,
render_pass_id, is_replica, mask_resource_id,
- contents_changed_since_last_frame, mask_uv_rect, filters, filter,
+ contents_changed_since_last_frame, mask_uv_rect, filters,
background_filters);
}
@@ -69,7 +68,6 @@ void RenderPassDrawQuad::SetAll(
gfx::Rect contents_changed_since_last_frame,
gfx::RectF mask_uv_rect,
const FilterOperations& filters,
- skia::RefPtr<SkImageFilter> filter,
const FilterOperations& background_filters) {
DCHECK_GT(render_pass_id.layer_id, 0);
DCHECK_GE(render_pass_id.index, 0);
@@ -82,7 +80,6 @@ void RenderPassDrawQuad::SetAll(
this->contents_changed_since_last_frame = contents_changed_since_last_frame;
this->mask_uv_rect = mask_uv_rect;
this->filters = filters;
- this->filter = filter;
this->background_filters = background_filters;
}
@@ -107,9 +104,6 @@ void RenderPassDrawQuad::ExtendValue(base::DictionaryValue* value) const {
MathUtil::AsValue(contents_changed_since_last_frame).release());
value->Set("mask_uv_rect", MathUtil::AsValue(mask_uv_rect).release());
value->Set("filters", filters.AsValue().release());
- // TODO(piman): dump SkImageFilters rather than just indicating if there are
- // any or not.
- value->SetBoolean("has_filter", !!filter);
value->Set("background_filters", background_filters.AsValue().release());
}
diff --git a/chromium/cc/quads/render_pass_draw_quad.h b/chromium/cc/quads/render_pass_draw_quad.h
index e253dec430b..8546c45621c 100644
--- a/chromium/cc/quads/render_pass_draw_quad.h
+++ b/chromium/cc/quads/render_pass_draw_quad.h
@@ -28,7 +28,6 @@ class CC_EXPORT RenderPassDrawQuad : public DrawQuad {
gfx::Rect contents_changed_since_last_frame,
gfx::RectF mask_uv_rect,
const FilterOperations& filters,
- skia::RefPtr<SkImageFilter> filter,
const FilterOperations& background_filters);
void SetAll(const SharedQuadState* shared_quad_state,
@@ -42,7 +41,6 @@ class CC_EXPORT RenderPassDrawQuad : public DrawQuad {
gfx::Rect contents_changed_since_last_frame,
gfx::RectF mask_uv_rect,
const FilterOperations& filters,
- skia::RefPtr<SkImageFilter> filter,
const FilterOperations& background_filters);
scoped_ptr<RenderPassDrawQuad> Copy(
@@ -55,11 +53,8 @@ class CC_EXPORT RenderPassDrawQuad : public DrawQuad {
gfx::Rect contents_changed_since_last_frame;
gfx::RectF mask_uv_rect;
- // Deprecated post-processing filters, applied to the pixels in the render
- // pass' texture.
+ // Post-processing filters, applied to the pixels in the render pass' texture.
FilterOperations filters;
- // Post-processing filter applied to the pixels in the render pass' texture.
- skia::RefPtr<SkImageFilter> filter;
// Post-processing filters, applied to the pixels showing through the
// background of the render pass, from behind it.
diff --git a/chromium/cc/quads/render_pass_unittest.cc b/chromium/cc/quads/render_pass_unittest.cc
index b12faa89840..e70a33dd685 100644
--- a/chromium/cc/quads/render_pass_unittest.cc
+++ b/chromium/cc/quads/render_pass_unittest.cc
@@ -8,6 +8,7 @@
#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/test/geometry_test_utils.h"
#include "cc/test/render_pass_test_common.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -29,10 +30,38 @@ struct RenderPassSize {
gfx::Rect output_rect;
gfx::RectF damage_rect;
bool has_transparent_background;
- bool has_occlusion_from_outside_target_surface;
ScopedPtrVector<CopyOutputRequest> copy_callbacks;
};
+static void CompareRenderPassLists(const RenderPassList& expected_list,
+ const RenderPassList& actual_list) {
+ EXPECT_EQ(expected_list.size(), actual_list.size());
+ for (size_t i = 0; i < actual_list.size(); ++i) {
+ RenderPass* expected = expected_list[i];
+ RenderPass* actual = actual_list[i];
+
+ EXPECT_EQ(expected->id, actual->id);
+ EXPECT_RECT_EQ(expected->output_rect, actual->output_rect);
+ EXPECT_EQ(expected->transform_to_root_target,
+ actual->transform_to_root_target);
+ EXPECT_RECT_EQ(expected->damage_rect, actual->damage_rect);
+ EXPECT_EQ(expected->has_transparent_background,
+ actual->has_transparent_background);
+
+ EXPECT_EQ(expected->shared_quad_state_list.size(),
+ actual->shared_quad_state_list.size());
+ EXPECT_EQ(expected->quad_list.size(), actual->quad_list.size());
+
+ for (size_t i = 0; i < expected->quad_list.size(); ++i) {
+ EXPECT_EQ(expected->quad_list[i]->rect.ToString(),
+ actual->quad_list[i]->rect.ToString());
+ EXPECT_EQ(
+ expected->quad_list[i]->shared_quad_state->content_bounds.ToString(),
+ actual->quad_list[i]->shared_quad_state->content_bounds.ToString());
+ }
+ }
+}
+
TEST(RenderPassTest, CopyShouldBeIdenticalExceptIdAndQuads) {
RenderPass::Id id(3, 2);
gfx::Rect output_rect(45, 22, 120, 13);
@@ -40,21 +69,24 @@ TEST(RenderPassTest, CopyShouldBeIdenticalExceptIdAndQuads) {
gfx::Transform(1.0, 0.5, 0.5, -0.5, -1.0, 0.0);
gfx::Rect damage_rect(56, 123, 19, 43);
bool has_transparent_background = true;
- bool has_occlusion_from_outside_target_surface = true;
scoped_ptr<TestRenderPass> pass = TestRenderPass::Create();
pass->SetAll(id,
output_rect,
damage_rect,
transform_to_root,
- has_transparent_background,
- has_occlusion_from_outside_target_surface);
+ has_transparent_background);
pass->copy_requests.push_back(CopyOutputRequest::CreateEmptyRequest());
// Stick a quad in the pass, this should not get copied.
scoped_ptr<SharedQuadState> shared_state = SharedQuadState::Create();
- shared_state->SetAll(
- gfx::Transform(), gfx::Size(), gfx::Rect(), gfx::Rect(), false, 1);
+ shared_state->SetAll(gfx::Transform(),
+ gfx::Size(),
+ gfx::Rect(),
+ gfx::Rect(),
+ false,
+ 1,
+ SkXfermode::kSrcOver_Mode);
pass->AppendSharedQuadState(shared_state.Pass());
scoped_ptr<CheckerboardDrawQuad> checkerboard_quad =
@@ -71,8 +103,6 @@ TEST(RenderPassTest, CopyShouldBeIdenticalExceptIdAndQuads) {
EXPECT_EQ(pass->transform_to_root_target, copy->transform_to_root_target);
EXPECT_RECT_EQ(pass->damage_rect, copy->damage_rect);
EXPECT_EQ(pass->has_transparent_background, copy->has_transparent_background);
- EXPECT_EQ(pass->has_occlusion_from_outside_target_surface,
- copy->has_occlusion_from_outside_target_surface);
EXPECT_EQ(0u, copy->quad_list.size());
// The copy request should not be copied/duplicated.
@@ -82,5 +112,204 @@ TEST(RenderPassTest, CopyShouldBeIdenticalExceptIdAndQuads) {
EXPECT_EQ(sizeof(RenderPassSize), sizeof(RenderPass));
}
+TEST(RenderPassTest, CopyAllShouldBeIdentical) {
+ RenderPassList pass_list;
+
+ RenderPass::Id id(3, 2);
+ gfx::Rect output_rect(45, 22, 120, 13);
+ gfx::Transform transform_to_root =
+ gfx::Transform(1.0, 0.5, 0.5, -0.5, -1.0, 0.0);
+ gfx::Rect damage_rect(56, 123, 19, 43);
+ bool has_transparent_background = true;
+
+ scoped_ptr<TestRenderPass> pass = TestRenderPass::Create();
+ pass->SetAll(id,
+ output_rect,
+ damage_rect,
+ transform_to_root,
+ has_transparent_background);
+
+ // Two quads using one shared state.
+ scoped_ptr<SharedQuadState> shared_state1 = SharedQuadState::Create();
+ shared_state1->SetAll(gfx::Transform(),
+ gfx::Size(1, 1),
+ gfx::Rect(),
+ gfx::Rect(),
+ false,
+ 1,
+ SkXfermode::kSrcOver_Mode);
+ pass->AppendSharedQuadState(shared_state1.Pass());
+
+ scoped_ptr<CheckerboardDrawQuad> checkerboard_quad1 =
+ CheckerboardDrawQuad::Create();
+ checkerboard_quad1->SetNew(
+ pass->shared_quad_state_list.back(), gfx::Rect(1, 1, 1, 1), SkColor());
+ pass->quad_list.push_back(checkerboard_quad1.PassAs<DrawQuad>());
+
+ scoped_ptr<CheckerboardDrawQuad> checkerboard_quad2 =
+ CheckerboardDrawQuad::Create();
+ checkerboard_quad2->SetNew(
+ pass->shared_quad_state_list.back(), gfx::Rect(2, 2, 2, 2), SkColor());
+ pass->quad_list.push_back(checkerboard_quad2.PassAs<DrawQuad>());
+
+ // And two quads using another shared state.
+ scoped_ptr<SharedQuadState> shared_state2 = SharedQuadState::Create();
+ shared_state2->SetAll(gfx::Transform(),
+ gfx::Size(2, 2),
+ gfx::Rect(),
+ gfx::Rect(),
+ false,
+ 1,
+ SkXfermode::kSrcOver_Mode);
+ pass->AppendSharedQuadState(shared_state2.Pass());
+
+ scoped_ptr<CheckerboardDrawQuad> checkerboard_quad3 =
+ CheckerboardDrawQuad::Create();
+ checkerboard_quad3->SetNew(
+ pass->shared_quad_state_list.back(), gfx::Rect(3, 3, 3, 3), SkColor());
+ pass->quad_list.push_back(checkerboard_quad3.PassAs<DrawQuad>());
+
+ scoped_ptr<CheckerboardDrawQuad> checkerboard_quad4 =
+ CheckerboardDrawQuad::Create();
+ checkerboard_quad4->SetNew(
+ pass->shared_quad_state_list.back(), gfx::Rect(4, 4, 4, 4), SkColor());
+ pass->quad_list.push_back(checkerboard_quad4.PassAs<DrawQuad>());
+
+ // A second render pass with a quad.
+ RenderPass::Id contrib_id(4, 1);
+ gfx::Rect contrib_output_rect(10, 15, 12, 17);
+ gfx::Transform contrib_transform_to_root =
+ gfx::Transform(1.0, 0.5, 0.5, -0.5, -1.0, 0.0);
+ gfx::Rect contrib_damage_rect(11, 16, 10, 15);
+ bool contrib_has_transparent_background = true;
+
+ scoped_ptr<TestRenderPass> contrib = TestRenderPass::Create();
+ contrib->SetAll(contrib_id,
+ contrib_output_rect,
+ contrib_damage_rect,
+ contrib_transform_to_root,
+ contrib_has_transparent_background);
+
+ scoped_ptr<SharedQuadState> contrib_shared_state = SharedQuadState::Create();
+ contrib_shared_state->SetAll(gfx::Transform(),
+ gfx::Size(2, 2),
+ gfx::Rect(),
+ gfx::Rect(),
+ false,
+ 1,
+ SkXfermode::kSrcOver_Mode);
+ contrib->AppendSharedQuadState(contrib_shared_state.Pass());
+
+ scoped_ptr<CheckerboardDrawQuad> contrib_quad =
+ CheckerboardDrawQuad::Create();
+ contrib_quad->SetNew(
+ contrib->shared_quad_state_list.back(), gfx::Rect(3, 3, 3, 3), SkColor());
+ contrib->quad_list.push_back(contrib_quad.PassAs<DrawQuad>());
+
+ // And a RenderPassDrawQuad for the contributing pass.
+ scoped_ptr<RenderPassDrawQuad> pass_quad = RenderPassDrawQuad::Create();
+ pass_quad->SetNew(pass->shared_quad_state_list.back(),
+ contrib_output_rect,
+ contrib_id,
+ false, // is_replica
+ 0, // mask_resource_id
+ contrib_damage_rect,
+ gfx::RectF(), // mask_uv_rect
+ FilterOperations(),
+ FilterOperations());
+ pass->quad_list.push_back(pass_quad.PassAs<DrawQuad>());
+
+ pass_list.push_back(pass.PassAs<RenderPass>());
+ pass_list.push_back(contrib.PassAs<RenderPass>());
+
+ // Make a copy with CopyAll().
+ RenderPassList copy_list;
+ RenderPass::CopyAll(pass_list, &copy_list);
+
+ CompareRenderPassLists(pass_list, copy_list);
+}
+
+TEST(RenderPassTest, CopyAllWithCulledQuads) {
+ RenderPassList pass_list;
+
+ RenderPass::Id id(3, 2);
+ gfx::Rect output_rect(45, 22, 120, 13);
+ gfx::Transform transform_to_root =
+ gfx::Transform(1.0, 0.5, 0.5, -0.5, -1.0, 0.0);
+ gfx::Rect damage_rect(56, 123, 19, 43);
+ bool has_transparent_background = true;
+
+ scoped_ptr<TestRenderPass> pass = TestRenderPass::Create();
+ pass->SetAll(id,
+ output_rect,
+ damage_rect,
+ transform_to_root,
+ has_transparent_background);
+
+ // A shared state with a quad.
+ scoped_ptr<SharedQuadState> shared_state1 = SharedQuadState::Create();
+ shared_state1->SetAll(gfx::Transform(),
+ gfx::Size(1, 1),
+ gfx::Rect(),
+ gfx::Rect(),
+ false,
+ 1,
+ SkXfermode::kSrcOver_Mode);
+ pass->AppendSharedQuadState(shared_state1.Pass());
+
+ scoped_ptr<CheckerboardDrawQuad> checkerboard_quad1 =
+ CheckerboardDrawQuad::Create();
+ checkerboard_quad1->SetNew(
+ pass->shared_quad_state_list.back(), gfx::Rect(1, 1, 1, 1), SkColor());
+ pass->quad_list.push_back(checkerboard_quad1.PassAs<DrawQuad>());
+
+ // A shared state with no quads, they were culled.
+ scoped_ptr<SharedQuadState> shared_state2 = SharedQuadState::Create();
+ shared_state2->SetAll(gfx::Transform(),
+ gfx::Size(2, 2),
+ gfx::Rect(),
+ gfx::Rect(),
+ false,
+ 1,
+ SkXfermode::kSrcOver_Mode);
+ pass->AppendSharedQuadState(shared_state2.Pass());
+
+ // A second shared state with no quads.
+ scoped_ptr<SharedQuadState> shared_state3 = SharedQuadState::Create();
+ shared_state3->SetAll(gfx::Transform(),
+ gfx::Size(2, 2),
+ gfx::Rect(),
+ gfx::Rect(),
+ false,
+ 1,
+ SkXfermode::kSrcOver_Mode);
+ pass->AppendSharedQuadState(shared_state3.Pass());
+
+ // A last shared state with a quad again.
+ scoped_ptr<SharedQuadState> shared_state4 = SharedQuadState::Create();
+ shared_state4->SetAll(gfx::Transform(),
+ gfx::Size(2, 2),
+ gfx::Rect(),
+ gfx::Rect(),
+ false,
+ 1,
+ SkXfermode::kSrcOver_Mode);
+ pass->AppendSharedQuadState(shared_state4.Pass());
+
+ scoped_ptr<CheckerboardDrawQuad> checkerboard_quad2 =
+ CheckerboardDrawQuad::Create();
+ checkerboard_quad2->SetNew(
+ pass->shared_quad_state_list.back(), gfx::Rect(3, 3, 3, 3), SkColor());
+ pass->quad_list.push_back(checkerboard_quad2.PassAs<DrawQuad>());
+
+ pass_list.push_back(pass.PassAs<RenderPass>());
+
+ // Make a copy with CopyAll().
+ RenderPassList copy_list;
+ RenderPass::CopyAll(pass_list, &copy_list);
+
+ CompareRenderPassLists(pass_list, copy_list);
+}
+
} // namespace
} // namespace cc
diff --git a/chromium/cc/quads/shared_quad_state.cc b/chromium/cc/quads/shared_quad_state.cc
index 6a53d9f6a9f..56584577917 100644
--- a/chromium/cc/quads/shared_quad_state.cc
+++ b/chromium/cc/quads/shared_quad_state.cc
@@ -10,7 +10,8 @@
namespace cc {
-SharedQuadState::SharedQuadState() : is_clipped(false), opacity(0.f) {}
+SharedQuadState::SharedQuadState()
+ : is_clipped(false), opacity(0.f), blend_mode(SkXfermode::kSrcOver_Mode) {}
SharedQuadState::~SharedQuadState() {
TRACE_EVENT_OBJECT_DELETED_WITH_ID(
@@ -26,19 +27,20 @@ scoped_ptr<SharedQuadState> SharedQuadState::Copy() const {
return make_scoped_ptr(new SharedQuadState(*this));
}
-void SharedQuadState::SetAll(
- const gfx::Transform& content_to_target_transform,
- gfx::Size content_bounds,
- gfx::Rect visible_content_rect,
- gfx::Rect clip_rect,
- bool is_clipped,
- float opacity) {
+void SharedQuadState::SetAll(const gfx::Transform& content_to_target_transform,
+ gfx::Size content_bounds,
+ gfx::Rect visible_content_rect,
+ gfx::Rect clip_rect,
+ bool is_clipped,
+ float opacity,
+ SkXfermode::Mode blend_mode) {
this->content_to_target_transform = content_to_target_transform;
this->content_bounds = content_bounds;
this->visible_content_rect = visible_content_rect;
this->clip_rect = clip_rect;
this->is_clipped = is_clipped;
this->opacity = opacity;
+ this->blend_mode = blend_mode;
}
scoped_ptr<base::Value> SharedQuadState::AsValue() const {
@@ -52,6 +54,7 @@ scoped_ptr<base::Value> SharedQuadState::AsValue() const {
value->SetBoolean("is_clipped", is_clipped);
value->Set("clip_rect", MathUtil::AsValue(clip_rect).release());
value->SetDouble("opacity", opacity);
+ value->SetString("blend_mode", SkXfermode::ModeName(blend_mode));
TracedValue::MakeDictIntoImplicitSnapshotWithCategory(
TRACE_DISABLED_BY_DEFAULT("cc.debug.quads"),
value.get(), "cc::SharedQuadState", this);
diff --git a/chromium/cc/quads/shared_quad_state.h b/chromium/cc/quads/shared_quad_state.h
index 79bd09b60f7..b70d4a11fb9 100644
--- a/chromium/cc/quads/shared_quad_state.h
+++ b/chromium/cc/quads/shared_quad_state.h
@@ -7,6 +7,7 @@
#include "base/memory/scoped_ptr.h"
#include "cc/base/cc_export.h"
+#include "third_party/skia/include/core/SkXfermode.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/transform.h"
@@ -28,7 +29,8 @@ class CC_EXPORT SharedQuadState {
gfx::Rect visible_content_rect,
gfx::Rect clip_rect,
bool is_clipped,
- float opacity);
+ float opacity,
+ SkXfermode::Mode blend_mode);
scoped_ptr<base::Value> AsValue() const;
// Transforms from quad's original content space to its target content space.
@@ -41,6 +43,7 @@ class CC_EXPORT SharedQuadState {
gfx::Rect clip_rect;
bool is_clipped;
float opacity;
+ SkXfermode::Mode blend_mode;
private:
SharedQuadState();
diff --git a/chromium/cc/quads/texture_draw_quad.cc b/chromium/cc/quads/texture_draw_quad.cc
index ae7cfd6e238..191dcc43e7f 100644
--- a/chromium/cc/quads/texture_draw_quad.cc
+++ b/chromium/cc/quads/texture_draw_quad.cc
@@ -84,80 +84,6 @@ const TextureDrawQuad* TextureDrawQuad::MaterialCast(const DrawQuad* quad) {
return static_cast<const TextureDrawQuad*>(quad);
}
-bool TextureDrawQuad::PerformClipping() {
- // This only occurs if the rect is only scaled and translated (and thus still
- // axis aligned).
- if (!quadTransform().IsPositiveScaleOrTranslation())
- return false;
-
- // Grab our scale and make sure it's positive.
- float x_scale = static_cast<float>(quadTransform().matrix().getDouble(0, 0));
- float y_scale = static_cast<float>(quadTransform().matrix().getDouble(1, 1));
-
- // Grab our offset.
- gfx::Vector2dF offset(
- static_cast<float>(quadTransform().matrix().getDouble(0, 3)),
- static_cast<float>(quadTransform().matrix().getDouble(1, 3)));
-
- // Transform the rect by the scale and offset.
- gfx::RectF rect_f = rect;
- rect_f.Scale(x_scale, y_scale);
- rect_f += offset;
-
- // Perform clipping and check to see if the result is empty.
- gfx::RectF clipped_rect = IntersectRects(rect_f, clipRect());
- if (clipped_rect.IsEmpty()) {
- rect = gfx::Rect();
- uv_top_left = gfx::PointF();
- uv_bottom_right = gfx::PointF();
- return true;
- }
-
- // Create a new uv-rect by clipping the old one to the new bounds.
- gfx::Vector2dF uv_scale(uv_bottom_right - uv_top_left);
- uv_scale.Scale(1.f / rect_f.width(), 1.f / rect_f.height());
- uv_bottom_right = uv_top_left +
- gfx::ScaleVector2d(
- clipped_rect.bottom_right() - rect_f.origin(),
- uv_scale.x(),
- uv_scale.y());
- uv_top_left = uv_top_left +
- gfx::ScaleVector2d(
- clipped_rect.origin() - rect_f.origin(),
- uv_scale.x(),
- uv_scale.y());
-
- // Indexing according to the quad vertex generation:
- // 1--2
- // | |
- // 0--3
- if (vertex_opacity[0] != vertex_opacity[1]
- || vertex_opacity[0] != vertex_opacity[2]
- || vertex_opacity[0] != vertex_opacity[3]) {
- const float x1 = (clipped_rect.x() - rect_f.x()) / rect_f.width();
- const float y1 = (clipped_rect.y() - rect_f.y()) / rect_f.height();
- const float x3 = (clipped_rect.right() - rect_f.x()) / rect_f.width();
- const float y3 = (clipped_rect.bottom() - rect_f.y()) / rect_f.height();
- const float x1y1 = x1 * vertex_opacity[2] + (1.0f - x1) * vertex_opacity[1];
- const float x1y3 = x1 * vertex_opacity[3] + (1.0f - x1) * vertex_opacity[0];
- const float x3y1 = x3 * vertex_opacity[2] + (1.0f - x3) * vertex_opacity[1];
- const float x3y3 = x3 * vertex_opacity[3] + (1.0f - x3) * vertex_opacity[0];
- vertex_opacity[0] = y3 * x1y3 + (1.0f - y3) * x1y1;
- vertex_opacity[1] = y1 * x1y3 + (1.0f - y1) * x1y1;
- vertex_opacity[2] = y1 * x3y3 + (1.0f - y1) * x3y1;
- vertex_opacity[3] = y3 * x3y3 + (1.0f - y3) * x3y1;
- }
-
- // Move the clipped rectangle back into its space.
- clipped_rect -= offset;
- clipped_rect.Scale(1.0f / x_scale, 1.0f / y_scale);
- rect = gfx::Rect(static_cast<int>(clipped_rect.x() + 0.5f),
- static_cast<int>(clipped_rect.y() + 0.5f),
- static_cast<int>(clipped_rect.width() + 0.5f),
- static_cast<int>(clipped_rect.height() + 0.5f));
- return true;
-}
-
void TextureDrawQuad::ExtendValue(base::DictionaryValue* value) const {
value->SetInteger("resource_id", resource_id);
value->SetBoolean("premultiplied_alpha", premultiplied_alpha);
diff --git a/chromium/cc/quads/texture_draw_quad.h b/chromium/cc/quads/texture_draw_quad.h
index 7f066188484..4aa4d7a1642 100644
--- a/chromium/cc/quads/texture_draw_quad.h
+++ b/chromium/cc/quads/texture_draw_quad.h
@@ -53,8 +53,6 @@ class CC_EXPORT TextureDrawQuad : public DrawQuad {
static const TextureDrawQuad* MaterialCast(const DrawQuad*);
- bool PerformClipping();
-
private:
TextureDrawQuad();
virtual void ExtendValue(base::DictionaryValue* value) const OVERRIDE;
diff --git a/chromium/cc/resources/bitmap_content_layer_updater.cc b/chromium/cc/resources/bitmap_content_layer_updater.cc
index 75b99c54b81..fd0fbdaf597 100644
--- a/chromium/cc/resources/bitmap_content_layer_updater.cc
+++ b/chromium/cc/resources/bitmap_content_layer_updater.cc
@@ -59,14 +59,16 @@ void BitmapContentLayerUpdater::PrepareToUpdate(
float contents_width_scale,
float contents_height_scale,
gfx::Rect* resulting_opaque_rect) {
- devtools_instrumentation::ScopedLayerTask paint_layer(
- devtools_instrumentation::kPaintLayer, layer_id_);
if (canvas_size_ != content_rect.size()) {
devtools_instrumentation::ScopedLayerTask paint_setup(
devtools_instrumentation::kPaintSetup, layer_id_);
canvas_size_ = content_rect.size();
- canvas_ = skia::AdoptRef(skia::CreateBitmapCanvas(
- canvas_size_.width(), canvas_size_.height(), layer_is_opaque_));
+ bitmap_backing_.setConfig(
+ SkBitmap::kARGB_8888_Config,
+ canvas_size_.width(), canvas_size_.height(),
+ 0, layer_is_opaque_ ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
+ bitmap_backing_.allocPixels();
+ canvas_ = skia::AdoptRef(new SkCanvas(bitmap_backing_));
}
base::TimeTicks start_time =
diff --git a/chromium/cc/resources/bitmap_content_layer_updater.h b/chromium/cc/resources/bitmap_content_layer_updater.h
index 2a417f06dfa..ecc0c153b7f 100644
--- a/chromium/cc/resources/bitmap_content_layer_updater.h
+++ b/chromium/cc/resources/bitmap_content_layer_updater.h
@@ -8,6 +8,7 @@
#include "cc/base/cc_export.h"
#include "cc/resources/content_layer_updater.h"
#include "skia/ext/refptr.h"
+#include "third_party/skia/include/core/SkBitmap.h"
class SkCanvas;
@@ -65,6 +66,7 @@ class CC_EXPORT BitmapContentLayerUpdater : public ContentLayerUpdater {
int layer_id);
virtual ~BitmapContentLayerUpdater();
+ SkBitmap bitmap_backing_;
skia::RefPtr<SkCanvas> canvas_;
gfx::Size canvas_size_;
bool opaque_;
diff --git a/chromium/cc/resources/bitmap_skpicture_content_layer_updater.cc b/chromium/cc/resources/bitmap_skpicture_content_layer_updater.cc
index 2db3f417a97..cc839a60eee 100644
--- a/chromium/cc/resources/bitmap_skpicture_content_layer_updater.cc
+++ b/chromium/cc/resources/bitmap_skpicture_content_layer_updater.cc
@@ -25,9 +25,9 @@ void BitmapSkPictureContentLayerUpdater::Resource::Update(
gfx::Vector2d dest_offset,
bool partial_update) {
bitmap_.setConfig(
- SkBitmap::kARGB_8888_Config, source_rect.width(), source_rect.height());
+ SkBitmap::kARGB_8888_Config, source_rect.width(), source_rect.height(), 0,
+ updater_->layer_is_opaque() ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
bitmap_.allocPixels();
- bitmap_.setIsOpaque(updater_->layer_is_opaque());
SkBitmapDevice device(bitmap_);
SkCanvas canvas(&device);
updater_->PaintContentsRect(&canvas, source_rect);
@@ -81,9 +81,7 @@ void BitmapSkPictureContentLayerUpdater::PaintContentsRect(
rendering_stats_instrumentation_->EndRecording(start_time);
rendering_stats_instrumentation_->AddRaster(
duration,
- duration,
- source_rect.width() * source_rect.height(),
- false);
+ source_rect.width() * source_rect.height());
}
} // namespace cc
diff --git a/chromium/cc/resources/content_layer_updater.cc b/chromium/cc/resources/content_layer_updater.cc
index 2e73c4bb904..bc6c635dbd0 100644
--- a/chromium/cc/resources/content_layer_updater.cc
+++ b/chromium/cc/resources/content_layer_updater.cc
@@ -60,12 +60,14 @@ void ContentLayerUpdater::PaintContents(SkCanvas* canvas,
SkRect layer_sk_rect = SkRect::MakeXYWH(
layer_rect.x(), layer_rect.y(), layer_rect.width(), layer_rect.height());
+ canvas->clipRect(layer_sk_rect);
+
// If the layer has opaque contents then there is no need to
// clear the canvas before painting.
- if (!layer_is_opaque_)
- canvas->clear(SK_ColorTRANSPARENT);
-
- canvas->clipRect(layer_sk_rect);
+ if (!layer_is_opaque_) {
+ TRACE_EVENT0("cc", "Clear");
+ canvas->drawColor(SK_ColorTRANSPARENT, SkXfermode::kSrc_Mode);
+ }
gfx::RectF opaque_layer_rect;
painter_->Paint(canvas, layer_rect, &opaque_layer_rect);
diff --git a/chromium/cc/resources/etc1_pixel_ref.cc b/chromium/cc/resources/etc1_pixel_ref.cc
new file mode 100644
index 00000000000..7176562317b
--- /dev/null
+++ b/chromium/cc/resources/etc1_pixel_ref.cc
@@ -0,0 +1,38 @@
+// 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/resources/etc1_pixel_ref.h"
+
+#include "base/memory/scoped_ptr.h"
+#include "third_party/skia/include/core/SkPixelRef.h"
+
+namespace cc {
+
+#ifdef SK_SUPPORT_LEGACY_PIXELREF_CONSTRUCTOR
+// Takes ownership of pixels.
+ETC1PixelRef::ETC1PixelRef(scoped_ptr<uint8_t[]> pixels)
+ : pixels_(pixels.Pass()) {
+ setImmutable();
+}
+#endif
+
+// Takes ownership of pixels.
+ETC1PixelRef::ETC1PixelRef(const SkImageInfo& info,
+ scoped_ptr<uint8_t[]> pixels)
+ : SkPixelRef(info), pixels_(pixels.Pass()) {
+ setImmutable();
+}
+
+ETC1PixelRef::~ETC1PixelRef() {}
+
+void* ETC1PixelRef::onLockPixels(SkColorTable** color_table) {
+ *color_table = NULL;
+ return static_cast<void*>(pixels_.get());
+}
+
+void ETC1PixelRef::onUnlockPixels() {}
+
+SkFlattenable::Factory ETC1PixelRef::getFactory() const { return NULL; }
+
+} // namespace cc
diff --git a/chromium/cc/resources/etc1_pixel_ref.h b/chromium/cc/resources/etc1_pixel_ref.h
new file mode 100644
index 00000000000..166e185f533
--- /dev/null
+++ b/chromium/cc/resources/etc1_pixel_ref.h
@@ -0,0 +1,44 @@
+// 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_RESOURCES_ETC1_PIXEL_REF_H_
+#define CC_RESOURCES_ETC1_PIXEL_REF_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "cc/base/cc_export.h"
+#include "third_party/skia/include/core/SkPixelRef.h"
+
+namespace cc {
+
+class CC_EXPORT ETC1PixelRef : public SkPixelRef {
+ public:
+#ifdef SK_SUPPORT_LEGACY_PIXELREF_CONSTRUCTOR
+ // DEPRECATED -- will remove once blink updates to pass info
+ // TODO(reed)
+ explicit ETC1PixelRef(scoped_ptr<uint8_t[]> pixels);
+#endif
+
+ // Takes ownership of pixels.
+ ETC1PixelRef(const SkImageInfo& info, scoped_ptr<uint8_t[]> pixels);
+ virtual ~ETC1PixelRef();
+
+ // SK_DECLARE_UNFLATTENABLE_OBJECT
+ virtual Factory getFactory() const OVERRIDE;
+
+ protected:
+ // Implementation of SkPixelRef.
+ virtual void* onLockPixels(SkColorTable** color_table) OVERRIDE;
+ virtual void onUnlockPixels() OVERRIDE;
+
+ private:
+ scoped_ptr<uint8_t[]> pixels_;
+
+ DISALLOW_COPY_AND_ASSIGN(ETC1PixelRef);
+};
+
+} // namespace cc
+
+#endif // CC_RESOURCES_ETC1_PIXEL_REF_H_
diff --git a/chromium/cc/resources/image_raster_worker_pool.cc b/chromium/cc/resources/image_raster_worker_pool.cc
index 30add2ad2ea..90572ab417d 100644
--- a/chromium/cc/resources/image_raster_worker_pool.cc
+++ b/chromium/cc/resources/image_raster_worker_pool.cc
@@ -57,8 +57,11 @@ class ImageWorkerPoolTaskImpl : public internal::WorkerPoolTask {
} // namespace
ImageRasterWorkerPool::ImageRasterWorkerPool(
- ResourceProvider* resource_provider, size_t num_threads)
+ ResourceProvider* resource_provider,
+ size_t num_threads,
+ GLenum texture_target)
: RasterWorkerPool(resource_provider, num_threads),
+ texture_target_(texture_target),
raster_tasks_pending_(false),
raster_tasks_required_for_activation_pending_(false) {
}
@@ -149,14 +152,17 @@ void ImageRasterWorkerPool::ScheduleTasks(RasterTask::Queue* queue) {
set_raster_required_for_activation_finished_task(
new_raster_required_for_activation_finished_task);
- TRACE_EVENT_ASYNC_STEP1(
+ TRACE_EVENT_ASYNC_STEP_INTO1(
"cc", "ScheduledTasks", this, "rasterizing",
"state", TracedValue::FromValue(StateAsValue().release()));
}
+GLenum ImageRasterWorkerPool::GetResourceTarget() const {
+ return texture_target_;
+}
+
ResourceFormat ImageRasterWorkerPool::GetResourceFormat() const {
- // Only format supported by CHROMIUM_map_image
- return RGBA_8888;
+ return resource_provider()->best_texture_format();
}
void ImageRasterWorkerPool::OnRasterTasksFinished() {
@@ -169,7 +175,7 @@ void ImageRasterWorkerPool::OnRasterTasksFinished() {
void ImageRasterWorkerPool::OnRasterTasksRequiredForActivationFinished() {
DCHECK(raster_tasks_required_for_activation_pending_);
raster_tasks_required_for_activation_pending_ = false;
- TRACE_EVENT_ASYNC_STEP1(
+ TRACE_EVENT_ASYNC_STEP_INTO1(
"cc", "ScheduledTasks", this, "rasterizing",
"state", TracedValue::FromValue(StateAsValue().release()));
client()->DidFinishRunningTasksRequiredForActivation();
diff --git a/chromium/cc/resources/image_raster_worker_pool.h b/chromium/cc/resources/image_raster_worker_pool.h
index 63526493350..38fe04238e1 100644
--- a/chromium/cc/resources/image_raster_worker_pool.h
+++ b/chromium/cc/resources/image_raster_worker_pool.h
@@ -14,20 +14,26 @@ class CC_EXPORT ImageRasterWorkerPool : public RasterWorkerPool {
virtual ~ImageRasterWorkerPool();
static scoped_ptr<RasterWorkerPool> Create(
- ResourceProvider* resource_provider, size_t num_threads) {
+ ResourceProvider* resource_provider,
+ size_t num_threads,
+ GLenum texture_target) {
return make_scoped_ptr<RasterWorkerPool>(
- new ImageRasterWorkerPool(resource_provider, num_threads));
+ new ImageRasterWorkerPool(resource_provider,
+ num_threads,
+ texture_target));
}
// Overridden from RasterWorkerPool:
virtual void ScheduleTasks(RasterTask::Queue* queue) OVERRIDE;
+ virtual GLenum GetResourceTarget() const OVERRIDE;
virtual ResourceFormat GetResourceFormat() const OVERRIDE;
virtual void OnRasterTasksFinished() OVERRIDE;
virtual void OnRasterTasksRequiredForActivationFinished() OVERRIDE;
private:
ImageRasterWorkerPool(ResourceProvider* resource_provider,
- size_t num_threads);
+ size_t num_threads,
+ GLenum texture_target);
void OnRasterTaskCompleted(
scoped_refptr<internal::RasterWorkerPoolTask> task, bool was_canceled);
@@ -43,6 +49,8 @@ class CC_EXPORT ImageRasterWorkerPool : public RasterWorkerPool {
internal::GraphNode* raster_finished_node,
TaskGraph* graph);
+ const GLenum texture_target_;
+
TaskMap image_tasks_;
bool raster_tasks_pending_;
diff --git a/chromium/cc/resources/managed_tile_state.cc b/chromium/cc/resources/managed_tile_state.cc
index 8856d4f5168..b453bd6d95f 100644
--- a/chromium/cc/resources/managed_tile_state.cc
+++ b/chromium/cc/resources/managed_tile_state.cc
@@ -54,8 +54,6 @@ ManagedTileState::ManagedTileState()
distance_to_visible_in_pixels(std::numeric_limits<float>::infinity()),
visible_and_ready_to_draw(false),
scheduled_priority(0) {
- for (int i = 0; i < NUM_TREES; ++i)
- tree_bin[i] = NEVER_BIN;
}
ManagedTileState::TileVersion::TileVersion()
@@ -89,13 +87,19 @@ ManagedTileState::~ManagedTileState() {
}
scoped_ptr<base::Value> ManagedTileState::AsValue() const {
+ bool has_resource = false;
+ bool has_active_task = false;
+ for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) {
+ has_resource |= (tile_versions[mode].resource_.get() != 0);
+ has_active_task |= !tile_versions[mode].raster_task_.is_null();
+ }
+
+ bool is_using_gpu_memory = has_resource || has_active_task;
+
scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
- state->SetBoolean("has_resource",
- tile_versions[raster_mode].resource_.get() != 0);
- state->Set("tree_bin.0",
- ManagedTileBinAsValue(tree_bin[ACTIVE_TREE]).release());
- state->Set("tree_bin.1",
- ManagedTileBinAsValue(tree_bin[PENDING_TREE]).release());
+ state->SetBoolean("has_resource", has_resource);
+ state->SetBoolean("is_using_gpu_memory", is_using_gpu_memory);
+ state->Set("bin", ManagedTileBinAsValue(bin).release());
state->Set("resolution", TileResolutionAsValue(resolution).release());
state->Set("time_to_needed_in_seconds",
MathUtil::AsValueSafely(time_to_needed_in_seconds).release());
@@ -114,4 +118,3 @@ scoped_ptr<base::Value> ManagedTileState::AsValue() const {
}
} // namespace cc
-
diff --git a/chromium/cc/resources/managed_tile_state.h b/chromium/cc/resources/managed_tile_state.h
index 35e4415dd9e..dc6f6d62cb6 100644
--- a/chromium/cc/resources/managed_tile_state.h
+++ b/chromium/cc/resources/managed_tile_state.h
@@ -10,6 +10,7 @@
#include "cc/resources/raster_worker_pool.h"
#include "cc/resources/resource_pool.h"
#include "cc/resources/resource_provider.h"
+#include "cc/resources/scoped_resource.h"
namespace cc {
@@ -111,7 +112,7 @@ class CC_EXPORT ManagedTileState {
Mode mode_;
SkColor solid_color_;
bool has_text_;
- scoped_ptr<ResourcePool::Resource> resource_;
+ scoped_ptr<ScopedResource> resource_;
RasterWorkerPool::RasterTask raster_task_;
};
@@ -125,7 +126,6 @@ class CC_EXPORT ManagedTileState {
RasterMode raster_mode;
ManagedTileBin bin;
- ManagedTileBin tree_bin[NUM_TREES];
TileResolution resolution;
bool required_for_activation;
diff --git a/chromium/cc/resources/picture.cc b/chromium/cc/resources/picture.cc
index f9afca9ee3d..8c3be9c3bca 100644
--- a/chromium/cc/resources/picture.cc
+++ b/chromium/cc/resources/picture.cc
@@ -13,8 +13,6 @@
#include "base/values.h"
#include "cc/base/math_util.h"
#include "cc/base/util.h"
-#include "cc/debug/benchmark_instrumentation.h"
-#include "cc/debug/rendering_stats_instrumentation.h"
#include "cc/debug/traced_picture.h"
#include "cc/debug/traced_value.h"
#include "cc/layers/content_layer_client.h"
@@ -88,7 +86,8 @@ scoped_refptr<Picture> Picture::Create(gfx::Rect layer_rect) {
}
Picture::Picture(gfx::Rect layer_rect)
- : layer_rect_(layer_rect) {
+ : layer_rect_(layer_rect),
+ cell_size_(layer_rect.size()) {
// Instead of recording a trace event for object creation here, we wait for
// the picture to be recorded in Picture::Record.
}
@@ -157,7 +156,8 @@ Picture::Picture(SkPicture* picture,
gfx::Rect opaque_rect) :
layer_rect_(layer_rect),
opaque_rect_(opaque_rect),
- picture_(skia::AdoptRef(picture)) {
+ picture_(skia::AdoptRef(picture)),
+ cell_size_(layer_rect.size()) {
}
Picture::Picture(const skia::RefPtr<SkPicture>& picture,
@@ -167,7 +167,8 @@ Picture::Picture(const skia::RefPtr<SkPicture>& picture,
layer_rect_(layer_rect),
opaque_rect_(opaque_rect),
picture_(picture),
- pixel_refs_(pixel_refs) {
+ pixel_refs_(pixel_refs),
+ cell_size_(layer_rect.size()) {
}
Picture::~Picture() {
@@ -204,11 +205,9 @@ void Picture::CloneForDrawing(int num_threads) {
}
void Picture::Record(ContentLayerClient* painter,
- const SkTileGridPicture::TileGridInfo& tile_grid_info,
- RenderingStatsInstrumentation* stats_instrumentation) {
- TRACE_EVENT1(benchmark_instrumentation::kCategory,
- benchmark_instrumentation::kPictureRecord,
- benchmark_instrumentation::kData, AsTraceableRecordData());
+ const SkTileGridPicture::TileGridInfo& tile_grid_info) {
+ TRACE_EVENT1("cc", "Picture::Record",
+ "data", AsTraceableRecordData());
DCHECK(!tile_grid_info.fTileInterval.isEmpty());
picture_ = skia::AdoptRef(new SkTileGridPicture(
@@ -231,14 +230,9 @@ void Picture::Record(ContentLayerClient* painter,
canvas->clipRect(layer_skrect);
gfx::RectF opaque_layer_rect;
- base::TimeTicks start_time = stats_instrumentation->StartRecording();
painter->PaintContents(canvas, layer_rect_, &opaque_layer_rect);
- base::TimeDelta duration = stats_instrumentation->EndRecording(start_time);
- stats_instrumentation->AddRecord(duration,
- layer_rect_.width() * layer_rect_.height());
-
canvas->restore();
picture_->endRecording();
@@ -248,13 +242,14 @@ void Picture::Record(ContentLayerClient* painter,
}
void Picture::GatherPixelRefs(
- const SkTileGridPicture::TileGridInfo& tile_grid_info,
- RenderingStatsInstrumentation* stats_instrumentation) {
+ const SkTileGridPicture::TileGridInfo& tile_grid_info) {
TRACE_EVENT2("cc", "Picture::GatherPixelRefs",
"width", layer_rect_.width(),
"height", layer_rect_.height());
DCHECK(picture_);
+ if (!WillPlayBackBitmaps())
+ return;
cell_size_ = gfx::Size(
tile_grid_info.fTileInterval.width() +
2 * tile_grid_info.fMargin.width(),
@@ -268,8 +263,6 @@ void Picture::GatherPixelRefs(
int max_x = 0;
int max_y = 0;
- base::TimeTicks start_time = stats_instrumentation->StartRecording();
-
skia::LazyPixelRefList pixel_refs;
skia::LazyPixelRefUtils::GatherPixelRefs(picture_.get(), &pixel_refs);
for (skia::LazyPixelRefList::const_iterator it = pixel_refs.begin();
@@ -299,37 +292,38 @@ void Picture::GatherPixelRefs(
max_y = std::max(max_y, max.y());
}
- base::TimeDelta duration = stats_instrumentation->EndRecording(start_time);
- stats_instrumentation->AddImageGathering(duration);
-
min_pixel_cell_ = gfx::Point(min_x, min_y);
max_pixel_cell_ = gfx::Point(max_x, max_y);
}
-void Picture::Raster(
+int Picture::Raster(
SkCanvas* canvas,
SkDrawPictureCallback* callback,
- gfx::Rect content_rect,
+ const Region& negated_content_region,
float contents_scale) {
- TRACE_EVENT_BEGIN1(benchmark_instrumentation::kCategory,
- benchmark_instrumentation::kPictureRaster,
- "data",
- AsTraceableRasterData(content_rect, contents_scale));
+ TRACE_EVENT_BEGIN1(
+ "cc",
+ "Picture::Raster",
+ "data",
+ AsTraceableRasterData(contents_scale));
DCHECK(picture_);
canvas->save();
- canvas->clipRect(gfx::RectToSkRect(content_rect));
+
+ 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());
picture_->draw(canvas, callback);
SkIRect bounds;
canvas->getClipDeviceBounds(&bounds);
canvas->restore();
- TRACE_EVENT_END1(benchmark_instrumentation::kCategory,
- benchmark_instrumentation::kPictureRaster,
- benchmark_instrumentation::kNumPixelsRasterized,
- bounds.width() * bounds.height());
+ TRACE_EVENT_END1(
+ "cc", "Picture::Raster",
+ "num_pixels_rasterized", bounds.width() * bounds.height());
+ return bounds.width() * bounds.height();
}
void Picture::Replay(SkCanvas* canvas) {
@@ -398,8 +392,9 @@ Picture::PixelRefIterator::PixelRefIterator(
current_index_(0) {
gfx::Rect layer_rect = picture->layer_rect_;
gfx::Size cell_size = picture->cell_size_;
+ DCHECK(!cell_size.IsEmpty());
- // Early out if the query rect doesn't intersect this picture
+ // Early out if the query rect doesn't intersect this picture.
if (!query_rect.Intersects(layer_rect)) {
min_point_ = gfx::Point(0, 0);
max_point_ = gfx::Point(0, 0);
@@ -475,26 +470,20 @@ Picture::PixelRefIterator& Picture::PixelRefIterator::operator++() {
return *this;
}
-scoped_ptr<base::debug::ConvertableToTraceFormat>
- Picture::AsTraceableRasterData(gfx::Rect rect, float scale) const {
+scoped_refptr<base::debug::ConvertableToTraceFormat>
+ Picture::AsTraceableRasterData(float scale) const {
scoped_ptr<base::DictionaryValue> raster_data(new base::DictionaryValue());
raster_data->Set("picture_id", TracedValue::CreateIDRef(this).release());
raster_data->SetDouble("scale", scale);
- raster_data->SetDouble("rect_x", rect.x());
- raster_data->SetDouble("rect_y", rect.y());
- raster_data->SetDouble("rect_width", rect.width());
- raster_data->SetDouble("rect_height", rect.height());
return TracedValue::FromValue(raster_data.release());
}
-scoped_ptr<base::debug::ConvertableToTraceFormat>
+scoped_refptr<base::debug::ConvertableToTraceFormat>
Picture::AsTraceableRecordData() const {
scoped_ptr<base::DictionaryValue> record_data(new base::DictionaryValue());
record_data->Set("picture_id", TracedValue::CreateIDRef(this).release());
- record_data->SetInteger(benchmark_instrumentation::kWidth,
- layer_rect_.width());
- record_data->SetInteger(benchmark_instrumentation::kHeight,
- layer_rect_.height());
+ record_data->SetInteger("width", layer_rect_.width());
+ record_data->SetInteger("height", layer_rect_.height());
return TracedValue::FromValue(record_data.release());
}
diff --git a/chromium/cc/resources/picture.h b/chromium/cc/resources/picture.h
index 238647772fc..085fb6a4531 100644
--- a/chromium/cc/resources/picture.h
+++ b/chromium/cc/resources/picture.h
@@ -17,6 +17,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "cc/base/cc_export.h"
+#include "cc/base/region.h"
#include "skia/ext/lazy_pixel_ref.h"
#include "skia/ext/refptr.h"
#include "third_party/skia/include/core/SkPixelRef.h"
@@ -34,7 +35,6 @@ class AnalysisCanvas;
namespace cc {
class ContentLayerClient;
-class RenderingStatsInstrumentation;
class CC_EXPORT Picture
: public base::RefCountedThreadSafe<Picture> {
@@ -60,21 +60,20 @@ class CC_EXPORT 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,
- const SkTileGridPicture::TileGridInfo& tile_grid_info,
- RenderingStatsInstrumentation* stats_instrumentation);
+ const SkTileGridPicture::TileGridInfo& tile_grid_info);
// Gather pixel refs from recording.
- void GatherPixelRefs(const SkTileGridPicture::TileGridInfo& tile_grid_info,
- RenderingStatsInstrumentation* stats_instrumentation);
+ void GatherPixelRefs(const SkTileGridPicture::TileGridInfo& tile_grid_info);
// Has Record() been called yet?
bool HasRecording() const { return picture_.get() != NULL; }
- // Apply this contents scale and raster the content rect into the canvas.
- void Raster(SkCanvas* canvas,
- SkDrawPictureCallback* callback,
- gfx::Rect content_rect,
- float contents_scale);
+ // Apply this scale and raster the negated region into the canvas. See comment
+ // in PicturePileImpl::RasterCommon for explanation on negated content region.
+ int Raster(SkCanvas* canvas,
+ SkDrawPictureCallback* callback,
+ const Region& negated_content_region,
+ float contents_scale);
// Draw the picture directly into the given canvas, without applying any
// clip/scale/layer transformations.
@@ -118,6 +117,8 @@ class CC_EXPORT Picture
void EmitTraceSnapshot();
void EmitTraceSnapshotAlias(Picture* original);
+ bool WillPlayBackBitmaps() const { return picture_->willPlayBackBitmaps(); }
+
private:
explicit Picture(gfx::Rect layer_rect);
// This constructor assumes SkPicture is already ref'd and transfers
@@ -144,9 +145,9 @@ class CC_EXPORT Picture
gfx::Point max_pixel_cell_;
gfx::Size cell_size_;
- scoped_ptr<base::debug::ConvertableToTraceFormat>
- AsTraceableRasterData(gfx::Rect rect, float scale) const;
- scoped_ptr<base::debug::ConvertableToTraceFormat>
+ scoped_refptr<base::debug::ConvertableToTraceFormat>
+ AsTraceableRasterData(float scale) const;
+ scoped_refptr<base::debug::ConvertableToTraceFormat>
AsTraceableRecordData() const;
friend class base::RefCountedThreadSafe<Picture>;
diff --git a/chromium/cc/resources/picture_layer_tiling.cc b/chromium/cc/resources/picture_layer_tiling.cc
index 12bfb18b441..1aa3567e0a3 100644
--- a/chromium/cc/resources/picture_layer_tiling.cc
+++ b/chromium/cc/resources/picture_layer_tiling.cc
@@ -339,35 +339,6 @@ void PictureLayerTiling::Reset() {
tiles_.clear();
}
-namespace {
-
-bool NearlyOne(SkMScalar lhs) {
- return std::abs(lhs-1.0) < std::numeric_limits<float>::epsilon();
-}
-
-bool NearlyZero(SkMScalar lhs) {
- return std::abs(lhs) < std::numeric_limits<float>::epsilon();
-}
-
-bool ApproximatelyTranslation(const SkMatrix44& matrix) {
- return
- NearlyOne(matrix.get(0, 0)) &&
- NearlyZero(matrix.get(1, 0)) &&
- NearlyZero(matrix.get(2, 0)) &&
- matrix.get(3, 0) == 0 &&
- NearlyZero(matrix.get(0, 1)) &&
- NearlyOne(matrix.get(1, 1)) &&
- NearlyZero(matrix.get(2, 1)) &&
- matrix.get(3, 1) == 0 &&
- NearlyZero(matrix.get(0, 2)) &&
- NearlyZero(matrix.get(1, 2)) &&
- NearlyOne(matrix.get(2, 2)) &&
- matrix.get(3, 2) == 0 &&
- matrix.get(3, 3) == 1;
-}
-
-} // namespace
-
void PictureLayerTiling::UpdateTilePriorities(
WhichTree tree,
gfx::Size device_viewport,
@@ -406,7 +377,8 @@ void PictureLayerTiling::UpdateTilePriorities(
gfx::Rect interest_rect = ExpandRectEquallyToAreaBoundedBy(
starting_rect,
interest_rect_area,
- ContentRect());
+ ContentRect(),
+ &expansion_cache_);
DCHECK(interest_rect.IsEmpty() ||
ContentRect().Contains(interest_rect));
@@ -419,17 +391,15 @@ void PictureLayerTiling::UpdateTilePriorities(
current_frame_time_in_seconds - last_impl_frame_time_in_seconds_;
}
- gfx::Rect view_rect(device_viewport);
+ gfx::RectF view_rect(device_viewport);
float current_scale = current_layer_contents_scale / contents_scale_;
float last_scale = last_layer_contents_scale / contents_scale_;
- bool store_screen_space_quads_on_tiles;
- TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
- &store_screen_space_quads_on_tiles);
-
// Fast path tile priority calculation when both transforms are translations.
- if (ApproximatelyTranslation(last_screen_transform.matrix()) &&
- ApproximatelyTranslation(current_screen_transform.matrix())) {
+ if (last_screen_transform.IsApproximatelyIdentityOrTranslation(
+ std::numeric_limits<float>::epsilon()) &&
+ current_screen_transform.IsApproximatelyIdentityOrTranslation(
+ std::numeric_limits<float>::epsilon())) {
gfx::Vector2dF current_offset(
current_screen_transform.matrix().get(0, 3),
current_screen_transform.matrix().get(1, 3));
@@ -456,7 +426,7 @@ void PictureLayerTiling::UpdateTilePriorities(
last_scale) + last_offset;
float distance_to_visible_in_pixels =
- TilePriority::manhattanDistance(current_screen_rect, view_rect);
+ current_screen_rect.ManhattanInternalDistance(view_rect);
float time_to_visible_in_seconds =
TilePriority::TimeForBoundsToIntersect(
@@ -465,8 +435,6 @@ void PictureLayerTiling::UpdateTilePriorities(
resolution_,
time_to_visible_in_seconds,
distance_to_visible_in_pixels);
- if (store_screen_space_quads_on_tiles)
- priority.set_current_screen_quad(gfx::QuadF(current_screen_rect));
tile->SetPriority(tree, priority);
}
} else if (!last_screen_transform.HasPerspective() &&
@@ -538,7 +506,7 @@ void PictureLayerTiling::UpdateTilePriorities(
last_tile_origin + last_vertical).BoundingBox();
float distance_to_visible_in_pixels =
- TilePriority::manhattanDistance(current_screen_rect, view_rect);
+ current_screen_rect.ManhattanInternalDistance(view_rect);
float time_to_visible_in_seconds =
TilePriority::TimeForBoundsToIntersect(
@@ -547,21 +515,6 @@ void PictureLayerTiling::UpdateTilePriorities(
resolution_,
time_to_visible_in_seconds,
distance_to_visible_in_pixels);
-
- if (store_screen_space_quads_on_tiles) {
- // This overhead is only triggered when logging event tracing data.
- gfx::Rect tile_bounds =
- tiling_data_.TileBounds(iter.index_x(), iter.index_y());
- gfx::RectF current_layer_content_rect = gfx::ScaleRect(
- tile_bounds,
- current_scale,
- current_scale);
- bool clipped;
- priority.set_current_screen_quad(
- MathUtil::MapQuad(current_screen_transform,
- gfx::QuadF(current_layer_content_rect),
- &clipped));
- }
tile->SetPriority(tree, priority);
}
} else {
@@ -588,7 +541,7 @@ void PictureLayerTiling::UpdateTilePriorities(
last_screen_transform, last_layer_content_rect);
float distance_to_visible_in_pixels =
- TilePriority::manhattanDistance(current_screen_rect, view_rect);
+ current_screen_rect.ManhattanInternalDistance(view_rect);
float time_to_visible_in_seconds =
TilePriority::TimeForBoundsToIntersect(
@@ -598,13 +551,6 @@ void PictureLayerTiling::UpdateTilePriorities(
resolution_,
time_to_visible_in_seconds,
distance_to_visible_in_pixels);
- if (store_screen_space_quads_on_tiles) {
- bool clipped;
- priority.set_current_screen_quad(
- MathUtil::MapQuad(current_screen_transform,
- gfx::QuadF(current_layer_content_rect),
- &clipped));
- }
tile->SetPriority(tree, priority);
}
}
@@ -648,6 +594,16 @@ void PictureLayerTiling::SetLiveTilesRect(
live_tiles_rect_ = new_live_tiles_rect;
}
+void PictureLayerTiling::DidBecomeRecycled() {
+ // DidBecomeActive below will set the active priority for tiles that are
+ // still in the tree. Calling this first on an active tiling that is becoming
+ // recycled takes care of tiles that are no longer in the active tree (eg.
+ // due to a pending invalidation).
+ for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) {
+ it->second->SetPriority(ACTIVE_TREE, TilePriority());
+ }
+}
+
void PictureLayerTiling::DidBecomeActive() {
for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) {
it->second->SetPriority(ACTIVE_TREE, it->second->priority(PENDING_TREE));
@@ -687,6 +643,10 @@ 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
@@ -718,10 +678,23 @@ int ComputeExpansionDelta(int num_x_edges, int num_y_edges,
gfx::Rect PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
gfx::Rect starting_rect,
int64 target_area,
- gfx::Rect bounding_rect) {
+ 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);
@@ -735,11 +708,15 @@ gfx::Rect PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
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;
}
@@ -809,7 +786,10 @@ gfx::Rect PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
break;
}
- return gfx::Rect(origin_x, origin_y, width, height);
+ gfx::Rect result(origin_x, origin_y, width, height);
+ if (cache)
+ cache->previous_result = result;
+ return result;
}
} // namespace cc
diff --git a/chromium/cc/resources/picture_layer_tiling.h b/chromium/cc/resources/picture_layer_tiling.h
index 973fa50b73f..dae62723711 100644
--- a/chromium/cc/resources/picture_layer_tiling.h
+++ b/chromium/cc/resources/picture_layer_tiling.h
@@ -34,7 +34,7 @@ class CC_EXPORT PictureLayerTilingClient {
gfx::Size content_bounds) const = 0;
virtual const Region* GetInvalidation() = 0;
virtual const PictureLayerTiling* GetTwinTiling(
- const PictureLayerTiling* tiling) = 0;
+ const PictureLayerTiling* tiling) const = 0;
protected:
virtual ~PictureLayerTilingClient() {}
@@ -78,6 +78,8 @@ class CC_EXPORT PictureLayerTiling {
return all_tiles;
}
+ Tile* TileAt(int i, int j) const;
+
// Iterate over all tiles to fill content_rect. Even if tiles are invalid
// (i.e. no valid resource) this tiling should still iterate over them.
// The union of all geometry_rect calls for each element iterated over should
@@ -107,6 +109,9 @@ class CC_EXPORT PictureLayerTiling {
CoverageIterator& operator++();
operator bool() const { return tile_j_ <= bottom_; }
+ int i() const { return tile_i_; }
+ int j() const { return tile_j_; }
+
private:
const PictureLayerTiling* tiling_;
gfx::Rect dest_rect_;
@@ -147,6 +152,13 @@ class CC_EXPORT PictureLayerTiling {
// also updates the pile on each tile to be the current client's pile.
void DidBecomeActive();
+ // Resets the active priority for all tiles in a tiling, when an active
+ // tiling is becoming recycled. This may include some tiles which are
+ // not in the the pending tiling (due to invalidations). This must
+ // be called before DidBecomeActive, as it resets the active priority
+ // while DidBecomeActive promotes pending priority on a similar set of tiles.
+ void DidBecomeRecycled();
+
void UpdateTilesToCurrentPile();
bool NeedsUpdateForFrameAtTime(double frame_time_in_seconds) {
@@ -156,10 +168,21 @@ class CC_EXPORT PictureLayerTiling {
scoped_ptr<base::Value> AsValue() const;
size_t GPUMemoryUsageInBytes() const;
- static gfx::Rect ExpandRectEquallyToAreaBoundedBy(
+ struct RectExpansionCache {
+ RectExpansionCache();
+
+ gfx::Rect previous_start;
+ gfx::Rect previous_bounds;
+ gfx::Rect previous_result;
+ int64 previous_target;
+ };
+
+ static
+ gfx::Rect ExpandRectEquallyToAreaBoundedBy(
gfx::Rect starting_rect,
int64 target_area,
- gfx::Rect bounding_rect);
+ gfx::Rect bounding_rect,
+ RectExpansionCache* cache);
bool has_ever_been_updated() const {
return last_impl_frame_time_in_seconds_ != 0.0;
@@ -174,7 +197,6 @@ class CC_EXPORT PictureLayerTiling {
PictureLayerTilingClient* client);
void SetLiveTilesRect(gfx::Rect live_tiles_rect);
void CreateTile(int i, int j, const PictureLayerTiling* twin_tiling);
- Tile* TileAt(int, int) const;
// Given properties.
float contents_scale_;
@@ -194,6 +216,8 @@ class CC_EXPORT PictureLayerTiling {
private:
DISALLOW_ASSIGN(PictureLayerTiling);
+
+ RectExpansionCache expansion_cache_;
};
} // namespace cc
diff --git a/chromium/cc/resources/picture_layer_tiling_perftest.cc b/chromium/cc/resources/picture_layer_tiling_perftest.cc
index 655603d2e85..7a9b8dff4b4 100644
--- a/chromium/cc/resources/picture_layer_tiling_perftest.cc
+++ b/chromium/cc/resources/picture_layer_tiling_perftest.cc
@@ -153,7 +153,12 @@ TEST_F(PictureLayerTilingPerfTest, Invalidate) {
RunInvalidateTest("50x50", full_region);
}
+#if defined(OS_ANDROID)
+// TODO(vmpstr): Investigate why this is noisy (crbug.com/310220).
+TEST_F(PictureLayerTilingPerfTest, DISABLED_UpdateTilePriorities) {
+#else
TEST_F(PictureLayerTilingPerfTest, UpdateTilePriorities) {
+#endif // defined(OS_ANDROID)
gfx::Transform transform;
RunUpdateTilePrioritiesStationaryTest("no_transform", transform);
RunUpdateTilePrioritiesScrollingTest("no_transform", transform);
diff --git a/chromium/cc/resources/picture_layer_tiling_set.cc b/chromium/cc/resources/picture_layer_tiling_set.cc
index 14c9cc87a30..5ad26506fd7 100644
--- a/chromium/cc/resources/picture_layer_tiling_set.cc
+++ b/chromium/cc/resources/picture_layer_tiling_set.cc
@@ -343,6 +343,11 @@ void PictureLayerTilingSet::DidBecomeActive() {
tilings_[i]->DidBecomeActive();
}
+void PictureLayerTilingSet::DidBecomeRecycled() {
+ for (size_t i = 0; i < tilings_.size(); ++i)
+ tilings_[i]->DidBecomeRecycled();
+}
+
scoped_ptr<base::Value> PictureLayerTilingSet::AsValue() const {
scoped_ptr<base::ListValue> state(new base::ListValue());
for (size_t i = 0; i < tilings_.size(); ++i)
diff --git a/chromium/cc/resources/picture_layer_tiling_set.h b/chromium/cc/resources/picture_layer_tiling_set.h
index 9a3f00db61f..29e6bf453f5 100644
--- a/chromium/cc/resources/picture_layer_tiling_set.h
+++ b/chromium/cc/resources/picture_layer_tiling_set.h
@@ -69,6 +69,7 @@ class CC_EXPORT PictureLayerTilingSet {
size_t max_tiles_for_interest_area);
void DidBecomeActive();
+ void DidBecomeRecycled();
// For a given rect, iterates through tiles that can fill it. If no
// set of tiles with resources can fill the rect, then it will iterate
diff --git a/chromium/cc/resources/picture_layer_tiling_set_unittest.cc b/chromium/cc/resources/picture_layer_tiling_set_unittest.cc
index 231e378fbd0..96129c64fe5 100644
--- a/chromium/cc/resources/picture_layer_tiling_set_unittest.cc
+++ b/chromium/cc/resources/picture_layer_tiling_set_unittest.cc
@@ -66,9 +66,9 @@ class PictureLayerTilingSetTestWithResources : public testing::Test {
CHECK(output_surface->BindToClient(&output_surface_client));
scoped_ptr<ResourceProvider> resource_provider =
- ResourceProvider::Create(output_surface.get(), 0, false);
+ ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1);
- FakePictureLayerTilingClient client;
+ FakePictureLayerTilingClient client(resource_provider.get());
client.SetTileSize(gfx::Size(256, 256));
gfx::Size layer_bounds(1000, 800);
PictureLayerTilingSet set(&client, layer_bounds);
diff --git a/chromium/cc/resources/picture_layer_tiling_unittest.cc b/chromium/cc/resources/picture_layer_tiling_unittest.cc
index af70f297ed2..6adc6116454 100644
--- a/chromium/cc/resources/picture_layer_tiling_unittest.cc
+++ b/chromium/cc/resources/picture_layer_tiling_unittest.cc
@@ -266,7 +266,7 @@ TEST(PictureLayerTilingTest, ExpandRectEqual) {
gfx::Rect bounds(-1000, -1000, 10000, 10000);
int64 target_area = 100 * 200;
gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
- in, target_area, bounds);
+ in, target_area, bounds, NULL);
EXPECT_EQ(in.ToString(), out.ToString());
}
@@ -275,7 +275,7 @@ TEST(PictureLayerTilingTest, ExpandRectSmaller) {
gfx::Rect bounds(-1000, -1000, 10000, 10000);
int64 target_area = 100 * 100;
gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
- in, target_area, bounds);
+ 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());
@@ -288,7 +288,7 @@ TEST(PictureLayerTilingTest, ExpandRectUnbounded) {
gfx::Rect bounds(-1000, -1000, 10000, 10000);
int64 target_area = 200 * 200;
gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
- in, target_area, bounds);
+ 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());
@@ -301,7 +301,7 @@ TEST(PictureLayerTilingTest, ExpandRectBoundedSmaller) {
gfx::Rect bounds(50, 60, 40, 30);
int64 target_area = 200 * 200;
gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
- in, target_area, bounds);
+ in, target_area, bounds, NULL);
EXPECT_EQ(bounds.ToString(), out.ToString());
}
@@ -310,7 +310,7 @@ TEST(PictureLayerTilingTest, ExpandRectBoundedEqual) {
gfx::Rect bounds = in;
int64 target_area = 200 * 200;
gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
- in, target_area, bounds);
+ in, target_area, bounds, NULL);
EXPECT_EQ(bounds.ToString(), out.ToString());
}
@@ -319,7 +319,7 @@ TEST(PictureLayerTilingTest, ExpandRectBoundedSmallerStretchVertical) {
gfx::Rect bounds(45, 0, 90, 300);
int64 target_area = 200 * 200;
gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
- in, target_area, bounds);
+ in, target_area, bounds, NULL);
EXPECT_EQ(bounds.ToString(), out.ToString());
}
@@ -328,7 +328,7 @@ TEST(PictureLayerTilingTest, ExpandRectBoundedEqualStretchVertical) {
gfx::Rect bounds(40, 0, 100, 300);
int64 target_area = 200 * 200;
gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
- in, target_area, bounds);
+ in, target_area, bounds, NULL);
EXPECT_EQ(bounds.ToString(), out.ToString());
}
@@ -337,7 +337,7 @@ TEST(PictureLayerTilingTest, ExpandRectBoundedSmallerStretchHorizontal) {
gfx::Rect bounds(0, 55, 180, 190);
int64 target_area = 200 * 200;
gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
- in, target_area, bounds);
+ in, target_area, bounds, NULL);
EXPECT_EQ(bounds.ToString(), out.ToString());
}
@@ -346,7 +346,7 @@ TEST(PictureLayerTilingTest, ExpandRectBoundedEqualStretchHorizontal) {
gfx::Rect bounds(0, 50, 180, 200);
int64 target_area = 200 * 200;
gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
- in, target_area, bounds);
+ in, target_area, bounds, NULL);
EXPECT_EQ(bounds.ToString(), out.ToString());
}
@@ -355,7 +355,7 @@ TEST(PictureLayerTilingTest, ExpandRectBoundedLeft) {
gfx::Rect bounds(20, -1000, 10000, 10000);
int64 target_area = 200 * 200;
gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
- in, target_area, bounds);
+ 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);
@@ -369,7 +369,7 @@ TEST(PictureLayerTilingTest, ExpandRectBoundedRight) {
gfx::Rect bounds(-1000, -1000, 1000+120, 10000);
int64 target_area = 200 * 200;
gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
- in, target_area, bounds);
+ 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);
@@ -383,7 +383,7 @@ TEST(PictureLayerTilingTest, ExpandRectBoundedTop) {
gfx::Rect bounds(-1000, 30, 10000, 10000);
int64 target_area = 200 * 200;
gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
- in, target_area, bounds);
+ 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);
@@ -397,7 +397,7 @@ TEST(PictureLayerTilingTest, ExpandRectBoundedBottom) {
gfx::Rect bounds(-1000, -1000, 10000, 1000 + 220);
int64 target_area = 200 * 200;
gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
- in, target_area, bounds);
+ 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);
@@ -411,7 +411,7 @@ TEST(PictureLayerTilingTest, ExpandRectSquishedHorizontally) {
gfx::Rect bounds(0, -4000, 100+40+20, 100000);
int64 target_area = 400 * 400;
gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
- in, target_area, bounds);
+ 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());
@@ -426,7 +426,7 @@ TEST(PictureLayerTilingTest, ExpandRectSquishedVertically) {
gfx::Rect bounds(-4000, 0, 100000, 200+50+30);
int64 target_area = 400 * 400;
gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
- in, target_area, bounds);
+ 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());
@@ -441,7 +441,7 @@ TEST(PictureLayerTilingTest, ExpandRectOutOfBoundsFarAway) {
gfx::Rect bounds(0, 0, 10, 10);
int64 target_area = 400 * 400;
gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
- in, target_area, bounds);
+ in, target_area, bounds, NULL);
EXPECT_TRUE(out.IsEmpty());
}
@@ -450,7 +450,7 @@ TEST(PictureLayerTilingTest, ExpandRectOutOfBoundsExpandedFullyCover) {
gfx::Rect bounds(0, 0, 10, 10);
int64 target_area = 400 * 400;
gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
- in, target_area, bounds);
+ in, target_area, bounds, NULL);
EXPECT_EQ(bounds.ToString(), out.ToString());
}
@@ -459,7 +459,7 @@ TEST(PictureLayerTilingTest, ExpandRectOutOfBoundsExpandedPartlyCover) {
gfx::Rect bounds(0, 0, 500, 500);
int64 target_area = 400 * 400;
gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
- in, target_area, bounds);
+ 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);
@@ -475,7 +475,7 @@ TEST(PictureLayerTilingTest, EmptyStartingRect) {
gfx::Rect bounds(0, 0, 10, 10);
int64 target_area = 400 * 400;
gfx::Rect out = PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy(
- in, target_area, bounds);
+ in, target_area, bounds, NULL);
EXPECT_TRUE(out.IsEmpty());
}
diff --git a/chromium/cc/resources/picture_pile.cc b/chromium/cc/resources/picture_pile.cc
index 17283ddd263..68d75d7aea1 100644
--- a/chromium/cc/resources/picture_pile.cc
+++ b/chromium/cc/resources/picture_pile.cc
@@ -5,23 +5,137 @@
#include "cc/resources/picture_pile.h"
#include <algorithm>
+#include <limits>
#include <vector>
#include "cc/base/region.h"
-#include "cc/debug/benchmark_instrumentation.h"
+#include "cc/debug/rendering_stats_instrumentation.h"
#include "cc/resources/picture_pile_impl.h"
+#include "cc/resources/tile_priority.h"
namespace {
-// Maximum number of pictures that can overlap before we collapse them into
-// a larger one.
-const size_t kMaxOverlapping = 2;
-// Maximum percentage area of the base picture another picture in the picture
-// list can be. If higher, we destroy the list and recreate from scratch.
-const float kResetThreshold = 0.7f;
// 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;
+
+// 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 do_clustering(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);
+ }
+
+float 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 1;
+ }
+
+ // 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);
+
+ float vertical_density;
+ std::vector<gfx::Rect> vertical_clustering;
+ vertical_density = do_clustering(invalid_tiles_vertical,
+ &vertical_clustering);
+
+ // Now try again with a horizontal sort, see which one is best
+ // TODO(humper): Heuristics for skipping this step?
+ std::vector<gfx::Rect> invalid_tiles_horizontal = invalid_tiles;
+ std::sort(invalid_tiles_vertical.begin(),
+ invalid_tiles_vertical.end(),
+ rect_sort_x);
+
+ float horizontal_density;
+ std::vector<gfx::Rect> horizontal_clustering;
+ horizontal_density = do_clustering(invalid_tiles_vertical,
+ &horizontal_clustering);
+
+ if (vertical_density < horizontal_density) {
+ *record_rects = horizontal_clustering;
+ return horizontal_density;
+ }
+
+ *record_rects = vertical_clustering;
+ return vertical_density;
+}
+
} // namespace
namespace cc {
@@ -38,6 +152,7 @@ bool PicturePile::Update(
bool contents_opaque,
const Region& invalidation,
gfx::Rect visible_layer_rect,
+ int frame_number,
RenderingStatsInstrumentation* stats_instrumentation) {
background_color_ = background_color;
contents_opaque_ = contents_opaque;
@@ -48,130 +163,93 @@ bool PicturePile::Update(
-kPixelDistanceToRecord,
-kPixelDistanceToRecord,
-kPixelDistanceToRecord);
- bool modified_pile = false;
+
+ bool invalidated = false;
for (Region::Iterator i(invalidation); i.has_rect(); i.next()) {
gfx::Rect invalidation = i.rect();
// Split this inflated invalidation across tile boundaries and apply it
// to all tiles that it touches.
for (TilingData::Iterator iter(&tiling_, invalidation);
iter; ++iter) {
- gfx::Rect tile =
- tiling_.TileBoundsWithBorder(iter.index_x(), iter.index_y());
- if (!tile.Intersects(interest_rect)) {
- // This invalidation touches a tile outside the interest rect, so
- // just remove the entire picture list.
- picture_list_map_.erase(iter.index());
- modified_pile = true;
- continue;
- }
+ const PictureMapKey& key = iter.index();
- gfx::Rect tile_invalidation = gfx::IntersectRects(invalidation, tile);
- if (tile_invalidation.IsEmpty())
- continue;
- PictureListMap::iterator find = picture_list_map_.find(iter.index());
- if (find == picture_list_map_.end())
+ PictureMap::iterator picture_it = picture_map_.find(key);
+ if (picture_it == picture_map_.end())
continue;
- PictureList& pic_list = find->second;
- // Leave empty pic_lists empty in case there are multiple invalidations.
- if (!pic_list.empty()) {
- // Inflate all recordings from invalidations with a margin so that when
- // scaled down to at least min_contents_scale, any final pixel touched
- // by an invalidation can be fully rasterized by this picture.
- tile_invalidation.Inset(-buffer_pixels(), -buffer_pixels());
-
- DCHECK_GE(tile_invalidation.width(), buffer_pixels() * 2 + 1);
- DCHECK_GE(tile_invalidation.height(), buffer_pixels() * 2 + 1);
-
- InvalidateRect(pic_list, tile_invalidation);
- modified_pile = true;
- }
+
+ // Inform the grid cell that it has been invalidated in this frame.
+ invalidated = picture_it->second.Invalidate(frame_number) || invalidated;
}
}
- int repeat_count = std::max(1, slow_down_raster_scale_factor_for_debug_);
-
- // Walk through all pictures in the rect of interest and record.
- for (TilingData::Iterator iter(&tiling_, interest_rect); iter; ++iter) {
- // Create a picture in this list if it doesn't exist.
- PictureList& pic_list = picture_list_map_[iter.index()];
- if (pic_list.empty()) {
- // Inflate the base picture with a margin, similar to invalidations, so
- // that when scaled down to at least min_contents_scale, the enclosed
- // rect still includes content all the way to the edge of the layer.
- gfx::Rect tile = tiling_.TileBounds(iter.index_x(), iter.index_y());
- tile.Inset(
- -buffer_pixels(),
- -buffer_pixels(),
- -buffer_pixels(),
- -buffer_pixels());
- scoped_refptr<Picture> base_picture = Picture::Create(tile);
- pic_list.push_back(base_picture);
- }
+ // Make a list of all invalid tiles; we will attempt to
+ // cluster these into multiple invalidation regions.
+ std::vector<gfx::Rect> invalid_tiles;
- for (PictureList::iterator pic = pic_list.begin();
- pic != pic_list.end(); ++pic) {
- if (!(*pic)->HasRecording()) {
- modified_pile = true;
- TRACE_EVENT0(benchmark_instrumentation::kCategory,
- benchmark_instrumentation::kRecordLoop);
- for (int i = 0; i < repeat_count; i++)
- (*pic)->Record(painter, tile_grid_info_, stats_instrumentation);
- (*pic)->GatherPixelRefs(tile_grid_info_, stats_instrumentation);
- (*pic)->CloneForDrawing(num_raster_threads_);
- }
+ for (TilingData::Iterator it(&tiling_, interest_rect);
+ it; ++it) {
+ const PictureMapKey& key = it.index();
+ PictureInfo& info = picture_map_[key];
+
+ gfx::Rect rect = PaddedRect(key);
+ int distance_to_visible =
+ rect.ManhattanInternalDistance(visible_layer_rect);
+
+ if (info.NeedsRecording(frame_number, distance_to_visible)) {
+ gfx::Rect tile = tiling_.TileBounds(key.first, key.second);
+ invalid_tiles.push_back(tile);
}
}
- UpdateRecordedRegion();
+ std::vector<gfx::Rect> record_rects;
+ ClusterTiles(invalid_tiles, &record_rects);
- return modified_pile;
-}
-
-class FullyContainedPredicate {
- public:
- explicit FullyContainedPredicate(gfx::Rect rect) : layer_rect_(rect) {}
- bool operator()(const scoped_refptr<Picture>& picture) {
- return picture->LayerRect().IsEmpty() ||
- layer_rect_.Contains(picture->LayerRect());
- }
- gfx::Rect layer_rect_;
-};
-
-void PicturePile::InvalidateRect(
- PictureList& picture_list,
- gfx::Rect invalidation) {
- DCHECK(!picture_list.empty());
- DCHECK(!invalidation.IsEmpty());
-
- std::vector<PictureList::iterator> overlaps;
- for (PictureList::iterator i = picture_list.begin();
- i != picture_list.end(); ++i) {
- if ((*i)->LayerRect().Contains(invalidation) && !(*i)->HasRecording())
- return;
- if ((*i)->LayerRect().Intersects(invalidation) && i != picture_list.begin())
- overlaps.push_back(i);
+ if (record_rects.empty()) {
+ if (invalidated)
+ UpdateRecordedRegion();
+ return invalidated;
}
- gfx::Rect picture_rect = invalidation;
- if (overlaps.size() >= kMaxOverlapping) {
- for (size_t j = 0; j < overlaps.size(); j++)
- picture_rect.Union((*overlaps[j])->LayerRect());
- }
+ for (std::vector<gfx::Rect>::iterator it = record_rects.begin();
+ it != record_rects.end();
+ it++) {
+ gfx::Rect record_rect = *it;
+ record_rect = PadRect(record_rect);
+
+ int repeat_count = std::max(1, slow_down_raster_scale_factor_for_debug_);
+ scoped_refptr<Picture> picture = Picture::Create(record_rect);
+
+ {
+ base::TimeDelta best_duration = base::TimeDelta::FromInternalValue(
+ std::numeric_limits<int64>::max());
+ for (int i = 0; i < repeat_count; i++) {
+ base::TimeTicks start_time = stats_instrumentation->StartRecording();
+ picture->Record(painter, tile_grid_info_);
+ base::TimeDelta duration =
+ stats_instrumentation->EndRecording(start_time);
+ best_duration = std::min(duration, best_duration);
+ }
+ int recorded_pixel_count =
+ picture->LayerRect().width() * picture->LayerRect().height();
+ stats_instrumentation->AddRecord(best_duration, recorded_pixel_count);
+ if (num_raster_threads_ > 1)
+ picture->GatherPixelRefs(tile_grid_info_);
+ picture->CloneForDrawing(num_raster_threads_);
+ }
- Picture* base_picture = picture_list.front().get();
- int max_pixels = kResetThreshold * base_picture->LayerRect().size().GetArea();
- if (picture_rect.size().GetArea() > max_pixels) {
- // This picture list will be entirely recreated, so clear it.
- picture_list.clear();
- return;
+ for (TilingData::Iterator it(&tiling_, record_rect);
+ it; ++it) {
+ const PictureMapKey& key = it.index();
+ gfx::Rect tile = PaddedRect(key);
+ if (record_rect.Contains(tile)) {
+ PictureInfo& info = picture_map_[key];
+ info.SetPicture(picture);
+ }
+ }
}
- FullyContainedPredicate pred(picture_rect);
- picture_list.erase(std::remove_if(picture_list.begin(),
- picture_list.end(),
- pred),
- picture_list.end());
- picture_list.push_back(Picture::Create(picture_rect));
+ UpdateRecordedRegion();
+ return true;
}
} // namespace cc
diff --git a/chromium/cc/resources/picture_pile.h b/chromium/cc/resources/picture_pile.h
index 7830a9e62c4..7860e7f831f 100644
--- a/chromium/cc/resources/picture_pile.h
+++ b/chromium/cc/resources/picture_pile.h
@@ -26,6 +26,7 @@ class CC_EXPORT PicturePile : public PicturePileBase {
bool contents_opaque,
const Region& invalidation,
gfx::Rect visible_layer_rect,
+ int frame_number,
RenderingStatsInstrumentation* stats_instrumentation);
void set_num_raster_threads(int num_raster_threads) {
@@ -46,12 +47,6 @@ class CC_EXPORT PicturePile : public PicturePileBase {
private:
friend class PicturePileImpl;
- // Add an invalidation to this picture list. If the list needs to be
- // entirely recreated, leave it empty. Do not call this on an empty list.
- void InvalidateRect(
- PictureList& picture_list,
- gfx::Rect invalidation);
-
DISALLOW_COPY_AND_ASSIGN(PicturePile);
};
diff --git a/chromium/cc/resources/picture_pile_base.cc b/chromium/cc/resources/picture_pile_base.cc
index 0352d30816c..7d60dcafc6b 100644
--- a/chromium/cc/resources/picture_pile_base.cc
+++ b/chromium/cc/resources/picture_pile_base.cc
@@ -5,6 +5,7 @@
#include "cc/resources/picture_pile_base.h"
#include <algorithm>
+#include <set>
#include <vector>
#include "base/logging.h"
@@ -17,18 +18,33 @@
namespace {
// Dimensions of the tiles in this picture pile as well as the dimensions of
// the base picture in each tile.
-const int kBasePictureSize = 3000;
+const int kBasePictureSize = 512;
const int kTileGridBorderPixels = 1;
-}
+#ifdef NDEBUG
+const bool kDefaultClearCanvasSetting = false;
+#else
+const bool kDefaultClearCanvasSetting = true;
+#endif
+
+// Invalidation frequency settings. kInvalidationFrequencyThreshold is a value
+// between 0 and 1 meaning invalidation frequency between 0% and 100% that
+// indicates when to stop invalidating offscreen regions.
+// kFrequentInvalidationDistanceThreshold defines what it means to be
+// "offscreen" in terms of distance to visible in css pixels.
+const float kInvalidationFrequencyThreshold = 0.75f;
+const int kFrequentInvalidationDistanceThreshold = 512;
+
+} // namespace
namespace cc {
PicturePileBase::PicturePileBase()
: min_contents_scale_(0),
background_color_(SkColorSetARGBInline(0, 0, 0, 0)),
- contents_opaque_(false),
slow_down_raster_scale_factor_for_debug_(0),
+ contents_opaque_(false),
show_debug_picture_borders_(false),
+ clear_canvas_with_debug_color_(kDefaultClearCanvasSetting),
num_raster_threads_(0) {
tiling_.SetMaxTextureSize(gfx::Size(kBasePictureSize, kBasePictureSize));
tile_grid_info_.fTileInterval.setEmpty();
@@ -37,16 +53,17 @@ PicturePileBase::PicturePileBase()
}
PicturePileBase::PicturePileBase(const PicturePileBase* other)
- : picture_list_map_(other->picture_list_map_),
+ : picture_map_(other->picture_map_),
tiling_(other->tiling_),
recorded_region_(other->recorded_region_),
min_contents_scale_(other->min_contents_scale_),
tile_grid_info_(other->tile_grid_info_),
background_color_(other->background_color_),
- contents_opaque_(other->contents_opaque_),
slow_down_raster_scale_factor_for_debug_(
other->slow_down_raster_scale_factor_for_debug_),
+ contents_opaque_(other->contents_opaque_),
show_debug_picture_borders_(other->show_debug_picture_borders_),
+ clear_canvas_with_debug_color_(other->clear_canvas_with_debug_color_),
num_raster_threads_(other->num_raster_threads_) {
}
@@ -57,21 +74,16 @@ PicturePileBase::PicturePileBase(
min_contents_scale_(other->min_contents_scale_),
tile_grid_info_(other->tile_grid_info_),
background_color_(other->background_color_),
- contents_opaque_(other->contents_opaque_),
slow_down_raster_scale_factor_for_debug_(
other->slow_down_raster_scale_factor_for_debug_),
+ contents_opaque_(other->contents_opaque_),
show_debug_picture_borders_(other->show_debug_picture_borders_),
+ clear_canvas_with_debug_color_(other->clear_canvas_with_debug_color_),
num_raster_threads_(other->num_raster_threads_) {
- const PictureListMap& other_pic_list_map = other->picture_list_map_;
- for (PictureListMap::const_iterator map_iter = other_pic_list_map.begin();
- map_iter != other_pic_list_map.end(); ++map_iter) {
- PictureList& pic_list = picture_list_map_[map_iter->first];
- const PictureList& other_pic_list = map_iter->second;
- for (PictureList::const_iterator pic_iter = other_pic_list.begin();
- pic_iter != other_pic_list.end(); ++pic_iter) {
- pic_list.push_back(
- (*pic_iter)->GetCloneForDrawingOnThread(thread_index));
- }
+ for (PictureMap::const_iterator it = other->picture_map_.begin();
+ it != other->picture_map_.end();
+ ++it) {
+ picture_map_[it->first] = it->second.CloneForThread(thread_index);
}
}
@@ -86,20 +98,22 @@ void PicturePileBase::Resize(gfx::Size new_size) {
tiling_.SetTotalSize(new_size);
// Find all tiles that contain any pixels outside the new size.
- std::vector<PictureListMapKey> to_erase;
+ std::vector<PictureMapKey> to_erase;
int min_toss_x = tiling_.FirstBorderTileXIndexFromSrcCoord(
std::min(old_size.width(), new_size.width()));
int min_toss_y = tiling_.FirstBorderTileYIndexFromSrcCoord(
std::min(old_size.height(), new_size.height()));
- for (PictureListMap::iterator iter = picture_list_map_.begin();
- iter != picture_list_map_.end(); ++iter) {
- if (iter->first.first < min_toss_x && iter->first.second < min_toss_y)
+ for (PictureMap::const_iterator it = picture_map_.begin();
+ it != picture_map_.end();
+ ++it) {
+ const PictureMapKey& key = it->first;
+ if (key.first < min_toss_x && key.second < min_toss_y)
continue;
- to_erase.push_back(iter->first);
+ to_erase.push_back(key);
}
for (size_t i = 0; i < to_erase.size(); ++i)
- picture_list_map_.erase(to_erase[i]);
+ picture_map_.erase(to_erase[i]);
}
void PicturePileBase::SetMinContentsScale(float min_contents_scale) {
@@ -123,19 +137,24 @@ void PicturePileBase::SetMinContentsScale(float min_contents_scale) {
min_contents_scale_ = min_contents_scale;
}
-void PicturePileBase::SetTileGridSize(gfx::Size tile_grid_size) {
- tile_grid_info_.fTileInterval.set(
- tile_grid_size.width() - 2 * kTileGridBorderPixels,
- tile_grid_size.height() - 2 * kTileGridBorderPixels);
- DCHECK_GT(tile_grid_info_.fTileInterval.width(), 0);
- DCHECK_GT(tile_grid_info_.fTileInterval.height(), 0);
- tile_grid_info_.fMargin.set(kTileGridBorderPixels,
- kTileGridBorderPixels);
+// static
+void PicturePileBase::ComputeTileGridInfo(
+ gfx::Size tile_grid_size,
+ SkTileGridPicture::TileGridInfo* info) {
+ DCHECK(info);
+ info->fTileInterval.set(tile_grid_size.width() - 2 * kTileGridBorderPixels,
+ tile_grid_size.height() - 2 * kTileGridBorderPixels);
+ DCHECK_GT(info->fTileInterval.width(), 0);
+ DCHECK_GT(info->fTileInterval.height(), 0);
+ info->fMargin.set(kTileGridBorderPixels, kTileGridBorderPixels);
// Offset the tile grid coordinate space to take into account the fact
// that the top-most and left-most tiles do not have top and left borders
// respectively.
- tile_grid_info_.fOffset.set(-kTileGridBorderPixels,
- -kTileGridBorderPixels);
+ info->fOffset.set(-kTileGridBorderPixels, -kTileGridBorderPixels);
+}
+
+void PicturePileBase::SetTileGridSize(gfx::Size tile_grid_size) {
+ ComputeTileGridInfo(tile_grid_size, &tile_grid_info_);
}
void PicturePileBase::SetBufferPixels(int new_buffer_pixels) {
@@ -147,25 +166,26 @@ void PicturePileBase::SetBufferPixels(int new_buffer_pixels) {
}
void PicturePileBase::Clear() {
- picture_list_map_.clear();
+ picture_map_.clear();
}
void PicturePileBase::UpdateRecordedRegion() {
recorded_region_.Clear();
- for (PictureListMap::iterator it = picture_list_map_.begin();
- it != picture_list_map_.end(); ++it) {
- const PictureListMapKey& key = it->first;
- recorded_region_.Union(tile_bounds(key.first, key.second));
+ for (PictureMap::const_iterator it = picture_map_.begin();
+ it != picture_map_.end();
+ ++it) {
+ if (it->second.GetPicture()) {
+ const PictureMapKey& key = it->first;
+ recorded_region_.Union(tile_bounds(key.first, key.second));
+ }
}
}
bool PicturePileBase::HasRecordingAt(int x, int y) {
- PictureListMap::iterator found =
- picture_list_map_.find(PictureListMapKey(x, y));
- if (found == picture_list_map_.end())
+ PictureMap::const_iterator found = picture_map_.find(PictureMapKey(x, y));
+ if (found == picture_map_.end())
return false;
- DCHECK(!found->second.empty());
- return true;
+ return !!found->second.GetPicture();
}
bool PicturePileBase::CanRaster(float contents_scale, gfx::Rect content_rect) {
@@ -177,25 +197,92 @@ bool PicturePileBase::CanRaster(float contents_scale, gfx::Rect content_rect) {
return recorded_region_.Contains(layer_rect);
}
+gfx::Rect PicturePileBase::PaddedRect(const PictureMapKey& key) {
+ gfx::Rect tile = tiling_.TileBounds(key.first, key.second);
+ return PadRect(tile);
+}
+
+gfx::Rect PicturePileBase::PadRect(gfx::Rect rect) {
+ gfx::Rect padded_rect = rect;
+ padded_rect.Inset(
+ -buffer_pixels(), -buffer_pixels(), -buffer_pixels(), -buffer_pixels());
+ return padded_rect;
+}
+
scoped_ptr<base::Value> PicturePileBase::AsValue() const {
scoped_ptr<base::ListValue> pictures(new base::ListValue());
gfx::Rect layer_rect(tiling_.total_size());
+ std::set<void*> appended_pictures;
for (TilingData::Iterator tile_iter(&tiling_, layer_rect);
tile_iter; ++tile_iter) {
- PictureListMap::const_iterator map_iter =
- picture_list_map_.find(tile_iter.index());
- if (map_iter == picture_list_map_.end())
+ PictureMap::const_iterator map_iter = picture_map_.find(tile_iter.index());
+ if (map_iter == picture_map_.end())
continue;
- const PictureList& pic_list= map_iter->second;
- if (pic_list.empty())
- continue;
- for (PictureList::const_reverse_iterator i = pic_list.rbegin();
- i != pic_list.rend(); ++i) {
- Picture* picture = (*i).get();
+
+ Picture* picture = map_iter->second.GetPicture();
+ if (picture && (appended_pictures.count(picture) == 0)) {
+ appended_pictures.insert(picture);
pictures->Append(TracedValue::CreateIDRef(picture).release());
}
}
return pictures.PassAs<base::Value>();
}
+PicturePileBase::PictureInfo::PictureInfo() : last_frame_number_(0) {}
+
+PicturePileBase::PictureInfo::~PictureInfo() {}
+
+void PicturePileBase::PictureInfo::AdvanceInvalidationHistory(
+ int frame_number) {
+ DCHECK_GE(frame_number, last_frame_number_);
+ if (frame_number == last_frame_number_)
+ return;
+
+ invalidation_history_ <<= (frame_number - last_frame_number_);
+ last_frame_number_ = frame_number;
+}
+
+bool PicturePileBase::PictureInfo::Invalidate(int frame_number) {
+ AdvanceInvalidationHistory(frame_number);
+ invalidation_history_.set(0);
+
+ bool did_invalidate = !!picture_;
+ picture_ = NULL;
+ return did_invalidate;
+}
+
+bool PicturePileBase::PictureInfo::NeedsRecording(int frame_number,
+ int distance_to_visible) {
+ AdvanceInvalidationHistory(frame_number);
+
+ // We only need recording if we don't have a picture. Furthermore, we only
+ // need a recording if we're within frequent invalidation distance threshold
+ // or the invalidation is not frequent enough (below invalidation frequency
+ // threshold).
+ return !picture_ &&
+ ((distance_to_visible <= kFrequentInvalidationDistanceThreshold) ||
+ (GetInvalidationFrequency() < kInvalidationFrequencyThreshold));
+}
+
+void PicturePileBase::PictureInfo::SetPicture(scoped_refptr<Picture> picture) {
+ picture_ = picture;
+}
+
+Picture* PicturePileBase::PictureInfo::GetPicture() const {
+ return picture_.get();
+}
+
+PicturePileBase::PictureInfo PicturePileBase::PictureInfo::CloneForThread(
+ int thread_index) const {
+ PictureInfo info = *this;
+ if (picture_.get())
+ info.picture_ = picture_->GetCloneForDrawingOnThread(thread_index);
+ return info;
+}
+
+float PicturePileBase::PictureInfo::GetInvalidationFrequency() const {
+ return invalidation_history_.count() /
+ static_cast<float>(INVALIDATION_FRAMES_TRACKED);
+}
+
} // namespace cc
diff --git a/chromium/cc/resources/picture_pile_base.h b/chromium/cc/resources/picture_pile_base.h
index fdb593fa81a..274c865ad3f 100644
--- a/chromium/cc/resources/picture_pile_base.h
+++ b/chromium/cc/resources/picture_pile_base.h
@@ -5,6 +5,7 @@
#ifndef CC_RESOURCES_PICTURE_PILE_BASE_H_
#define CC_RESOURCES_PICTURE_PILE_BASE_H_
+#include <bitset>
#include <list>
#include <utility>
@@ -41,33 +42,71 @@ class CC_EXPORT PicturePileBase : public base::RefCounted<PicturePileBase> {
bool HasRecordingAt(int x, int y);
bool CanRaster(float contents_scale, gfx::Rect content_rect);
+ static void ComputeTileGridInfo(gfx::Size tile_grid_size,
+ SkTileGridPicture::TileGridInfo* info);
+
void SetTileGridSize(gfx::Size tile_grid_size);
TilingData& tiling() { return tiling_; }
scoped_ptr<base::Value> AsValue() const;
protected:
+ class CC_EXPORT PictureInfo {
+ public:
+ enum {
+ INVALIDATION_FRAMES_TRACKED = 32
+ };
+
+ PictureInfo();
+ ~PictureInfo();
+
+ bool Invalidate(int frame_number);
+ bool NeedsRecording(int frame_number, int distance_to_visible);
+ PictureInfo CloneForThread(int thread_index) const;
+ void SetPicture(scoped_refptr<Picture> picture);
+ Picture* GetPicture() const;
+
+ float GetInvalidationFrequencyForTesting() const {
+ return GetInvalidationFrequency();
+ }
+
+ private:
+ void AdvanceInvalidationHistory(int frame_number);
+ float GetInvalidationFrequency() const;
+
+ int last_frame_number_;
+ scoped_refptr<Picture> picture_;
+ std::bitset<INVALIDATION_FRAMES_TRACKED> invalidation_history_;
+ };
+
+ typedef std::pair<int, int> PictureMapKey;
+ typedef base::hash_map<PictureMapKey, PictureInfo> PictureMap;
+
virtual ~PicturePileBase();
+ void SetRecordedRegionForTesting(const Region& recorded_region) {
+ recorded_region_ = recorded_region;
+ }
+
int num_raster_threads() { return num_raster_threads_; }
int buffer_pixels() const { return tiling_.border_texels(); }
void Clear();
- typedef std::pair<int, int> PictureListMapKey;
- typedef std::list<scoped_refptr<Picture> > PictureList;
- typedef base::hash_map<PictureListMapKey, PictureList> PictureListMap;
+ gfx::Rect PaddedRect(const PictureMapKey& key);
+ gfx::Rect PadRect(gfx::Rect rect);
- // A picture pile is a tiled set of picture lists. The picture list map
- // is a map of tile indices to picture lists.
- PictureListMap picture_list_map_;
+ // 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_;
Region recorded_region_;
float min_contents_scale_;
SkTileGridPicture::TileGridInfo tile_grid_info_;
SkColor background_color_;
- bool contents_opaque_;
int slow_down_raster_scale_factor_for_debug_;
+ bool contents_opaque_;
bool show_debug_picture_borders_;
+ bool clear_canvas_with_debug_color_;
int num_raster_threads_;
private:
diff --git a/chromium/cc/resources/picture_pile_impl.cc b/chromium/cc/resources/picture_pile_impl.cc
index 3a4020e072b..b6f4d77156f 100644
--- a/chromium/cc/resources/picture_pile_impl.cc
+++ b/chromium/cc/resources/picture_pile_impl.cc
@@ -7,7 +7,6 @@
#include "base/debug/trace_event.h"
#include "cc/base/region.h"
-#include "cc/debug/benchmark_instrumentation.h"
#include "cc/debug/debug_colors.h"
#include "cc/resources/picture_pile_impl.h"
#include "skia/ext/analysis_canvas.h"
@@ -73,26 +72,33 @@ void PicturePileImpl::RasterDirect(
SkCanvas* canvas,
gfx::Rect canvas_rect,
float contents_scale,
- RasterStats* raster_stats) {
- RasterCommon(canvas, NULL, canvas_rect, contents_scale, raster_stats);
+ RenderingStatsInstrumentation* rendering_stats_instrumentation) {
+ RasterCommon(canvas,
+ NULL,
+ canvas_rect,
+ contents_scale,
+ rendering_stats_instrumentation,
+ false);
}
void PicturePileImpl::RasterForAnalysis(
skia::AnalysisCanvas* canvas,
gfx::Rect canvas_rect,
- float contents_scale) {
- RasterCommon(canvas, canvas, canvas_rect, contents_scale, NULL);
+ float contents_scale,
+ RenderingStatsInstrumentation* stats_instrumentation) {
+ RasterCommon(
+ canvas, canvas, canvas_rect, contents_scale, stats_instrumentation, true);
}
void PicturePileImpl::RasterToBitmap(
SkCanvas* canvas,
gfx::Rect canvas_rect,
float contents_scale,
- RasterStats* raster_stats) {
-#ifndef NDEBUG
- // Any non-painted areas will be left in this color.
- canvas->clear(DebugColors::NonPaintedFillColor());
-#endif // NDEBUG
+ RenderingStatsInstrumentation* rendering_stats_instrumentation) {
+ if (clear_canvas_with_debug_color_) {
+ // Any non-painted areas will be left in this color.
+ canvas->clear(DebugColors::NonPaintedFillColor());
+ }
// If this picture has opaque contents, it is guaranteeing that it will
// draw an opaque rect the size of the layer. If it is not, then we must
@@ -109,18 +115,17 @@ void PicturePileImpl::RasterToBitmap(
gfx::SizeF total_content_size = gfx::ScaleSize(tiling_.total_size(),
contents_scale);
gfx::Rect content_rect(gfx::ToCeiledSize(total_content_size));
- gfx::Rect deflated_content_rect = content_rect;
- content_rect.Intersect(canvas_rect);
// The final texel of content may only be partially covered by a
// rasterization; this rect represents the content rect that is fully
// covered by content.
+ gfx::Rect deflated_content_rect = content_rect;
deflated_content_rect.Inset(0, 0, 1, 1);
- deflated_content_rect.Intersect(canvas_rect);
if (!deflated_content_rect.Contains(canvas_rect)) {
// Drawing at most 2 x 2 x (canvas width + canvas height) texels is 2-3X
// faster than clearing, so special case this.
canvas->save();
+ canvas->translate(-canvas_rect.x(), -canvas_rect.y());
gfx::Rect inflated_content_rect = content_rect;
inflated_content_rect.Inset(0, 0, -1, -1);
canvas->clipRect(gfx::RectToSkRect(inflated_content_rect),
@@ -132,7 +137,71 @@ void PicturePileImpl::RasterToBitmap(
}
}
- RasterCommon(canvas, NULL, canvas_rect, contents_scale, raster_stats);
+ RasterCommon(canvas,
+ NULL,
+ canvas_rect,
+ contents_scale,
+ rendering_stats_instrumentation,
+ false);
+}
+
+void PicturePileImpl::CoalesceRasters(gfx::Rect canvas_rect,
+ gfx::Rect content_rect,
+ float contents_scale,
+ PictureRegionMap* results) {
+ DCHECK(results);
+ // Rasterize the collection of relevant picture piles.
+ gfx::Rect layer_rect = gfx::ScaleToEnclosingRect(
+ content_rect, 1.f / contents_scale);
+
+ // 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.
+ for (TilingData::Iterator tile_iter(&tiling_, layer_rect);
+ tile_iter; ++tile_iter) {
+ PictureMap::iterator map_iter = picture_map_.find(tile_iter.index());
+ if (map_iter == picture_map_.end())
+ continue;
+ PictureInfo& info = map_iter->second;
+ Picture* picture = info.GetPicture();
+ if (!picture)
+ continue;
+
+ // 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);
+
+ PictureRegionMap::iterator it = results->find(picture);
+ if (it == results->end()) {
+ Region& region = (*results)[picture];
+ region = content_rect;
+ region.Subtract(content_clip);
+ continue;
+ }
+
+ Region& region = it->second;
+ region.Subtract(content_clip);
+ }
}
void PicturePileImpl::RasterCommon(
@@ -140,128 +209,84 @@ void PicturePileImpl::RasterCommon(
SkDrawPictureCallback* callback,
gfx::Rect canvas_rect,
float contents_scale,
- RasterStats* raster_stats) {
+ RenderingStatsInstrumentation* rendering_stats_instrumentation,
+ bool is_analysis) {
DCHECK(contents_scale >= min_contents_scale_);
canvas->translate(-canvas_rect.x(), -canvas_rect.y());
-
gfx::SizeF total_content_size = gfx::ScaleSize(tiling_.total_size(),
contents_scale);
gfx::Rect total_content_rect(gfx::ToCeiledSize(total_content_size));
gfx::Rect content_rect = total_content_rect;
content_rect.Intersect(canvas_rect);
- // Rasterize the collection of relevant picture piles.
- gfx::Rect layer_rect = gfx::ScaleToEnclosingRect(
- content_rect, 1.f / contents_scale);
-
canvas->clipRect(gfx::RectToSkRect(content_rect),
SkRegion::kIntersect_Op);
- Region unclipped(content_rect);
- if (raster_stats) {
- raster_stats->total_pixels_rasterized = 0;
- raster_stats->total_rasterize_time = base::TimeDelta::FromSeconds(0);
- raster_stats->best_rasterize_time = base::TimeDelta::FromSeconds(0);
- }
+ PictureRegionMap picture_region_map;
+ CoalesceRasters(
+ canvas_rect, content_rect, contents_scale, &picture_region_map);
- for (TilingData::Iterator tile_iter(&tiling_, layer_rect);
- tile_iter; ++tile_iter) {
- PictureListMap::iterator map_iter =
- picture_list_map_.find(tile_iter.index());
- if (map_iter == picture_list_map_.end())
- continue;
- PictureList& pic_list= map_iter->second;
- if (pic_list.empty())
- continue;
+#ifndef NDEBUG
+ Region total_clip;
+#endif // NDEBUG
- // Raster through the picture list top down, using clips to make sure that
- // pictures on top are not overdrawn by pictures on the bottom.
- for (PictureList::reverse_iterator i = pic_list.rbegin();
- i != pic_list.rend(); ++i) {
- // 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'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 content_clip = gfx::ScaleToEnclosedRect(
- (*i)->LayerRect(), contents_scale);
-
- DCHECK(!content_clip.IsEmpty()) <<
- "Layer rect: " << (*i)->LayerRect().ToString() <<
- "Contents scale: " << contents_scale;
-
- content_clip.Intersect(canvas_rect);
-
- if (!unclipped.Intersects(content_clip))
- continue;
-
- base::TimeDelta total_duration =
- base::TimeDelta::FromInternalValue(0);
- base::TimeDelta best_duration =
- base::TimeDelta::FromInternalValue(std::numeric_limits<int64>::max());
- int repeat_count = std::max(1, slow_down_raster_scale_factor_for_debug_);
-
- TRACE_EVENT0(benchmark_instrumentation::kCategory,
- benchmark_instrumentation::kRasterLoop);
- for (int j = 0; j < repeat_count; ++j) {
- base::TimeTicks start_time;
- if (raster_stats)
- start_time = base::TimeTicks::HighResNow();
-
- (*i)->Raster(canvas, callback, content_clip, contents_scale);
-
- if (raster_stats) {
- base::TimeDelta duration = base::TimeTicks::HighResNow() - start_time;
- total_duration += duration;
- best_duration = std::min(best_duration, duration);
- }
- }
+ // 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) {
+ Picture* picture = it->first;
+ Region negated_clip_region = it->second;
- if (raster_stats) {
- raster_stats->total_pixels_rasterized +=
- repeat_count * content_clip.width() * content_clip.height();
- raster_stats->total_rasterize_time += total_duration;
- raster_stats->best_rasterize_time += best_duration;
- }
+#ifndef NDEBUG
+ Region positive_clip = content_rect;
+ positive_clip.Subtract(negated_clip_region);
+ total_clip.Union(positive_clip);
+#endif // NDEBUG
+
+ base::TimeDelta best_duration =
+ base::TimeDelta::FromInternalValue(std::numeric_limits<int64>::max());
+ int repeat_count = std::max(1, slow_down_raster_scale_factor_for_debug_);
+ int rasterized_pixel_count = 0;
+
+ for (int j = 0; j < repeat_count; ++j) {
+ base::TimeTicks start_time;
+ if (rendering_stats_instrumentation)
+ start_time = rendering_stats_instrumentation->StartRecording();
- if (show_debug_picture_borders_) {
- gfx::Rect border = gfx::ScaleToEnclosedRect(
- (*i)->LayerRect(), contents_scale);
- border.Inset(0, 0, 1, 1);
-
- SkPaint picture_border_paint;
- picture_border_paint.setColor(DebugColors::PictureBorderColor());
- canvas->drawLine(border.x(), border.y(), border.right(), border.y(),
- picture_border_paint);
- canvas->drawLine(border.right(), border.y(), border.right(),
- border.bottom(), picture_border_paint);
- canvas->drawLine(border.right(), border.bottom(), border.x(),
- border.bottom(), picture_border_paint);
- canvas->drawLine(border.x(), border.bottom(), border.x(), border.y(),
- picture_border_paint);
+ rasterized_pixel_count = picture->Raster(
+ canvas, callback, negated_clip_region, contents_scale);
+
+ if (rendering_stats_instrumentation) {
+ base::TimeDelta duration =
+ rendering_stats_instrumentation->EndRecording(start_time);
+ best_duration = std::min(best_duration, duration);
}
+ }
- // Don't allow pictures underneath to draw where this picture did.
- canvas->clipRect(
- gfx::RectToSkRect(content_clip),
- SkRegion::kDifference_Op);
- unclipped.Subtract(content_clip);
+ if (rendering_stats_instrumentation) {
+ if (is_analysis) {
+ rendering_stats_instrumentation->AddAnalysis(best_duration,
+ rasterized_pixel_count);
+ } else {
+ rendering_stats_instrumentation->AddRaster(best_duration,
+ rasterized_pixel_count);
+ }
}
}
#ifndef NDEBUG
- // Fill the remaining clip with debug color. This allows us to
+ // 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
-
- // We should always paint some part of |content_rect|.
- DCHECK(!unclipped.Contains(content_rect));
}
skia::RefPtr<SkPicture> PicturePileImpl::GetFlattenedPicture() {
@@ -283,9 +308,18 @@ skia::RefPtr<SkPicture> PicturePileImpl::GetFlattenedPicture() {
return picture;
}
-void PicturePileImpl::AnalyzeInRect(gfx::Rect content_rect,
- float contents_scale,
- PicturePileImpl::Analysis* analysis) {
+void PicturePileImpl::AnalyzeInRect(
+ gfx::Rect content_rect,
+ float contents_scale,
+ PicturePileImpl::Analysis* analysis) {
+ AnalyzeInRect(content_rect, contents_scale, analysis, NULL);
+}
+
+void PicturePileImpl::AnalyzeInRect(
+ gfx::Rect content_rect,
+ float contents_scale,
+ PicturePileImpl::Analysis* analysis,
+ RenderingStatsInstrumentation* stats_instrumentation) {
DCHECK(analysis);
TRACE_EVENT0("cc", "PicturePileImpl::AnalyzeInRect");
@@ -301,7 +335,7 @@ void PicturePileImpl::AnalyzeInRect(gfx::Rect content_rect,
skia::AnalysisDevice device(empty_bitmap);
skia::AnalysisCanvas canvas(&device);
- RasterForAnalysis(&canvas, layer_rect, 1.0f);
+ RasterForAnalysis(&canvas, layer_rect, 1.0f, stats_instrumentation);
analysis->is_solid_color = canvas.GetColorIfSolid(&analysis->solid_color);
analysis->has_text = canvas.HasText();
@@ -322,14 +356,12 @@ PicturePileImpl::PixelRefIterator::PixelRefIterator(
: picture_pile_(picture_pile),
layer_rect_(gfx::ScaleToEnclosingRect(
content_rect, 1.f / contents_scale)),
- tile_iterator_(&picture_pile_->tiling_, layer_rect_),
- picture_list_(NULL) {
+ tile_iterator_(&picture_pile_->tiling_, layer_rect_) {
// Early out if there isn't a single tile.
if (!tile_iterator_)
return;
- if (AdvanceToTileWithPictures())
- AdvanceToPictureWithPixelRefs();
+ AdvanceToTilePictureWithPixelRefs();
}
PicturePileImpl::PixelRefIterator::~PixelRefIterator() {
@@ -341,50 +373,40 @@ PicturePileImpl::PixelRefIterator&
if (pixel_ref_iterator_)
return *this;
- ++picture_list_iterator_;
- AdvanceToPictureWithPixelRefs();
+ ++tile_iterator_;
+ AdvanceToTilePictureWithPixelRefs();
return *this;
}
-bool PicturePileImpl::PixelRefIterator::AdvanceToTileWithPictures() {
+void PicturePileImpl::PixelRefIterator::AdvanceToTilePictureWithPixelRefs() {
for (; tile_iterator_; ++tile_iterator_) {
- PictureListMap::const_iterator map_iterator =
- picture_pile_->picture_list_map_.find(tile_iterator_.index());
- if (map_iterator != picture_pile_->picture_list_map_.end()) {
- picture_list_ = &map_iterator->second;
- picture_list_iterator_ = picture_list_->begin();
- return true;
- }
- }
+ PictureMap::const_iterator it =
+ picture_pile_->picture_map_.find(tile_iterator_.index());
+ if (it == picture_pile_->picture_map_.end())
+ continue;
- return false;
-}
+ const Picture* picture = it->second.GetPicture();
+ if (!picture || (processed_pictures_.count(picture) != 0) ||
+ !picture->WillPlayBackBitmaps())
+ continue;
-void PicturePileImpl::PixelRefIterator::AdvanceToPictureWithPixelRefs() {
- DCHECK(tile_iterator_);
- do {
- for (;
- picture_list_iterator_ != picture_list_->end();
- ++picture_list_iterator_) {
- pixel_ref_iterator_ =
- Picture::PixelRefIterator(layer_rect_, picture_list_iterator_->get());
- if (pixel_ref_iterator_)
- return;
- }
- ++tile_iterator_;
- } while (AdvanceToTileWithPictures());
+ processed_pictures_.insert(picture);
+ pixel_ref_iterator_ = Picture::PixelRefIterator(layer_rect_, picture);
+ if (pixel_ref_iterator_)
+ break;
+ }
}
void PicturePileImpl::DidBeginTracing() {
gfx::Rect layer_rect(tiling_.total_size());
- for (PictureListMap::iterator pli = picture_list_map_.begin();
- pli != picture_list_map_.end();
- pli++) {
- PictureList& picture_list = (*pli).second;
- for (PictureList::iterator picture = picture_list.begin();
- picture != picture_list.end();
- picture++) {
- (*picture)->EmitTraceSnapshot();
+ std::set<void*> processed_pictures;
+ for (PictureMap::iterator it = picture_map_.begin();
+ it != picture_map_.end();
+ ++it) {
+ Picture* picture = it->second.GetPicture();
+ if (picture && (processed_pictures.count(picture) == 0)) {
+ picture->EmitTraceSnapshot();
+ processed_pictures.insert(picture);
}
}
}
diff --git a/chromium/cc/resources/picture_pile_impl.h b/chromium/cc/resources/picture_pile_impl.h
index c6c3ab3fbe4..180dba258ee 100644
--- a/chromium/cc/resources/picture_pile_impl.h
+++ b/chromium/cc/resources/picture_pile_impl.h
@@ -7,10 +7,12 @@
#include <list>
#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/resources/picture_pile_base.h"
#include "skia/ext/analysis_canvas.h"
#include "skia/ext/refptr.h"
@@ -27,16 +29,6 @@ class CC_EXPORT PicturePileImpl : public PicturePileBase {
// Get paint-safe version of this picture for a specific thread.
PicturePileImpl* GetCloneForDrawingOnThread(unsigned thread_index) const;
- struct CC_EXPORT RasterStats {
- // Minimum rasterize time from N runs
- // N=max(1,slow-down-raster-scale-factor)
- base::TimeDelta best_rasterize_time;
- // Total rasterize time for all N runs
- base::TimeDelta total_rasterize_time;
- // Total number of pixels rasterize in all N runs
- int64 total_pixels_rasterized;
- };
-
// Raster a subrect of this PicturePileImpl into the given canvas.
// It's only safe to call paint on a cloned version. It is assumed
// that contents_scale has already been applied to this canvas.
@@ -49,7 +41,7 @@ class CC_EXPORT PicturePileImpl : public PicturePileBase {
SkCanvas* canvas,
gfx::Rect canvas_rect,
float contents_scale,
- RasterStats* raster_stats);
+ RenderingStatsInstrumentation* rendering_stats_instrumentation);
// Similar to the above RasterDirect method, but this is a convenience method
// for when it is known that the raster is going to an intermediate bitmap
@@ -58,15 +50,15 @@ class CC_EXPORT PicturePileImpl : public PicturePileBase {
SkCanvas* canvas,
gfx::Rect canvas_rect,
float contents_scale,
- RasterStats* raster_stats);
+ RenderingStatsInstrumentation* stats_instrumentation);
// Called when analyzing a tile. We can use AnalysisCanvas as
// SkDrawPictureCallback, which allows us to early out from analysis.
void RasterForAnalysis(
skia::AnalysisCanvas* canvas,
gfx::Rect canvas_rect,
- float contents_scale);
-
+ float contents_scale,
+ RenderingStatsInstrumentation* stats_instrumentation);
skia::RefPtr<SkPicture> GetFlattenedPicture();
@@ -83,6 +75,11 @@ class CC_EXPORT PicturePileImpl : public PicturePileBase {
float contents_scale,
Analysis* analysis);
+ void AnalyzeInRect(gfx::Rect content_rect,
+ float contents_scale,
+ Analysis* analysis,
+ RenderingStatsInstrumentation* stats_instrumentation);
+
class CC_EXPORT PixelRefIterator {
public:
PixelRefIterator(gfx::Rect content_rect,
@@ -96,15 +93,13 @@ class CC_EXPORT PicturePileImpl : public PicturePileBase {
operator bool() const { return pixel_ref_iterator_; }
private:
- bool AdvanceToTileWithPictures();
- void AdvanceToPictureWithPixelRefs();
+ void AdvanceToTilePictureWithPixelRefs();
const PicturePileImpl* picture_pile_;
gfx::Rect layer_rect_;
TilingData::Iterator tile_iterator_;
Picture::PixelRefIterator pixel_ref_iterator_;
- const PictureList* picture_list_;
- PictureList::const_iterator picture_list_iterator_;
+ std::set<const void*> processed_pictures_;
};
void DidBeginTracing();
@@ -132,12 +127,20 @@ class CC_EXPORT PicturePileImpl : public PicturePileBase {
PicturePileImpl(const PicturePileImpl* other, unsigned thread_index);
+ private:
+ typedef std::map<Picture*, Region> PictureRegionMap;
+ void CoalesceRasters(gfx::Rect canvas_rect,
+ gfx::Rect content_rect,
+ float contents_scale,
+ PictureRegionMap* result);
+
void RasterCommon(
SkCanvas* canvas,
SkDrawPictureCallback* callback,
gfx::Rect canvas_rect,
float contents_scale,
- RasterStats* raster_stats);
+ RenderingStatsInstrumentation* rendering_stats_instrumentation,
+ bool is_analysis);
// Once instantiated, |clones_for_drawing_| can't be modified. This
// guarantees thread-safe access during the life time of a PicturePileImpl
diff --git a/chromium/cc/resources/picture_pile_impl_unittest.cc b/chromium/cc/resources/picture_pile_impl_unittest.cc
index 6f33691b5da..e5691e39301 100644
--- a/chromium/cc/resources/picture_pile_impl_unittest.cc
+++ b/chromium/cc/resources/picture_pile_impl_unittest.cc
@@ -635,128 +635,75 @@ TEST(PicturePileImplTest, PixelRefIteratorLazyRefsBaseNonLazy) {
}
}
-TEST(PicturePileImplTest, PixelRefIteratorMultiplePictures) {
- gfx::Size tile_size(256, 256);
- gfx::Size layer_bounds(256, 256);
-
- SkTileGridPicture::TileGridInfo tile_grid_info;
- tile_grid_info.fTileInterval = SkISize::Make(256, 256);
- tile_grid_info.fMargin.setEmpty();
- tile_grid_info.fOffset.setZero();
-
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
-
- SkBitmap lazy_bitmap[2][2];
- CreateBitmap(gfx::Size(32, 32), "lazy", &lazy_bitmap[0][0]);
- CreateBitmap(gfx::Size(32, 32), "lazy", &lazy_bitmap[0][1]);
- CreateBitmap(gfx::Size(32, 32), "lazy", &lazy_bitmap[1][1]);
- SkBitmap non_lazy_bitmap;
- CreateBitmap(gfx::Size(256, 256), "notlazy", &non_lazy_bitmap);
-
- // Each bitmap goes into its own picture, the final layout
- // has lazy pixel refs in the following regions:
- // ||=======||
- // ||x| |x||
- // ||-- --||
- // || |x||
- // ||=======||
- pile->add_draw_bitmap(non_lazy_bitmap, gfx::Point(0, 0));
- pile->RerecordPile();
-
- FakeContentLayerClient content_layer_clients[2][2];
- FakeRenderingStatsInstrumentation stats_instrumentation;
- scoped_refptr<Picture> pictures[2][2];
- for (int y = 0; y < 2; ++y) {
- for (int x = 0; x < 2; ++x) {
- if (x == 0 && y == 1)
- continue;
- content_layer_clients[y][x].add_draw_bitmap(
- lazy_bitmap[y][x],
- gfx::Point(x * 128 + 10, y * 128 + 10));
- pictures[y][x] = Picture::Create(
- gfx::Rect(x * 128 + 10, y * 128 + 10, 64, 64));
- pictures[y][x]->Record(
- &content_layer_clients[y][x],
- tile_grid_info,
- &stats_instrumentation);
- pictures[y][x]->GatherPixelRefs(tile_grid_info, &stats_instrumentation);
- pile->AddPictureToRecording(0, 0, pictures[y][x]);
- }
- }
-
- // These should find only one pixel ref.
- {
- PicturePileImpl::PixelRefIterator iterator(
- gfx::Rect(0, 0, 128, 128), 1.0, pile.get());
- EXPECT_TRUE(iterator);
- EXPECT_TRUE(*iterator == lazy_bitmap[0][0].pixelRef());
- EXPECT_FALSE(++iterator);
- }
- {
- PicturePileImpl::PixelRefIterator iterator(
- gfx::Rect(128, 0, 128, 128), 1.0, pile.get());
- EXPECT_TRUE(iterator);
- EXPECT_TRUE(*iterator == lazy_bitmap[0][1].pixelRef());
- EXPECT_FALSE(++iterator);
- }
- {
- PicturePileImpl::PixelRefIterator iterator(
- gfx::Rect(128, 128, 128, 128), 1.0, pile.get());
- EXPECT_TRUE(iterator);
- EXPECT_TRUE(*iterator == lazy_bitmap[1][1].pixelRef());
- EXPECT_FALSE(++iterator);
- }
- // This one should not find any refs
- {
- PicturePileImpl::PixelRefIterator iterator(
- gfx::Rect(0, 128, 128, 128), 1.0, pile.get());
- EXPECT_FALSE(iterator);
- }
-}
-
TEST(PicturePileImpl, RasterContentsOpaque) {
gfx::Size tile_size(1000, 1000);
gfx::Size layer_bounds(3, 5);
float contents_scale = 1.5f;
+ float raster_divisions = 2.f;
scoped_refptr<FakePicturePileImpl> pile =
FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
// Because the caller sets content opaque, it also promises that it
// has at least filled in layer_bounds opaquely.
- SkPaint red_paint;
- red_paint.setColor(SK_ColorRED);
- pile->add_draw_rect_with_paint(gfx::Rect(layer_bounds), red_paint);
+ SkPaint white_paint;
+ white_paint.setColor(SK_ColorWHITE);
+ pile->add_draw_rect_with_paint(gfx::Rect(layer_bounds), white_paint);
pile->SetMinContentsScale(contents_scale);
- pile->set_background_color(SK_ColorRED);
+ pile->set_background_color(SK_ColorBLACK);
pile->set_contents_opaque(true);
+ pile->set_clear_canvas_with_debug_color(false);
pile->RerecordPile();
gfx::Size content_bounds(
gfx::ToCeiledSize(gfx::ScaleSize(layer_bounds, contents_scale)));
- // Simulate a canvas rect larger than the content bounds. Every pixel
- // up to one pixel outside the content bounds is guaranteed to be opaque.
- // Outside of that is undefined.
- gfx::Rect canvas_rect(content_bounds);
- canvas_rect.Inset(0, 0, -1, -1);
-
- SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kARGB_8888_Config,
- canvas_rect.width(),
- canvas_rect.height());
- bitmap.allocPixels();
- SkCanvas canvas(bitmap);
-
- PicturePileImpl::RasterStats raster_stats;
- pile->RasterToBitmap(
- &canvas, canvas_rect, contents_scale, &raster_stats);
-
- 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]), 255u);
+ // 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.setConfig(SkBitmap::kARGB_8888_Config,
+ canvas_rect.width(),
+ canvas_rect.height());
+ bitmap.allocPixels();
+ SkCanvas canvas(bitmap);
+ canvas.clear(SK_ColorTRANSPARENT);
+
+ FakeRenderingStatsInstrumentation rendering_stats_instrumentation;
+
+ pile->RasterToBitmap(&canvas,
+ canvas_rect,
+ contents_scale,
+ &rendering_stats_instrumentation);
+
+ 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));
+ }
}
}
@@ -770,6 +717,7 @@ TEST(PicturePileImpl, RasterContentsTransparent) {
pile->set_background_color(SK_ColorTRANSPARENT);
pile->set_contents_opaque(false);
pile->SetMinContentsScale(contents_scale);
+ pile->set_clear_canvas_with_debug_color(false);
pile->RerecordPile();
gfx::Size content_bounds(
@@ -785,9 +733,9 @@ TEST(PicturePileImpl, RasterContentsTransparent) {
bitmap.allocPixels();
SkCanvas canvas(bitmap);
- PicturePileImpl::RasterStats raster_stats;
+ FakeRenderingStatsInstrumentation rendering_stats_instrumentation;
pile->RasterToBitmap(
- &canvas, canvas_rect, contents_scale, &raster_stats);
+ &canvas, canvas_rect, contents_scale, &rendering_stats_instrumentation);
SkColor* pixels = reinterpret_cast<SkColor*>(bitmap.getPixels());
int num_pixels = bitmap.width() * bitmap.height();
diff --git a/chromium/cc/resources/picture_pile_unittest.cc b/chromium/cc/resources/picture_pile_unittest.cc
index 1eeb5ad5fe5..91ec355424e 100644
--- a/chromium/cc/resources/picture_pile_unittest.cc
+++ b/chromium/cc/resources/picture_pile_unittest.cc
@@ -2,6 +2,9 @@
// 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/resources/picture_pile.h"
#include "cc/test/fake_content_layer_client.h"
#include "cc/test/fake_rendering_stats_instrumentation.h"
@@ -16,11 +19,11 @@ class TestPicturePile : public PicturePile {
public:
using PicturePile::buffer_pixels;
- PictureListMap& picture_list_map() { return picture_list_map_; }
+ PictureMap& picture_map() { return picture_map_; }
- typedef PicturePile::PictureList PictureList;
- typedef PicturePile::PictureListMapKey PictureListMapKey;
- typedef PicturePile::PictureListMap PictureListMap;
+ typedef PicturePile::PictureInfo PictureInfo;
+ typedef PicturePile::PictureMapKey PictureMapKey;
+ typedef PicturePile::PictureMap PictureMap;
protected:
virtual ~TestPicturePile() {}
@@ -46,6 +49,7 @@ TEST(PicturePileTest, SmallInvalidateInflated) {
false,
gfx::Rect(layer_size),
gfx::Rect(layer_size),
+ 1,
&stats_instrumentation);
// Invalidate something inside a tile.
@@ -55,27 +59,23 @@ TEST(PicturePileTest, SmallInvalidateInflated) {
false,
invalidate_rect,
gfx::Rect(layer_size),
+ 2,
&stats_instrumentation);
EXPECT_EQ(1, pile->tiling().num_tiles_x());
EXPECT_EQ(1, pile->tiling().num_tiles_y());
- TestPicturePile::PictureList& picture_list =
- pile->picture_list_map().find(
- TestPicturePile::PictureListMapKey(0, 0))->second;
- EXPECT_EQ(2u, picture_list.size());
- for (TestPicturePile::PictureList::iterator it = picture_list.begin();
- it != picture_list.end();
- ++it) {
- scoped_refptr<Picture> picture = *it;
- gfx::Rect picture_rect =
- gfx::ScaleToEnclosedRect(picture->LayerRect(), min_scale);
-
- // The invalidation in each tile should have been made 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();
- }
+ TestPicturePile::PictureInfo& picture_info =
+ pile->picture_map().find(TestPicturePile::PictureMapKey(0, 0))->second;
+ // We should have a picture.
+ EXPECT_TRUE(!!picture_info.GetPicture());
+ gfx::Rect picture_rect = gfx::ScaleToEnclosedRect(
+ picture_info.GetPicture()->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(PicturePileTest, LargeInvalidateInflated) {
@@ -98,6 +98,7 @@ TEST(PicturePileTest, LargeInvalidateInflated) {
false,
gfx::Rect(layer_size),
gfx::Rect(layer_size),
+ 1,
&stats_instrumentation);
// Invalidate something inside a tile.
@@ -107,29 +108,23 @@ TEST(PicturePileTest, LargeInvalidateInflated) {
false,
invalidate_rect,
gfx::Rect(layer_size),
+ 2,
&stats_instrumentation);
EXPECT_EQ(1, pile->tiling().num_tiles_x());
EXPECT_EQ(1, pile->tiling().num_tiles_y());
- TestPicturePile::PictureList& picture_list =
- pile->picture_list_map().find(
- TestPicturePile::PictureListMapKey(0, 0))->second;
- EXPECT_EQ(2u, picture_list.size());
+ TestPicturePile::PictureInfo& picture_info =
+ pile->picture_map().find(TestPicturePile::PictureMapKey(0, 0))->second;
+ EXPECT_TRUE(!!picture_info.GetPicture());
int expected_inflation = pile->buffer_pixels();
- scoped_refptr<Picture> base_picture = *picture_list.begin();
+ Picture* base_picture = picture_info.GetPicture();
gfx::Rect base_picture_rect(layer_size);
base_picture_rect.Inset(-expected_inflation, -expected_inflation);
EXPECT_EQ(base_picture_rect.ToString(),
base_picture->LayerRect().ToString());
-
- scoped_refptr<Picture> picture = *(++picture_list.begin());
- gfx::Rect picture_rect(invalidate_rect);
- picture_rect.Inset(-expected_inflation, -expected_inflation);
- EXPECT_EQ(picture_rect.ToString(),
- picture->LayerRect().ToString());
}
TEST(PicturePileTest, InvalidateOnTileBoundaryInflated) {
@@ -155,12 +150,23 @@ TEST(PicturePileTest, InvalidateOnTileBoundaryInflated) {
EXPECT_EQ(7, pile->buffer_pixels());
EXPECT_EQ(7, pile->tiling().border_texels());
- // Update the whole layer.
+ // Update the whole layer to create initial pictures.
+ pile->Update(&client,
+ background_color,
+ false,
+ gfx::Rect(layer_size),
+ gfx::Rect(layer_size),
+ 0,
+ &stats_instrumentation);
+
+ // Invalidate everything again to have a non zero invalidation
+ // frequency.
pile->Update(&client,
background_color,
false,
gfx::Rect(layer_size),
gfx::Rect(layer_size),
+ 1,
&stats_instrumentation);
// Invalidate something just over a tile boundary by a single pixel.
@@ -175,34 +181,120 @@ TEST(PicturePileTest, InvalidateOnTileBoundaryInflated) {
false,
invalidate_rect,
gfx::Rect(layer_size),
+ 2,
&stats_instrumentation);
for (int i = 0; i < pile->tiling().num_tiles_x(); ++i) {
for (int j = 0; j < pile->tiling().num_tiles_y(); ++j) {
- // (1, 0) and (1, 1) should be invalidated partially.
- bool expect_invalidated = i == 1 && (j == 0 || j == 1);
-
- TestPicturePile::PictureList& picture_list =
- pile->picture_list_map().find(
- TestPicturePile::PictureListMapKey(i, j))->second;
- if (!expect_invalidated) {
- EXPECT_EQ(1u, picture_list.size()) << "For i,j " << i << "," << j;
- continue;
+ TestPicturePile::PictureInfo& picture_info =
+ pile->picture_map().find(
+ TestPicturePile::PictureMapKey(i, j))->second;
+
+ // Expect (1, 1) and (1, 0) to be invalidated once more
+ // than the rest of the tiles.
+ if (i == 1 && (j == 0 || j == 1)) {
+ EXPECT_FLOAT_EQ(
+ 2.0f / TestPicturePile::PictureInfo::INVALIDATION_FRAMES_TRACKED,
+ picture_info.GetInvalidationFrequencyForTesting());
+ } else {
+ EXPECT_FLOAT_EQ(
+ 1.0f / TestPicturePile::PictureInfo::INVALIDATION_FRAMES_TRACKED,
+ picture_info.GetInvalidationFrequencyForTesting());
}
+ }
+ }
+}
- EXPECT_EQ(2u, picture_list.size()) << "For i,j " << i << "," << j;
- for (TestPicturePile::PictureList::iterator it = picture_list.begin();
- it != picture_list.end();
- ++it) {
- scoped_refptr<Picture> picture = *it;
- gfx::Rect picture_rect =
- gfx::ScaleToEnclosedRect(picture->LayerRect(), min_scale);
-
- // The invalidation in each tile should have been made 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(PicturePileTest, StopRecordingOffscreenInvalidations) {
+ FakeContentLayerClient client;
+ FakeRenderingStatsInstrumentation stats_instrumentation;
+ scoped_refptr<TestPicturePile> pile = new TestPicturePile;
+ SkColor background_color = SK_ColorBLUE;
+
+ float min_scale = 0.125;
+ gfx::Size base_picture_size = pile->tiling().max_texture_size();
+
+ gfx::Size layer_size =
+ gfx::ToFlooredSize(gfx::ScaleSize(base_picture_size, 4.f));
+ pile->Resize(layer_size);
+ pile->SetTileGridSize(gfx::Size(1000, 1000));
+ pile->SetMinContentsScale(min_scale);
+
+ gfx::Rect viewport(0, 0, layer_size.width(), 1);
+
+ // Update the whole layer until the invalidation frequency is high.
+ int frame;
+ for (frame = 0; frame < 33; ++frame) {
+ pile->Update(&client,
+ background_color,
+ false,
+ gfx::Rect(layer_size),
+ viewport,
+ frame,
+ &stats_instrumentation);
+ }
+
+ // Make sure we have a high invalidation frequency.
+ for (int i = 0; i < pile->tiling().num_tiles_x(); ++i) {
+ for (int j = 0; j < pile->tiling().num_tiles_y(); ++j) {
+ TestPicturePile::PictureInfo& picture_info =
+ pile->picture_map().find(
+ TestPicturePile::PictureMapKey(i, j))->second;
+ EXPECT_FLOAT_EQ(1.0f, picture_info.GetInvalidationFrequencyForTesting())
+ << "i " << i << " j " << j;
+ }
+ }
+
+ // Update once more with a small viewport 0,0 layer_width by 1
+ pile->Update(&client,
+ background_color,
+ false,
+ gfx::Rect(layer_size),
+ viewport,
+ frame,
+ &stats_instrumentation);
+
+ for (int i = 0; i < pile->tiling().num_tiles_x(); ++i) {
+ for (int j = 0; j < pile->tiling().num_tiles_y(); ++j) {
+ TestPicturePile::PictureInfo& picture_info =
+ pile->picture_map().find(
+ TestPicturePile::PictureMapKey(i, j))->second;
+ EXPECT_FLOAT_EQ(1.0f, picture_info.GetInvalidationFrequencyForTesting());
+
+ // If the y far enough away we expect to find no picture (no re-recording
+ // happened). For close y, the picture should change.
+ if (j >= 2)
+ EXPECT_FALSE(picture_info.GetPicture()) << "i " << i << " j " << j;
+ else
+ EXPECT_TRUE(picture_info.GetPicture()) << "i " << i << " j " << j;
+ }
+ }
+
+ // Now update with no invalidation and full viewport
+ pile->Update(&client,
+ background_color,
+ false,
+ gfx::Rect(),
+ gfx::Rect(layer_size),
+ frame+1,
+ &stats_instrumentation);
+
+ for (int i = 0; i < pile->tiling().num_tiles_x(); ++i) {
+ for (int j = 0; j < pile->tiling().num_tiles_y(); ++j) {
+ TestPicturePile::PictureInfo& picture_info =
+ pile->picture_map().find(
+ TestPicturePile::PictureMapKey(i, j))->second;
+ // Expect the invalidation frequency to be less than 1, since we just
+ // updated with no invalidations.
+ float expected_frequency =
+ 1.0f -
+ 1.0f / TestPicturePile::PictureInfo::INVALIDATION_FRAMES_TRACKED;
+
+ EXPECT_FLOAT_EQ(expected_frequency,
+ picture_info.GetInvalidationFrequencyForTesting());
+
+ // We expect that there are pictures everywhere now.
+ EXPECT_TRUE(picture_info.GetPicture()) << "i " << i << " j " << j;
}
}
}
diff --git a/chromium/cc/resources/picture_unittest.cc b/chromium/cc/resources/picture_unittest.cc
index aa20ebb6381..f279a99b281 100644
--- a/chromium/cc/resources/picture_unittest.cc
+++ b/chromium/cc/resources/picture_unittest.cc
@@ -8,7 +8,6 @@
#include "base/memory/scoped_ptr.h"
#include "base/values.h"
#include "cc/test/fake_content_layer_client.h"
-#include "cc/test/fake_rendering_stats_instrumentation.h"
#include "cc/test/skia_common.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkCanvas.h"
@@ -33,7 +32,6 @@ TEST(PictureTest, AsBase64String) {
tile_grid_info.fOffset.setZero();
FakeContentLayerClient content_layer_client;
- FakeRenderingStatsInstrumentation stats_instrumentation;
scoped_ptr<base::Value> tmp;
@@ -52,8 +50,7 @@ TEST(PictureTest, AsBase64String) {
content_layer_client.add_draw_rect(layer_rect, red_paint);
scoped_refptr<Picture> one_rect_picture = Picture::Create(layer_rect);
one_rect_picture->Record(&content_layer_client,
- tile_grid_info,
- &stats_instrumentation);
+ tile_grid_info);
scoped_ptr<base::Value> serialized_one_rect(
one_rect_picture->AsValue());
@@ -79,8 +76,7 @@ TEST(PictureTest, AsBase64String) {
content_layer_client.add_draw_rect(gfx::Rect(25, 25, 50, 50), green_paint);
scoped_refptr<Picture> two_rect_picture = Picture::Create(layer_rect);
two_rect_picture->Record(&content_layer_client,
- tile_grid_info,
- &stats_instrumentation);
+ tile_grid_info);
scoped_ptr<base::Value> serialized_two_rect(
two_rect_picture->AsValue());
@@ -113,7 +109,6 @@ TEST(PictureTest, PixelRefIterator) {
tile_grid_info.fOffset.setZero();
FakeContentLayerClient content_layer_client;
- FakeRenderingStatsInstrumentation stats_instrumentation;
// Lazy pixel refs are found in the following grids:
// |---|---|---|---|
@@ -130,18 +125,18 @@ TEST(PictureTest, PixelRefIterator) {
for (int x = 0; x < 4; ++x) {
if ((x + y) & 1) {
CreateBitmap(gfx::Size(500, 500), "lazy", &lazy_bitmap[y][x]);
+ SkPaint paint;
content_layer_client.add_draw_bitmap(
lazy_bitmap[y][x],
- gfx::Point(x * 512 + 6, y * 512 + 6));
+ gfx::Point(x * 512 + 6, y * 512 + 6), paint);
}
}
}
scoped_refptr<Picture> picture = Picture::Create(layer_rect);
picture->Record(&content_layer_client,
- tile_grid_info,
- &stats_instrumentation);
- picture->GatherPixelRefs(tile_grid_info, &stats_instrumentation);
+ tile_grid_info);
+ picture->GatherPixelRefs(tile_grid_info);
// Default iterator does not have any pixel refs
{
@@ -211,7 +206,6 @@ TEST(PictureTest, PixelRefIteratorNonZeroLayer) {
tile_grid_info.fOffset.setZero();
FakeContentLayerClient content_layer_client;
- FakeRenderingStatsInstrumentation stats_instrumentation;
// Lazy pixel refs are found in the following grids:
// |---|---|---|---|
@@ -228,18 +222,18 @@ TEST(PictureTest, PixelRefIteratorNonZeroLayer) {
for (int x = 0; x < 4; ++x) {
if ((x + y) & 1) {
CreateBitmap(gfx::Size(500, 500), "lazy", &lazy_bitmap[y][x]);
+ SkPaint paint;
content_layer_client.add_draw_bitmap(
lazy_bitmap[y][x],
- gfx::Point(1024 + x * 512 + 6, y * 512 + 6));
+ gfx::Point(1024 + x * 512 + 6, y * 512 + 6), paint);
}
}
}
scoped_refptr<Picture> picture = Picture::Create(layer_rect);
picture->Record(&content_layer_client,
- tile_grid_info,
- &stats_instrumentation);
- picture->GatherPixelRefs(tile_grid_info, &stats_instrumentation);
+ tile_grid_info);
+ picture->GatherPixelRefs(tile_grid_info);
// Default iterator does not have any pixel refs
{
@@ -333,7 +327,6 @@ TEST(PictureTest, PixelRefIteratorOnePixelQuery) {
tile_grid_info.fOffset.setZero();
FakeContentLayerClient content_layer_client;
- FakeRenderingStatsInstrumentation stats_instrumentation;
// Lazy pixel refs are found in the following grids:
// |---|---|---|---|
@@ -350,18 +343,18 @@ TEST(PictureTest, PixelRefIteratorOnePixelQuery) {
for (int x = 0; x < 4; ++x) {
if ((x + y) & 1) {
CreateBitmap(gfx::Size(500, 500), "lazy", &lazy_bitmap[y][x]);
+ SkPaint paint;
content_layer_client.add_draw_bitmap(
lazy_bitmap[y][x],
- gfx::Point(x * 512 + 6, y * 512 + 6));
+ gfx::Point(x * 512 + 6, y * 512 + 6), paint);
}
}
}
scoped_refptr<Picture> picture = Picture::Create(layer_rect);
picture->Record(&content_layer_client,
- tile_grid_info,
- &stats_instrumentation);
- picture->GatherPixelRefs(tile_grid_info, &stats_instrumentation);
+ tile_grid_info);
+ picture->GatherPixelRefs(tile_grid_info);
for (int y = 0; y < 4; ++y) {
for (int x = 0; x < 4; ++x) {
@@ -389,7 +382,6 @@ TEST(PictureTest, CreateFromSkpValue) {
tile_grid_info.fOffset.setZero();
FakeContentLayerClient content_layer_client;
- FakeRenderingStatsInstrumentation stats_instrumentation;
scoped_ptr<base::Value> tmp;
@@ -408,8 +400,7 @@ TEST(PictureTest, CreateFromSkpValue) {
content_layer_client.add_draw_rect(layer_rect, red_paint);
scoped_refptr<Picture> one_rect_picture = Picture::Create(layer_rect);
one_rect_picture->Record(&content_layer_client,
- tile_grid_info,
- &stats_instrumentation);
+ tile_grid_info);
scoped_ptr<base::Value> serialized_one_rect(
one_rect_picture->AsValue());
diff --git a/chromium/cc/resources/pixel_buffer_raster_worker_pool.cc b/chromium/cc/resources/pixel_buffer_raster_worker_pool.cc
index a555e581540..011e5147e06 100644
--- a/chromium/cc/resources/pixel_buffer_raster_worker_pool.cc
+++ b/chromium/cc/resources/pixel_buffer_raster_worker_pool.cc
@@ -212,11 +212,15 @@ void PixelBufferRasterWorkerPool::ScheduleTasks(RasterTask::Queue* queue) {
check_for_completed_raster_tasks_pending_ = false;
ScheduleCheckForCompletedRasterTasks();
- TRACE_EVENT_ASYNC_STEP1(
+ TRACE_EVENT_ASYNC_STEP_INTO1(
"cc", "ScheduledTasks", this, StateName(),
"state", TracedValue::FromValue(StateAsValue().release()));
}
+GLenum PixelBufferRasterWorkerPool::GetResourceTarget() const {
+ return GL_TEXTURE_2D;
+}
+
ResourceFormat PixelBufferRasterWorkerPool::GetResourceFormat() const {
return resource_provider()->memory_efficient_texture_format();
}
@@ -397,7 +401,7 @@ void PixelBufferRasterWorkerPool::CheckForCompletedRasterTasks() {
if (PendingRasterTaskCount())
ScheduleMoreTasks();
- TRACE_EVENT_ASYNC_STEP1(
+ TRACE_EVENT_ASYNC_STEP_INTO1(
"cc", "ScheduledTasks", this, StateName(),
"state", TracedValue::FromValue(StateAsValue().release()));
diff --git a/chromium/cc/resources/pixel_buffer_raster_worker_pool.h b/chromium/cc/resources/pixel_buffer_raster_worker_pool.h
index a856d8ae5a9..88be2c02a7f 100644
--- a/chromium/cc/resources/pixel_buffer_raster_worker_pool.h
+++ b/chromium/cc/resources/pixel_buffer_raster_worker_pool.h
@@ -34,6 +34,7 @@ class CC_EXPORT PixelBufferRasterWorkerPool : public RasterWorkerPool {
// Overridden from RasterWorkerPool:
virtual void ScheduleTasks(RasterTask::Queue* queue) OVERRIDE;
+ virtual GLenum GetResourceTarget() const OVERRIDE;
virtual ResourceFormat GetResourceFormat() const OVERRIDE;
virtual void OnRasterTasksFinished() OVERRIDE;
virtual void OnRasterTasksRequiredForActivationFinished() OVERRIDE;
diff --git a/chromium/cc/resources/prioritized_resource.cc b/chromium/cc/resources/prioritized_resource.cc
index 313b275a3ab..f62ee40b0cb 100644
--- a/chromium/cc/resources/prioritized_resource.cc
+++ b/chromium/cc/resources/prioritized_resource.cc
@@ -124,6 +124,7 @@ PrioritizedResource::Backing::Backing(unsigned id,
priority_at_last_priority_update_(PriorityCalculator::LowestPriority()),
was_above_priority_cutoff_at_last_priority_update_(false),
in_drawing_impl_tree_(false),
+ in_parent_compositor_(false),
#ifdef NDEBUG
resource_has_been_deleted_(false) {}
#else
@@ -154,7 +155,7 @@ bool PrioritizedResource::Backing::ResourceHasBeenDeleted() const {
return resource_has_been_deleted_;
}
-bool PrioritizedResource::Backing::CanBeRecycled() const {
+bool PrioritizedResource::Backing::CanBeRecycledIfNotInExternalUse() const {
DCHECK(!proxy() || proxy()->IsImplThread());
return !was_above_priority_cutoff_at_last_priority_update_ &&
!in_drawing_impl_tree_;
@@ -173,10 +174,12 @@ void PrioritizedResource::Backing::UpdatePriority() {
}
}
-void PrioritizedResource::Backing::UpdateInDrawingImplTree() {
+void PrioritizedResource::Backing::UpdateState(
+ ResourceProvider* resource_provider) {
DCHECK(!proxy() ||
(proxy()->IsImplThread() && proxy()->IsMainThreadBlocked()));
in_drawing_impl_tree_ = !!owner();
+ in_parent_compositor_ = resource_provider->InUseByConsumer(id());
if (!in_drawing_impl_tree_) {
DCHECK_EQ(priority_at_last_priority_update_,
PriorityCalculator::LowestPriority());
diff --git a/chromium/cc/resources/prioritized_resource.h b/chromium/cc/resources/prioritized_resource.h
index a3d5d89cf64..ee90024fd5c 100644
--- a/chromium/cc/resources/prioritized_resource.h
+++ b/chromium/cc/resources/prioritized_resource.h
@@ -111,10 +111,10 @@ class CC_EXPORT PrioritizedResource {
ResourceFormat format);
~Backing();
void UpdatePriority();
- void UpdateInDrawingImplTree();
+ void UpdateState(ResourceProvider* resource_provider);
PrioritizedResource* owner() { return owner_; }
- bool CanBeRecycled() const;
+ bool CanBeRecycledIfNotInExternalUse() const;
int request_priority_at_last_priority_update() const {
return priority_at_last_priority_update_;
}
@@ -122,6 +122,7 @@ class CC_EXPORT PrioritizedResource {
return was_above_priority_cutoff_at_last_priority_update_;
}
bool in_drawing_impl_tree() const { return in_drawing_impl_tree_; }
+ bool in_parent_compositor() const { return in_parent_compositor_; }
void DeleteResource(ResourceProvider* resource_provider);
bool ResourceHasBeenDeleted() const;
@@ -137,6 +138,8 @@ class CC_EXPORT PrioritizedResource {
// Set if this is currently-drawing impl tree.
bool in_drawing_impl_tree_;
+ // Set if this is in the parent compositor.
+ bool in_parent_compositor_;
bool resource_has_been_deleted_;
diff --git a/chromium/cc/resources/prioritized_resource_manager.cc b/chromium/cc/resources/prioritized_resource_manager.cc
index 1a6e545a1a5..da8f0555124 100644
--- a/chromium/cc/resources/prioritized_resource_manager.cc
+++ b/chromium/cc/resources/prioritized_resource_manager.cc
@@ -160,7 +160,8 @@ void PrioritizedResourceManager::PushTexturePrioritiesToBackings() {
memory_visible_and_nearby_bytes_;
}
-void PrioritizedResourceManager::UpdateBackingsInDrawingImplTree() {
+void PrioritizedResourceManager::UpdateBackingsState(
+ ResourceProvider* resource_provider) {
TRACE_EVENT0("cc",
"PrioritizedResourceManager::UpdateBackingsInDrawingImplTree");
DCHECK(proxy_->IsImplThread() && proxy_->IsMainThreadBlocked());
@@ -169,7 +170,7 @@ void PrioritizedResourceManager::UpdateBackingsInDrawingImplTree() {
for (BackingList::iterator it = backings_.begin(); it != backings_.end();
++it) {
PrioritizedResource::Backing* backing = (*it);
- backing->UpdateInDrawingImplTree();
+ backing->UpdateState(resource_provider);
}
SortBackings();
AssertInvariants();
@@ -240,7 +241,7 @@ void PrioritizedResourceManager::AcquireBackingTextureIfNeeded(
// First try to recycle
for (BackingList::iterator it = backings_.begin(); it != backings_.end();
++it) {
- if (!(*it)->CanBeRecycled())
+ if (!(*it)->CanBeRecycledIfNotInExternalUse())
break;
if (resource_provider->InUseByConsumer((*it)->id()))
continue;
@@ -298,7 +299,8 @@ bool PrioritizedResourceManager::EvictBackingsToReduceMemory(
backing->request_priority_at_last_priority_update(),
priority_cutoff))
break;
- if (eviction_policy == EVICT_ONLY_RECYCLABLE && !backing->CanBeRecycled())
+ if (eviction_policy == EVICT_ONLY_RECYCLABLE &&
+ !backing->CanBeRecycledIfNotInExternalUse())
break;
if (unlink_policy == UNLINK_BACKINGS && backing->owner())
backing->owner()->Unlink();
@@ -320,12 +322,18 @@ void PrioritizedResourceManager::ReduceWastedMemory(
++it) {
if ((*it)->owner())
break;
+ if ((*it)->in_parent_compositor())
+ continue;
wasted_memory += (*it)->bytes();
}
- size_t ten_percent_of_memory = memory_available_bytes_ / 10;
- if (wasted_memory > ten_percent_of_memory)
+ size_t wasted_memory_to_allow = memory_available_bytes_ / 10;
+ // If the external priority cutoff indicates that unused memory should be
+ // freed, then do not allow any memory for texture recycling.
+ if (external_priority_cutoff_ != PriorityCalculator::AllowEverythingCutoff())
+ wasted_memory_to_allow = 0;
+ if (wasted_memory > wasted_memory_to_allow)
EvictBackingsToReduceMemory(MemoryUseBytes() -
- (wasted_memory - ten_percent_of_memory),
+ (wasted_memory - wasted_memory_to_allow),
PriorityCalculator::AllowEverythingCutoff(),
EVICT_ONLY_RECYCLABLE,
DO_NOT_UNLINK_BACKINGS,
@@ -365,6 +373,7 @@ bool PrioritizedResourceManager::ReduceMemoryOnImplThread(
ResourceProvider* resource_provider) {
DCHECK(proxy_->IsImplThread());
DCHECK(resource_provider);
+
// If we are in the process of uploading a new frame then the backings at the
// very end of the list are not sorted by priority. Sort them before doing the
// eviction.
@@ -377,18 +386,6 @@ bool PrioritizedResourceManager::ReduceMemoryOnImplThread(
resource_provider);
}
-void PrioritizedResourceManager::ReduceWastedMemoryOnImplThread(
- ResourceProvider* resource_provider) {
- DCHECK(proxy_->IsImplThread());
- DCHECK(resource_provider);
- // If we are in the process of uploading a new frame then the backings at the
- // very end of the list are not sorted by priority. Sort them before doing the
- // eviction.
- if (backings_tail_not_sorted_)
- SortBackings();
- ReduceWastedMemory(resource_provider);
-}
-
void PrioritizedResourceManager::UnlinkAndClearEvictedBackings() {
DCHECK(proxy_->IsMainThread());
base::AutoLock scoped_lock(evicted_backings_lock_);
@@ -456,6 +453,7 @@ PrioritizedResource::Backing* PrioritizedResourceManager::CreateBacking(
ResourceProvider::ResourceId resource_id =
resource_provider->CreateManagedResource(
size,
+ GL_TEXTURE_2D,
GL_CLAMP_TO_EDGE,
ResourceProvider::TextureUsageAny,
format);
@@ -535,12 +533,12 @@ void PrioritizedResourceManager::AssertInvariants() {
(!backings_tail_not_sorted_ ||
!backing->was_above_priority_cutoff_at_last_priority_update()))
DCHECK(CompareBackings(previous_backing, backing));
- if (!backing->CanBeRecycled())
+ if (!backing->CanBeRecycledIfNotInExternalUse())
reached_unrecyclable = true;
if (reached_unrecyclable)
- DCHECK(!backing->CanBeRecycled());
+ DCHECK(!backing->CanBeRecycledIfNotInExternalUse());
else
- DCHECK(backing->CanBeRecycled());
+ DCHECK(backing->CanBeRecycledIfNotInExternalUse());
previous_backing = backing;
}
#endif
diff --git a/chromium/cc/resources/prioritized_resource_manager.h b/chromium/cc/resources/prioritized_resource_manager.h
index 07cc7cf39a6..9b558a45b8f 100644
--- a/chromium/cc/resources/prioritized_resource_manager.h
+++ b/chromium/cc/resources/prioritized_resource_manager.h
@@ -96,10 +96,6 @@ class CC_EXPORT PrioritizedResourceManager {
int priority_cutoff,
ResourceProvider* resource_provider);
- // Delete contents textures' backing resources that can be recycled. This
- // may be called on the impl thread while the main thread is running.
- void ReduceWastedMemoryOnImplThread(ResourceProvider* resource_provider);
-
// Returns true if there exist any textures that are linked to backings that
// have had their resources evicted. Only when we commit a tree that has no
// textures linked to evicted backings may we allow drawing. After an
@@ -129,7 +125,7 @@ class CC_EXPORT PrioritizedResourceManager {
void PushTexturePrioritiesToBackings();
// Mark all textures' backings as being in the drawing impl tree.
- void UpdateBackingsInDrawingImplTree();
+ void UpdateBackingsState(ResourceProvider* resource_provider);
const Proxy* ProxyForDebug() const;
@@ -156,25 +152,32 @@ class CC_EXPORT PrioritizedResourceManager {
// Compare backings. Lowest priority first.
static inline bool CompareBackings(PrioritizedResource::Backing* a,
PrioritizedResource::Backing* b) {
- // Make textures that can be recycled appear first
- if (a->CanBeRecycled() != b->CanBeRecycled())
- return (a->CanBeRecycled() > b->CanBeRecycled());
+ // Make textures that can be recycled appear first.
+ if (a->CanBeRecycledIfNotInExternalUse() !=
+ b->CanBeRecycledIfNotInExternalUse())
+ return (a->CanBeRecycledIfNotInExternalUse() >
+ b->CanBeRecycledIfNotInExternalUse());
// Then sort by being above or below the priority cutoff.
if (a->was_above_priority_cutoff_at_last_priority_update() !=
b->was_above_priority_cutoff_at_last_priority_update())
return (a->was_above_priority_cutoff_at_last_priority_update() <
b->was_above_priority_cutoff_at_last_priority_update());
// Then sort by priority (note that backings that no longer have owners will
- // always have the lowest priority)
+ // always have the lowest priority).
if (a->request_priority_at_last_priority_update() !=
b->request_priority_at_last_priority_update())
return PriorityCalculator::priority_is_lower(
a->request_priority_at_last_priority_update(),
b->request_priority_at_last_priority_update());
- // Finally sort by being in the impl tree versus being completely
- // unreferenced
+ // Then sort by being in the impl tree versus being completely
+ // unreferenced.
if (a->in_drawing_impl_tree() != b->in_drawing_impl_tree())
return (a->in_drawing_impl_tree() < b->in_drawing_impl_tree());
+ // Finally, prefer to evict textures in the parent compositor because
+ // they will otherwise take another roundtrip to the parent compositor
+ // before they are evicted.
+ if (a->in_parent_compositor() != b->in_parent_compositor())
+ return (a->in_parent_compositor() > b->in_parent_compositor());
return a < b;
}
diff --git a/chromium/cc/resources/prioritized_resource_unittest.cc b/chromium/cc/resources/prioritized_resource_unittest.cc
index 181498c5a34..7619dcc75e3 100644
--- a/chromium/cc/resources/prioritized_resource_unittest.cc
+++ b/chromium/cc/resources/prioritized_resource_unittest.cc
@@ -4,8 +4,11 @@
#include "cc/resources/prioritized_resource.h"
+#include <vector>
+
#include "cc/resources/prioritized_resource_manager.h"
#include "cc/resources/resource.h"
+#include "cc/resources/resource_provider.h"
#include "cc/test/fake_output_surface.h"
#include "cc/test/fake_output_surface_client.h"
#include "cc/test/fake_proxy.h"
@@ -24,7 +27,7 @@ class PrioritizedResourceTest : public testing::Test {
DebugScopedSetImplThread impl_thread(&proxy_);
CHECK(output_surface_->BindToClient(&output_surface_client_));
resource_provider_ =
- cc::ResourceProvider::Create(output_surface_.get(), 0, false);
+ ResourceProvider::Create(output_surface_.get(), NULL, 0, false, 1);
}
virtual ~PrioritizedResourceTest() {
@@ -51,10 +54,10 @@ class PrioritizedResourceTest : public testing::Test {
texture->RequestLate();
ResourceManagerAssertInvariants(texture->resource_manager());
DebugScopedSetImplThreadAndMainThreadBlocked
- impl_thread_and_main_thread_blocked(&proxy_);
+ impl_thread_and_main_thread_blocked(&proxy_);
bool success = texture->can_acquire_backing_texture();
if (success)
- texture->AcquireBackingTexture(ResourceProvider());
+ texture->AcquireBackingTexture(resource_provider());
return success;
}
@@ -67,17 +70,17 @@ class PrioritizedResourceTest : public testing::Test {
void ResourceManagerUpdateBackingsPriorities(
PrioritizedResourceManager* resource_manager) {
DebugScopedSetImplThreadAndMainThreadBlocked
- impl_thread_and_main_thread_blocked(&proxy_);
+ impl_thread_and_main_thread_blocked(&proxy_);
resource_manager->PushTexturePrioritiesToBackings();
}
- cc::ResourceProvider* ResourceProvider() { return resource_provider_.get(); }
+ ResourceProvider* resource_provider() { return resource_provider_.get(); }
void ResourceManagerAssertInvariants(
PrioritizedResourceManager* resource_manager) {
#ifndef NDEBUG
DebugScopedSetImplThreadAndMainThreadBlocked
- impl_thread_and_main_thread_blocked(&proxy_);
+ impl_thread_and_main_thread_blocked(&proxy_);
resource_manager->AssertInvariants();
#endif
}
@@ -91,13 +94,24 @@ class PrioritizedResourceTest : public testing::Test {
return resource_manager->evicted_backings_.size();
}
+ std::vector<unsigned> BackingResources(
+ PrioritizedResourceManager* resource_manager) {
+ std::vector<unsigned> resources;
+ for (PrioritizedResourceManager::BackingList::iterator it =
+ resource_manager->backings_.begin();
+ it != resource_manager->backings_.end();
+ ++it)
+ resources.push_back((*it)->id());
+ return resources;
+ }
+
protected:
FakeProxy proxy_;
const gfx::Size texture_size_;
const ResourceFormat texture_format_;
FakeOutputSurfaceClient output_surface_client_;
scoped_ptr<OutputSurface> output_surface_;
- scoped_ptr<cc::ResourceProvider> resource_provider_;
+ scoped_ptr<ResourceProvider> resource_provider_;
};
namespace {
@@ -144,8 +158,8 @@ TEST_F(PrioritizedResourceTest, RequestTextureExceedingMaxLimit) {
resource_manager->MaxMemoryNeededBytes());
DebugScopedSetImplThreadAndMainThreadBlocked
- impl_thread_and_main_thread_blocked(&proxy_);
- resource_manager->ClearAllMemory(ResourceProvider());
+ impl_thread_and_main_thread_blocked(&proxy_);
+ resource_manager->ClearAllMemory(resource_provider());
}
TEST_F(PrioritizedResourceTest, ChangeMemoryLimits) {
@@ -168,8 +182,8 @@ TEST_F(PrioritizedResourceTest, ChangeMemoryLimits) {
ValidateTexture(textures[i].get(), false);
{
DebugScopedSetImplThreadAndMainThreadBlocked
- impl_thread_and_main_thread_blocked(&proxy_);
- resource_manager->ReduceMemory(ResourceProvider());
+ impl_thread_and_main_thread_blocked(&proxy_);
+ resource_manager->ReduceMemory(resource_provider());
}
EXPECT_EQ(TexturesMemorySize(8), resource_manager->MemoryAboveCutoffBytes());
@@ -183,8 +197,8 @@ TEST_F(PrioritizedResourceTest, ChangeMemoryLimits) {
EXPECT_EQ(ValidateTexture(textures[i].get(), false), i < 5);
{
DebugScopedSetImplThreadAndMainThreadBlocked
- impl_thread_and_main_thread_blocked(&proxy_);
- resource_manager->ReduceMemory(ResourceProvider());
+ impl_thread_and_main_thread_blocked(&proxy_);
+ resource_manager->ReduceMemory(resource_provider());
}
EXPECT_EQ(TexturesMemorySize(5), resource_manager->MemoryAboveCutoffBytes());
@@ -200,8 +214,8 @@ TEST_F(PrioritizedResourceTest, ChangeMemoryLimits) {
EXPECT_EQ(ValidateTexture(textures[i].get(), false), i < 4);
{
DebugScopedSetImplThreadAndMainThreadBlocked
- impl_thread_and_main_thread_blocked(&proxy_);
- resource_manager->ReduceMemory(ResourceProvider());
+ impl_thread_and_main_thread_blocked(&proxy_);
+ resource_manager->ReduceMemory(resource_provider());
}
EXPECT_EQ(TexturesMemorySize(4), resource_manager->MemoryAboveCutoffBytes());
@@ -211,8 +225,158 @@ TEST_F(PrioritizedResourceTest, ChangeMemoryLimits) {
resource_manager->MaxMemoryNeededBytes());
DebugScopedSetImplThreadAndMainThreadBlocked
- impl_thread_and_main_thread_blocked(&proxy_);
- resource_manager->ClearAllMemory(ResourceProvider());
+ impl_thread_and_main_thread_blocked(&proxy_);
+ resource_manager->ClearAllMemory(resource_provider());
+}
+
+TEST_F(PrioritizedResourceTest, ReduceWastedMemory) {
+ const size_t kMaxTextures = 20;
+ scoped_ptr<PrioritizedResourceManager> resource_manager =
+ CreateManager(kMaxTextures);
+ scoped_ptr<PrioritizedResource> textures[kMaxTextures];
+
+ for (size_t i = 0; i < kMaxTextures; ++i) {
+ textures[i] =
+ resource_manager->CreateTexture(texture_size_, texture_format_);
+ }
+ for (size_t i = 0; i < kMaxTextures; ++i)
+ textures[i]->set_request_priority(100 + i);
+
+ // Set the memory limit to the max number of textures.
+ resource_manager->SetMaxMemoryLimitBytes(TexturesMemorySize(kMaxTextures));
+ PrioritizeTexturesAndBackings(resource_manager.get());
+
+ // Create backings and textures for all of the textures.
+ for (size_t i = 0; i < kMaxTextures; ++i) {
+ ValidateTexture(textures[i].get(), false);
+
+ {
+ DebugScopedSetImplThreadAndMainThreadBlocked
+ impl_thread_and_main_thread_blocked(&proxy_);
+ uint8_t image[4] = {0};
+ textures[i]->SetPixels(resource_provider_.get(),
+ image,
+ gfx::Rect(1, 1),
+ gfx::Rect(1, 1),
+ gfx::Vector2d());
+ }
+ }
+ {
+ DebugScopedSetImplThreadAndMainThreadBlocked
+ impl_thread_and_main_thread_blocked(&proxy_);
+ resource_manager->ReduceMemory(resource_provider());
+ }
+
+ // 20 textures have backings allocated.
+ EXPECT_EQ(TexturesMemorySize(20), resource_manager->MemoryUseBytes());
+
+ // Destroy one texture, not enough is wasted to cause cleanup.
+ textures[0] = scoped_ptr<PrioritizedResource>();
+ PrioritizeTexturesAndBackings(resource_manager.get());
+ {
+ DebugScopedSetImplThreadAndMainThreadBlocked
+ impl_thread_and_main_thread_blocked(&proxy_);
+ resource_manager->UpdateBackingsState(resource_provider());
+ resource_manager->ReduceWastedMemory(resource_provider());
+ }
+ EXPECT_EQ(TexturesMemorySize(20), resource_manager->MemoryUseBytes());
+
+ // Destroy half the textures, leaving behind the backings. Now a cleanup
+ // should happen.
+ for (size_t i = 0; i < kMaxTextures / 2; ++i)
+ textures[i] = scoped_ptr<PrioritizedResource>();
+ PrioritizeTexturesAndBackings(resource_manager.get());
+ {
+ DebugScopedSetImplThreadAndMainThreadBlocked
+ impl_thread_and_main_thread_blocked(&proxy_);
+ resource_manager->UpdateBackingsState(resource_provider());
+ resource_manager->ReduceWastedMemory(resource_provider());
+ }
+ EXPECT_GT(TexturesMemorySize(20), resource_manager->MemoryUseBytes());
+
+ DebugScopedSetImplThreadAndMainThreadBlocked
+ impl_thread_and_main_thread_blocked(&proxy_);
+ resource_manager->ClearAllMemory(resource_provider());
+}
+
+TEST_F(PrioritizedResourceTest, InUseNotWastedMemory) {
+ const size_t kMaxTextures = 20;
+ scoped_ptr<PrioritizedResourceManager> resource_manager =
+ CreateManager(kMaxTextures);
+ scoped_ptr<PrioritizedResource> textures[kMaxTextures];
+
+ for (size_t i = 0; i < kMaxTextures; ++i) {
+ textures[i] =
+ resource_manager->CreateTexture(texture_size_, texture_format_);
+ }
+ for (size_t i = 0; i < kMaxTextures; ++i)
+ textures[i]->set_request_priority(100 + i);
+
+ // Set the memory limit to the max number of textures.
+ resource_manager->SetMaxMemoryLimitBytes(TexturesMemorySize(kMaxTextures));
+ PrioritizeTexturesAndBackings(resource_manager.get());
+
+ // Create backings and textures for all of the textures.
+ for (size_t i = 0; i < kMaxTextures; ++i) {
+ ValidateTexture(textures[i].get(), false);
+
+ {
+ DebugScopedSetImplThreadAndMainThreadBlocked
+ impl_thread_and_main_thread_blocked(&proxy_);
+ uint8_t image[4] = {0};
+ textures[i]->SetPixels(resource_provider_.get(),
+ image,
+ gfx::Rect(1, 1),
+ gfx::Rect(1, 1),
+ gfx::Vector2d());
+ }
+ }
+ {
+ DebugScopedSetImplThreadAndMainThreadBlocked
+ impl_thread_and_main_thread_blocked(&proxy_);
+ resource_manager->ReduceMemory(resource_provider());
+ }
+
+ // 20 textures have backings allocated.
+ EXPECT_EQ(TexturesMemorySize(20), resource_manager->MemoryUseBytes());
+
+ // Send half the textures to a parent compositor.
+ ResourceProvider::ResourceIdArray to_send;
+ TransferableResourceArray transferable;
+ for (size_t i = 0; i < kMaxTextures / 2; ++i)
+ to_send.push_back(textures[i]->resource_id());
+ resource_provider_->PrepareSendToParent(to_send, &transferable);
+
+ // Destroy half the textures, leaving behind the backings. The backings are
+ // sent to a parent compositor though, so they should not be considered wasted
+ // and a cleanup should not happen.
+ for (size_t i = 0; i < kMaxTextures / 2; ++i)
+ textures[i] = scoped_ptr<PrioritizedResource>();
+ PrioritizeTexturesAndBackings(resource_manager.get());
+ {
+ DebugScopedSetImplThreadAndMainThreadBlocked
+ impl_thread_and_main_thread_blocked(&proxy_);
+ resource_manager->UpdateBackingsState(resource_provider());
+ resource_manager->ReduceWastedMemory(resource_provider());
+ }
+ EXPECT_EQ(TexturesMemorySize(20), resource_manager->MemoryUseBytes());
+
+ // Receive the textures back from the parent compositor. Now a cleanup should
+ // happen.
+ ReturnedResourceArray returns;
+ TransferableResource::ReturnResources(transferable, &returns);
+ resource_provider_->ReceiveReturnsFromParent(returns);
+ {
+ DebugScopedSetImplThreadAndMainThreadBlocked
+ impl_thread_and_main_thread_blocked(&proxy_);
+ resource_manager->UpdateBackingsState(resource_provider());
+ resource_manager->ReduceWastedMemory(resource_provider());
+ }
+ EXPECT_GT(TexturesMemorySize(20), resource_manager->MemoryUseBytes());
+
+ DebugScopedSetImplThreadAndMainThreadBlocked
+ impl_thread_and_main_thread_blocked(&proxy_);
+ resource_manager->ClearAllMemory(resource_provider());
}
TEST_F(PrioritizedResourceTest, ChangePriorityCutoff) {
@@ -238,8 +402,8 @@ TEST_F(PrioritizedResourceTest, ChangePriorityCutoff) {
EXPECT_EQ(ValidateTexture(textures[i].get(), true), i < 6);
{
DebugScopedSetImplThreadAndMainThreadBlocked
- impl_thread_and_main_thread_blocked(&proxy_);
- resource_manager->ReduceMemory(ResourceProvider());
+ impl_thread_and_main_thread_blocked(&proxy_);
+ resource_manager->ReduceMemory(resource_provider());
}
EXPECT_EQ(TexturesMemorySize(6), resource_manager->MemoryAboveCutoffBytes());
EXPECT_LE(resource_manager->MemoryUseBytes(),
@@ -252,22 +416,21 @@ TEST_F(PrioritizedResourceTest, ChangePriorityCutoff) {
EXPECT_EQ(ValidateTexture(textures[i].get(), false), i < 4);
{
DebugScopedSetImplThreadAndMainThreadBlocked
- impl_thread_and_main_thread_blocked(&proxy_);
- resource_manager->ReduceMemory(ResourceProvider());
+ impl_thread_and_main_thread_blocked(&proxy_);
+ resource_manager->ReduceMemory(resource_provider());
}
EXPECT_EQ(TexturesMemorySize(4), resource_manager->MemoryAboveCutoffBytes());
// Do a one-time eviction for one more texture based on priority cutoff
- PrioritizedResourceManager::BackingList evicted_backings;
resource_manager->UnlinkAndClearEvictedBackings();
{
DebugScopedSetImplThreadAndMainThreadBlocked
- impl_thread_and_main_thread_blocked(&proxy_);
+ impl_thread_and_main_thread_blocked(&proxy_);
resource_manager->ReduceMemoryOnImplThread(
- TexturesMemorySize(8), 104, ResourceProvider());
+ TexturesMemorySize(8), 104, resource_provider());
EXPECT_EQ(0u, EvictedBackingCount(resource_manager.get()));
resource_manager->ReduceMemoryOnImplThread(
- TexturesMemorySize(8), 103, ResourceProvider());
+ TexturesMemorySize(8), 103, resource_provider());
EXPECT_EQ(1u, EvictedBackingCount(resource_manager.get()));
}
resource_manager->UnlinkAndClearEvictedBackings();
@@ -279,14 +442,157 @@ TEST_F(PrioritizedResourceTest, ChangePriorityCutoff) {
EXPECT_EQ(ValidateTexture(textures[i].get(), false), i < 4);
{
DebugScopedSetImplThreadAndMainThreadBlocked
- impl_thread_and_main_thread_blocked(&proxy_);
- resource_manager->ReduceMemory(ResourceProvider());
+ impl_thread_and_main_thread_blocked(&proxy_);
+ resource_manager->ReduceMemory(resource_provider());
}
EXPECT_EQ(TexturesMemorySize(4), resource_manager->MemoryAboveCutoffBytes());
DebugScopedSetImplThreadAndMainThreadBlocked
- impl_thread_and_main_thread_blocked(&proxy_);
- resource_manager->ClearAllMemory(ResourceProvider());
+ impl_thread_and_main_thread_blocked(&proxy_);
+ resource_manager->ClearAllMemory(resource_provider());
+}
+
+TEST_F(PrioritizedResourceTest, EvictingTexturesInParent) {
+ const size_t kMaxTextures = 8;
+ scoped_ptr<PrioritizedResourceManager> resource_manager =
+ CreateManager(kMaxTextures);
+ scoped_ptr<PrioritizedResource> textures[kMaxTextures];
+ unsigned texture_resource_ids[kMaxTextures];
+
+ for (size_t i = 0; i < kMaxTextures; ++i) {
+ textures[i] =
+ resource_manager->CreateTexture(texture_size_, texture_format_);
+ textures[i]->set_request_priority(100 + i);
+ }
+
+ PrioritizeTexturesAndBackings(resource_manager.get());
+ for (size_t i = 0; i < kMaxTextures; ++i) {
+ EXPECT_TRUE(ValidateTexture(textures[i].get(), true));
+
+ {
+ DebugScopedSetImplThreadAndMainThreadBlocked
+ impl_thread_and_main_thread_blocked(&proxy_);
+ uint8_t image[4] = {0};
+ textures[i]->SetPixels(resource_provider_.get(),
+ image,
+ gfx::Rect(1, 1),
+ gfx::Rect(1, 1),
+ gfx::Vector2d());
+ }
+ }
+ {
+ DebugScopedSetImplThreadAndMainThreadBlocked
+ impl_thread_and_main_thread_blocked(&proxy_);
+ resource_manager->ReduceMemory(resource_provider());
+ }
+ EXPECT_EQ(TexturesMemorySize(8), resource_manager->MemoryAboveCutoffBytes());
+
+ for (size_t i = 0; i < 8; ++i)
+ texture_resource_ids[i] = textures[i]->resource_id();
+
+ // Evict four textures. It will be the last four.
+ {
+ DebugScopedSetImplThreadAndMainThreadBlocked
+ impl_thread_and_main_thread_blocked(&proxy_);
+ resource_manager->ReduceMemoryOnImplThread(
+ TexturesMemorySize(4), 200, resource_provider());
+
+ EXPECT_EQ(4u, EvictedBackingCount(resource_manager.get()));
+
+ // The last four backings are evicted.
+ std::vector<unsigned> remaining = BackingResources(resource_manager.get());
+ EXPECT_TRUE(std::find(remaining.begin(),
+ remaining.end(),
+ texture_resource_ids[0]) != remaining.end());
+ EXPECT_TRUE(std::find(remaining.begin(),
+ remaining.end(),
+ texture_resource_ids[1]) != remaining.end());
+ EXPECT_TRUE(std::find(remaining.begin(),
+ remaining.end(),
+ texture_resource_ids[2]) != remaining.end());
+ EXPECT_TRUE(std::find(remaining.begin(),
+ remaining.end(),
+ texture_resource_ids[3]) != remaining.end());
+ }
+ resource_manager->UnlinkAndClearEvictedBackings();
+ EXPECT_EQ(TexturesMemorySize(4), resource_manager->MemoryUseBytes());
+
+ // Re-allocate the the texture after the eviction.
+ PrioritizeTexturesAndBackings(resource_manager.get());
+ for (size_t i = 0; i < kMaxTextures; ++i) {
+ EXPECT_TRUE(ValidateTexture(textures[i].get(), true));
+
+ {
+ DebugScopedSetImplThreadAndMainThreadBlocked
+ impl_thread_and_main_thread_blocked(&proxy_);
+ uint8_t image[4] = {0};
+ textures[i]->SetPixels(resource_provider_.get(),
+ image,
+ gfx::Rect(1, 1),
+ gfx::Rect(1, 1),
+ gfx::Vector2d());
+ }
+ }
+ {
+ DebugScopedSetImplThreadAndMainThreadBlocked
+ impl_thread_and_main_thread_blocked(&proxy_);
+ resource_manager->ReduceMemory(resource_provider());
+ }
+ EXPECT_EQ(TexturesMemorySize(8), resource_manager->MemoryAboveCutoffBytes());
+
+ // Send the last two of the textures to a parent compositor.
+ ResourceProvider::ResourceIdArray to_send;
+ TransferableResourceArray transferable;
+ for (size_t i = 6; i < 8; ++i)
+ to_send.push_back(textures[i]->resource_id());
+ resource_provider_->PrepareSendToParent(to_send, &transferable);
+
+ // Set the last two textures to be tied for prioity with the two
+ // before them. Being sent to the parent will break the tie.
+ textures[4]->set_request_priority(100 + 4);
+ textures[5]->set_request_priority(100 + 5);
+ textures[6]->set_request_priority(100 + 4);
+ textures[7]->set_request_priority(100 + 5);
+
+ for (size_t i = 0; i < 8; ++i)
+ texture_resource_ids[i] = textures[i]->resource_id();
+
+ // Drop all the textures. Now we have backings that can be recycled.
+ for (size_t i = 0; i < 8; ++i)
+ textures[0].reset();
+ PrioritizeTexturesAndBackings(resource_manager.get());
+
+ // The next commit finishes.
+ {
+ DebugScopedSetImplThreadAndMainThreadBlocked
+ impl_thread_and_main_thread_blocked(&proxy_);
+ resource_manager->UpdateBackingsState(resource_provider());
+ }
+
+ // Evict four textures. It would be the last four again, except that 2 of them
+ // are sent to the parent, so they are evicted last.
+ {
+ DebugScopedSetImplThreadAndMainThreadBlocked
+ impl_thread_and_main_thread_blocked(&proxy_);
+ resource_manager->ReduceMemoryOnImplThread(
+ TexturesMemorySize(4), 200, resource_provider());
+
+ EXPECT_EQ(4u, EvictedBackingCount(resource_manager.get()));
+ // The last 2 backings remain this time.
+ std::vector<unsigned> remaining = BackingResources(resource_manager.get());
+ EXPECT_TRUE(std::find(remaining.begin(),
+ remaining.end(),
+ texture_resource_ids[6]) == remaining.end());
+ EXPECT_TRUE(std::find(remaining.begin(),
+ remaining.end(),
+ texture_resource_ids[7]) == remaining.end());
+ }
+ resource_manager->UnlinkAndClearEvictedBackings();
+ EXPECT_EQ(TexturesMemorySize(4), resource_manager->MemoryUseBytes());
+
+ DebugScopedSetImplThreadAndMainThreadBlocked
+ impl_thread_and_main_thread_blocked(&proxy_);
+ resource_manager->ClearAllMemory(resource_provider());
}
TEST_F(PrioritizedResourceTest, ResourceManagerPartialUpdateTextures) {
@@ -348,8 +654,8 @@ TEST_F(PrioritizedResourceTest, ResourceManagerPartialUpdateTextures) {
EXPECT_FALSE(textures[3]->have_backing_texture());
DebugScopedSetImplThreadAndMainThreadBlocked
- impl_thread_and_main_thread_blocked(&proxy_);
- resource_manager->ClearAllMemory(ResourceProvider());
+ impl_thread_and_main_thread_blocked(&proxy_);
+ resource_manager->ClearAllMemory(resource_provider());
}
TEST_F(PrioritizedResourceTest, ResourceManagerPrioritiesAreEqual) {
@@ -393,8 +699,8 @@ TEST_F(PrioritizedResourceTest, ResourceManagerPrioritiesAreEqual) {
resource_manager->MemoryAboveCutoffBytes());
DebugScopedSetImplThreadAndMainThreadBlocked
- impl_thread_and_main_thread_blocked(&proxy_);
- resource_manager->ClearAllMemory(ResourceProvider());
+ impl_thread_and_main_thread_blocked(&proxy_);
+ resource_manager->ClearAllMemory(resource_provider());
}
TEST_F(PrioritizedResourceTest, ResourceManagerDestroyedFirst) {
@@ -413,8 +719,8 @@ TEST_F(PrioritizedResourceTest, ResourceManagerDestroyedFirst) {
EXPECT_TRUE(texture->have_backing_texture());
{
DebugScopedSetImplThreadAndMainThreadBlocked
- impl_thread_and_main_thread_blocked(&proxy_);
- resource_manager->ClearAllMemory(ResourceProvider());
+ impl_thread_and_main_thread_blocked(&proxy_);
+ resource_manager->ClearAllMemory(resource_provider());
}
resource_manager.reset();
@@ -443,8 +749,8 @@ TEST_F(PrioritizedResourceTest, TextureMovedToNewManager) {
texture->SetTextureManager(NULL);
{
DebugScopedSetImplThreadAndMainThreadBlocked
- impl_thread_and_main_thread_blocked(&proxy_);
- resource_manager_one->ClearAllMemory(ResourceProvider());
+ impl_thread_and_main_thread_blocked(&proxy_);
+ resource_manager_one->ClearAllMemory(resource_provider());
}
resource_manager_one.reset();
@@ -460,8 +766,8 @@ TEST_F(PrioritizedResourceTest, TextureMovedToNewManager) {
EXPECT_TRUE(texture->have_backing_texture());
DebugScopedSetImplThreadAndMainThreadBlocked
- impl_thread_and_main_thread_blocked(&proxy_);
- resource_manager_two->ClearAllMemory(ResourceProvider());
+ impl_thread_and_main_thread_blocked(&proxy_);
+ resource_manager_two->ClearAllMemory(resource_provider());
}
TEST_F(PrioritizedResourceTest,
@@ -517,8 +823,8 @@ TEST_F(PrioritizedResourceTest,
resource_manager->MaxMemoryNeededBytes());
DebugScopedSetImplThreadAndMainThreadBlocked
- impl_thread_and_main_thread_blocked(&proxy_);
- resource_manager->ClearAllMemory(ResourceProvider());
+ impl_thread_and_main_thread_blocked(&proxy_);
+ resource_manager->ClearAllMemory(resource_provider());
}
TEST_F(PrioritizedResourceTest,
@@ -565,8 +871,8 @@ TEST_F(PrioritizedResourceTest,
resource_manager->MaxMemoryNeededBytes());
DebugScopedSetImplThreadAndMainThreadBlocked
- impl_thread_and_main_thread_blocked(&proxy_);
- resource_manager->ClearAllMemory(ResourceProvider());
+ impl_thread_and_main_thread_blocked(&proxy_);
+ resource_manager->ClearAllMemory(resource_provider());
}
TEST_F(PrioritizedResourceTest,
@@ -617,8 +923,8 @@ TEST_F(PrioritizedResourceTest,
resource_manager->MemoryAboveCutoffBytes());
DebugScopedSetImplThreadAndMainThreadBlocked
- impl_thread_and_main_thread_blocked(&proxy_);
- resource_manager->ClearAllMemory(ResourceProvider());
+ impl_thread_and_main_thread_blocked(&proxy_);
+ resource_manager->ClearAllMemory(resource_provider());
}
TEST_F(PrioritizedResourceTest, RequestLateBackingsSorting) {
@@ -669,8 +975,8 @@ TEST_F(PrioritizedResourceTest, RequestLateBackingsSorting) {
EXPECT_FALSE(TextureBackingIsAbovePriorityCutoff(textures[i].get()));
DebugScopedSetImplThreadAndMainThreadBlocked
- impl_thread_and_main_thread_blocked(&proxy_);
- resource_manager->ClearAllMemory(ResourceProvider());
+ impl_thread_and_main_thread_blocked(&proxy_);
+ resource_manager->ClearAllMemory(resource_provider());
}
TEST_F(PrioritizedResourceTest, ClearUploadsToEvictedResources) {
@@ -695,7 +1001,7 @@ TEST_F(PrioritizedResourceTest, ClearUploadsToEvictedResources) {
ResourceUpdateQueue queue;
DebugScopedSetImplThreadAndMainThreadBlocked
- impl_thread_and_main_thread_blocked(&proxy_);
+ impl_thread_and_main_thread_blocked(&proxy_);
for (size_t i = 0; i < kMaxTextures; ++i) {
const ResourceUpdate upload = ResourceUpdate::Create(
textures[i].get(), NULL, gfx::Rect(), gfx::Rect(), gfx::Vector2d());
@@ -712,12 +1018,12 @@ TEST_F(PrioritizedResourceTest, ClearUploadsToEvictedResources) {
resource_manager->ReduceMemoryOnImplThread(
TexturesMemorySize(1),
PriorityCalculator::AllowEverythingCutoff(),
- ResourceProvider());
+ resource_provider());
queue.ClearUploadsToEvictedResources();
EXPECT_EQ(1u, queue.FullUploadSize());
resource_manager->ReduceMemoryOnImplThread(
- 0, PriorityCalculator::AllowEverythingCutoff(), ResourceProvider());
+ 0, PriorityCalculator::AllowEverythingCutoff(), resource_provider());
queue.ClearUploadsToEvictedResources();
EXPECT_EQ(0u, queue.FullUploadSize());
}
@@ -788,7 +1094,7 @@ TEST_F(PrioritizedResourceTest, UsageStatistics) {
// Push priorities to backings, and verify we see the new values.
{
DebugScopedSetImplThreadAndMainThreadBlocked
- impl_thread_and_main_thread_blocked(&proxy_);
+ impl_thread_and_main_thread_blocked(&proxy_);
resource_manager->PushTexturePrioritiesToBackings();
EXPECT_EQ(TexturesMemorySize(2), resource_manager->MemoryUseBytes());
EXPECT_EQ(TexturesMemorySize(3), resource_manager->MemoryVisibleBytes());
@@ -797,8 +1103,8 @@ TEST_F(PrioritizedResourceTest, UsageStatistics) {
}
DebugScopedSetImplThreadAndMainThreadBlocked
- impl_thread_and_main_thread_blocked(&proxy_);
- resource_manager->ClearAllMemory(ResourceProvider());
+ impl_thread_and_main_thread_blocked(&proxy_);
+ resource_manager->ClearAllMemory(resource_provider());
}
} // namespace
diff --git a/chromium/cc/resources/prioritized_tile_set_unittest.cc b/chromium/cc/resources/prioritized_tile_set_unittest.cc
index 7de1032523c..b51eb0063fb 100644
--- a/chromium/cc/resources/prioritized_tile_set_unittest.cc
+++ b/chromium/cc/resources/prioritized_tile_set_unittest.cc
@@ -57,22 +57,25 @@ class PrioritizedTileSetTest : public testing::Test {
CHECK(output_surface_->BindToClient(&output_surface_client_));
resource_provider_ =
- ResourceProvider::Create(output_surface_.get(), 0, false).Pass();
- tile_manager_.reset(new FakeTileManager(&tile_manager_client_,
- resource_provider_.get()));
+ ResourceProvider::Create(output_surface_.get(),
+ NULL,
+ 0,
+ false,
+ 1).Pass();
+ tile_manager_.reset(
+ new FakeTileManager(&tile_manager_client_, resource_provider_.get()));
picture_pile_ = FakePicturePileImpl::CreatePile();
}
scoped_refptr<Tile> CreateTile() {
- return make_scoped_refptr(new Tile(tile_manager_.get(),
- picture_pile_.get(),
- settings_.default_tile_size,
- gfx::Rect(),
- gfx::Rect(),
- 1.0,
- 0,
- 0,
- true));
+ return tile_manager_->CreateTile(picture_pile_.get(),
+ settings_.default_tile_size,
+ gfx::Rect(),
+ gfx::Rect(),
+ 1.0,
+ 0,
+ 0,
+ Tile::USE_LCD_TEXT);
}
private:
diff --git a/chromium/cc/resources/priority_calculator.cc b/chromium/cc/resources/priority_calculator.cc
index 4e828207ff1..fe5741c30e9 100644
--- a/chromium/cc/resources/priority_calculator.cc
+++ b/chromium/cc/resources/priority_calculator.cc
@@ -68,20 +68,11 @@ int PriorityCalculator::LingeringPriority(int previous_priority) {
std::max(kLingeringBasePriority, previous_priority + 1));
}
-namespace {
-int ManhattanDistance(gfx::Rect a, gfx::Rect b) {
- gfx::Rect c = gfx::UnionRects(a, b);
- int x = std::max(0, c.width() - a.width() - b.width() + 1);
- int y = std::max(0, c.height() - a.height() - b.height() + 1);
- return (x + y);
-}
-}
-
// static
int PriorityCalculator::PriorityFromDistance(gfx::Rect visible_rect,
gfx::Rect texture_rect,
bool draws_to_root_surface) {
- int distance = ManhattanDistance(visible_rect, texture_rect);
+ int distance = visible_rect.ManhattanInternalDistance(texture_rect);
if (!distance)
return VisiblePriority(draws_to_root_surface);
return std::min(kNotVisibleLimitPriority, kNotVisibleBasePriority + distance);
diff --git a/chromium/cc/resources/raster_worker_pool.cc b/chromium/cc/resources/raster_worker_pool.cc
index 5aaf0b66540..06fd18e62e0 100644
--- a/chromium/cc/resources/raster_worker_pool.cc
+++ b/chromium/cc/resources/raster_worker_pool.cc
@@ -7,7 +7,6 @@
#include "base/json/json_writer.h"
#include "base/metrics/histogram.h"
#include "base/values.h"
-#include "cc/debug/benchmark_instrumentation.h"
#include "cc/debug/devtools_instrumentation.h"
#include "cc/debug/traced_value.h"
#include "cc/resources/picture_pile_impl.h"
@@ -55,7 +54,6 @@ class RasterWorkerPoolTaskImpl : public internal::RasterWorkerPoolTask {
gfx::Rect content_rect,
float contents_scale,
RasterMode raster_mode,
- bool is_tile_in_pending_tree_now_bin,
TileResolution tile_resolution,
int layer_id,
const void* tile_id,
@@ -68,7 +66,6 @@ class RasterWorkerPoolTaskImpl : public internal::RasterWorkerPoolTask {
content_rect_(content_rect),
contents_scale_(contents_scale),
raster_mode_(raster_mode),
- is_tile_in_pending_tree_now_bin_(is_tile_in_pending_tree_now_bin),
tile_resolution_(tile_resolution),
layer_id_(layer_id),
tile_id_(tile_id),
@@ -90,14 +87,12 @@ class RasterWorkerPoolTaskImpl : public internal::RasterWorkerPoolTask {
DCHECK(picture_clone);
- base::TimeTicks start_time = rendering_stats_->StartRecording();
- picture_clone->AnalyzeInRect(content_rect_, contents_scale_, &analysis_);
- base::TimeDelta duration = rendering_stats_->EndRecording(start_time);
+ picture_clone->AnalyzeInRect(
+ content_rect_, contents_scale_, &analysis_, rendering_stats_);
// Record the solid color prediction.
UMA_HISTOGRAM_BOOLEAN("Renderer4.SolidColorTilesAnalyzed",
analysis_.is_solid_color);
- rendering_stats_->AddAnalysisResult(duration, analysis_.is_solid_color);
// Clear the flag if we're not using the estimator.
analysis_.is_solid_color &= kUseColorEstimator;
@@ -108,9 +103,8 @@ class RasterWorkerPoolTaskImpl : public internal::RasterWorkerPoolTask {
gfx::Size size,
int stride) {
TRACE_EVENT2(
- benchmark_instrumentation::kCategory,
- benchmark_instrumentation::kRunRasterOnThread,
- benchmark_instrumentation::kData,
+ "cc", "RasterWorkerPoolTaskImpl::RunRasterOnThread",
+ "data",
TracedValue::FromValue(DataAsValue().release()),
"raster_mode",
TracedValue::FromValue(RasterModeAsValue(raster_mode_).release()));
@@ -147,6 +141,7 @@ class RasterWorkerPoolTaskImpl : public internal::RasterWorkerPoolTask {
break;
case LUMINANCE_8:
case RGB_565:
+ case ETC1:
NOTREACHED();
break;
}
@@ -170,25 +165,30 @@ class RasterWorkerPoolTaskImpl : public internal::RasterWorkerPoolTask {
canvas.setDrawFilter(draw_filter.get());
- if (rendering_stats_->record_rendering_stats()) {
- PicturePileImpl::RasterStats raster_stats;
+ base::TimeDelta prev_rasterize_time =
+ rendering_stats_->impl_thread_rendering_stats().rasterize_time;
+
+ // Only record rasterization time for highres tiles, because
+ // lowres tiles are not required for activation and therefore
+ // introduce noise in the measurement (sometimes they get rasterized
+ // before we draw and sometimes they aren't)
+ if (tile_resolution_ == HIGH_RESOLUTION) {
picture_clone->RasterToBitmap(
- &canvas, content_rect_, contents_scale_, &raster_stats);
- rendering_stats_->AddRaster(
- raster_stats.total_rasterize_time,
- raster_stats.best_rasterize_time,
- raster_stats.total_pixels_rasterized,
- is_tile_in_pending_tree_now_bin_);
+ &canvas, content_rect_, contents_scale_, rendering_stats_);
+ } else {
+ picture_clone->RasterToBitmap(
+ &canvas, content_rect_, contents_scale_, NULL);
+ }
+ if (rendering_stats_->record_rendering_stats()) {
+ base::TimeDelta current_rasterize_time =
+ rendering_stats_->impl_thread_rendering_stats().rasterize_time;
HISTOGRAM_CUSTOM_COUNTS(
"Renderer4.PictureRasterTimeUS",
- raster_stats.total_rasterize_time.InMicroseconds(),
+ (current_rasterize_time - prev_rasterize_time).InMicroseconds(),
0,
100000,
100);
- } else {
- picture_clone->RasterToBitmap(
- &canvas, content_rect_, contents_scale_, NULL);
}
ChangeBitmapConfigIfNeeded(bitmap, buffer);
@@ -216,8 +216,6 @@ class RasterWorkerPoolTaskImpl : public internal::RasterWorkerPoolTask {
scoped_ptr<base::Value> DataAsValue() const {
scoped_ptr<base::DictionaryValue> res(new base::DictionaryValue());
res->Set("tile_id", TracedValue::CreateIDRef(tile_id_).release());
- res->SetBoolean("is_tile_in_pending_tree_now_bin",
- is_tile_in_pending_tree_now_bin_);
res->Set("resolution", TileResolutionAsValue(tile_resolution_).release());
res->SetInteger("source_frame_number", source_frame_number_);
res->SetInteger("layer_id", layer_id_);
@@ -227,8 +225,7 @@ class RasterWorkerPoolTaskImpl : public internal::RasterWorkerPoolTask {
void ChangeBitmapConfigIfNeeded(const SkBitmap& bitmap,
void* buffer) {
TRACE_EVENT0("cc", "RasterWorkerPoolTaskImpl::ChangeBitmapConfigIfNeeded");
- SkBitmap::Config config = SkBitmapConfigFromFormat(
- resource()->format());
+ SkBitmap::Config config = SkBitmapConfig(resource()->format());
if (bitmap.getConfig() != config) {
SkBitmap bitmap_dest;
IdentityAllocator allocator(buffer);
@@ -244,7 +241,6 @@ class RasterWorkerPoolTaskImpl : public internal::RasterWorkerPoolTask {
gfx::Rect content_rect_;
float contents_scale_;
RasterMode raster_mode_;
- bool is_tile_in_pending_tree_now_bin_;
TileResolution tile_resolution_;
int layer_id_;
const void* tile_id_;
@@ -271,10 +267,7 @@ class ImageDecodeWorkerPoolTaskImpl : public internal::WorkerPoolTask {
TRACE_EVENT0("cc", "ImageDecodeWorkerPoolTaskImpl::RunOnWorkerThread");
devtools_instrumentation::ScopedImageDecodeTask image_decode_task(
pixel_ref_.get());
- base::TimeTicks start_time = rendering_stats_->StartRecording();
pixel_ref_->Decode();
- base::TimeDelta duration = rendering_stats_->EndRecording(start_time);
- rendering_stats_->AddDeferredImageDecode(duration);
}
virtual void CompleteOnOriginThread() OVERRIDE {
reply_.Run(!HasFinishedRunning());
@@ -434,7 +427,6 @@ RasterWorkerPool::RasterTask RasterWorkerPool::CreateRasterTask(
gfx::Rect content_rect,
float contents_scale,
RasterMode raster_mode,
- bool is_tile_in_pending_tree_now_bin,
TileResolution tile_resolution,
int layer_id,
const void* tile_id,
@@ -448,7 +440,6 @@ RasterWorkerPool::RasterTask RasterWorkerPool::CreateRasterTask(
content_rect,
contents_scale,
raster_mode,
- is_tile_in_pending_tree_now_bin,
tile_resolution,
layer_id,
tile_id,
diff --git a/chromium/cc/resources/raster_worker_pool.h b/chromium/cc/resources/raster_worker_pool.h
index b12a1b43c23..fac2fd845ce 100644
--- a/chromium/cc/resources/raster_worker_pool.h
+++ b/chromium/cc/resources/raster_worker_pool.h
@@ -22,10 +22,6 @@ class LazyPixelRef;
}
namespace cc {
-class PicturePileImpl;
-class PixelBufferRasterWorkerPool;
-class ResourceProvider;
-
namespace internal {
class CC_EXPORT RasterWorkerPoolTask
@@ -186,6 +182,9 @@ class CC_EXPORT RasterWorkerPool : public WorkerPool {
// even if they later get canceled by another call to ScheduleTasks().
virtual void ScheduleTasks(RasterTask::Queue* queue) = 0;
+ // Returns the target that needs to be used for raster task resources.
+ virtual GLenum GetResourceTarget() const = 0;
+
// Returns the format that needs to be used for raster task resources.
virtual ResourceFormat GetResourceFormat() const = 0;
@@ -196,7 +195,6 @@ class CC_EXPORT RasterWorkerPool : public WorkerPool {
gfx::Rect content_rect,
float contents_scale,
RasterMode raster_mode,
- bool is_tile_in_pending_tree_now_bin,
TileResolution tile_resolution,
int layer_id,
const void* tile_id,
@@ -273,10 +271,10 @@ class CC_EXPORT RasterWorkerPool : public WorkerPool {
RasterTask::Queue::TaskVector raster_tasks_;
RasterTask::Queue::TaskSet raster_tasks_required_for_activation_;
- base::WeakPtrFactory<RasterWorkerPool> weak_ptr_factory_;
scoped_refptr<internal::WorkerPoolTask> raster_finished_task_;
scoped_refptr<internal::WorkerPoolTask>
raster_required_for_activation_finished_task_;
+ base::WeakPtrFactory<RasterWorkerPool> weak_ptr_factory_;
};
} // namespace cc
diff --git a/chromium/cc/resources/raster_worker_pool_perftest.cc b/chromium/cc/resources/raster_worker_pool_perftest.cc
index cec9c4820d1..8b9c8e0b5f5 100644
--- a/chromium/cc/resources/raster_worker_pool_perftest.cc
+++ b/chromium/cc/resources/raster_worker_pool_perftest.cc
@@ -40,6 +40,10 @@ class PerfRasterWorkerPool : public RasterWorkerPool {
virtual void ScheduleTasks(RasterTask::Queue* queue) OVERRIDE {
NOTREACHED();
}
+ virtual GLenum GetResourceTarget() const OVERRIDE {
+ NOTREACHED();
+ return GL_TEXTURE_2D;
+ }
virtual ResourceFormat GetResourceFormat() const OVERRIDE {
NOTREACHED();
return RGBA_8888;
@@ -164,7 +168,6 @@ class RasterWorkerPoolPerfTest : public testing::Test {
gfx::Rect(),
1.0,
HIGH_QUALITY_RASTER_MODE,
- false,
TileResolution(),
1,
NULL,
diff --git a/chromium/cc/resources/raster_worker_pool_unittest.cc b/chromium/cc/resources/raster_worker_pool_unittest.cc
index 61cb324f772..716edf6c526 100644
--- a/chromium/cc/resources/raster_worker_pool_unittest.cc
+++ b/chromium/cc/resources/raster_worker_pool_unittest.cc
@@ -7,7 +7,6 @@
#include <limits>
#include <vector>
-#include "cc/debug/test_web_graphics_context_3d.h"
#include "cc/resources/image_raster_worker_pool.h"
#include "cc/resources/picture_pile.h"
#include "cc/resources/picture_pile_impl.h"
@@ -16,6 +15,7 @@
#include "cc/resources/scoped_resource.h"
#include "cc/test/fake_output_surface.h"
#include "cc/test/fake_output_surface_client.h"
+#include "cc/test/test_web_graphics_context_3d.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace cc {
@@ -67,8 +67,8 @@ class RasterWorkerPoolTest : public testing::Test,
output_surface_ = FakeOutputSurface::Create3d(context_provider_).Pass();
CHECK(output_surface_->BindToClient(&output_surface_client_));
- resource_provider_ =
- ResourceProvider::Create(output_surface_.get(), 0, false).Pass();
+ resource_provider_ = ResourceProvider::Create(
+ output_surface_.get(), NULL, 0, false, 1).Pass();
}
virtual ~RasterWorkerPoolTest() {
resource_provider_.reset();
@@ -104,7 +104,7 @@ class RasterWorkerPoolTest : public testing::Test,
void RunTest(bool use_map_image) {
if (use_map_image) {
raster_worker_pool_ = ImageRasterWorkerPool::Create(
- resource_provider(), 1);
+ resource_provider(), 1, GL_TEXTURE_2D);
} else {
raster_worker_pool_ =
PixelBufferRasterWorkerPool::Create(
@@ -159,7 +159,7 @@ class RasterWorkerPoolTest : public testing::Test,
const gfx::Size size(1, 1);
scoped_ptr<ScopedResource> resource(
- ScopedResource::create(resource_provider()));
+ ScopedResource::Create(resource_provider()));
resource->Allocate(size, ResourceProvider::TextureUsageAny, RGBA_8888);
const Resource* const_resource = resource.get();
diff --git a/chromium/cc/resources/resource.cc b/chromium/cc/resources/resource.cc
index c97db7fb872..9bbcd4f498b 100644
--- a/chromium/cc/resources/resource.cc
+++ b/chromium/cc/resources/resource.cc
@@ -13,8 +13,5 @@ size_t Resource::bytes() const {
return MemorySizeBytes(size_, format_);
}
-size_t Resource::MemorySizeBytes(gfx::Size size, ResourceFormat format) {
- return ResourceProvider::BytesPerPixel(format) * size.width() * size.height();
-}
} // namespace cc
diff --git a/chromium/cc/resources/resource.h b/chromium/cc/resources/resource.h
index d2d104c1370..e9dd393a6a4 100644
--- a/chromium/cc/resources/resource.h
+++ b/chromium/cc/resources/resource.h
@@ -25,7 +25,10 @@ class CC_EXPORT Resource {
ResourceFormat format() const { return format_; }
size_t bytes() const;
- static size_t MemorySizeBytes(gfx::Size size, ResourceFormat format);
+ inline static size_t MemorySizeBytes(gfx::Size size, ResourceFormat format) {
+ DCHECK_EQ(0u, (BitsPerPixel(format) * size.width() * size.height()) % 8);
+ return (BitsPerPixel(format) * size.width() * size.height()) / 8;
+ }
protected:
void set_id(ResourceProvider::ResourceId id) { id_ = id; }
diff --git a/chromium/cc/resources/resource_format.cc b/chromium/cc/resources/resource_format.cc
index 5ea3df12598..35617174cb5 100644
--- a/chromium/cc/resources/resource_format.cc
+++ b/chromium/cc/resources/resource_format.cc
@@ -6,13 +6,14 @@
namespace cc {
-SkBitmap::Config SkBitmapConfigFromFormat(ResourceFormat format) {
+SkBitmap::Config SkBitmapConfig(ResourceFormat format) {
switch (format) {
case RGBA_4444:
return SkBitmap::kARGB_4444_Config;
case RGBA_8888:
case BGRA_8888:
return SkBitmap::kARGB_8888_Config;
+ case ETC1:
case LUMINANCE_8:
case RGB_565:
NOTREACHED();
diff --git a/chromium/cc/resources/resource_format.h b/chromium/cc/resources/resource_format.h
index ef83cc02eb7..54061394ff7 100644
--- a/chromium/cc/resources/resource_format.h
+++ b/chromium/cc/resources/resource_format.h
@@ -10,16 +10,18 @@
namespace cc {
+// Keep in sync with arrays below.
enum ResourceFormat {
RGBA_8888,
RGBA_4444,
BGRA_8888,
LUMINANCE_8,
RGB_565,
- RESOURCE_FORMAT_MAX = RGB_565,
+ ETC1,
+ RESOURCE_FORMAT_MAX = ETC1,
};
-SkBitmap::Config SkBitmapConfigFromFormat(ResourceFormat format);
+SkBitmap::Config SkBitmapConfig(ResourceFormat format);
} // namespace cc
diff --git a/chromium/cc/resources/resource_pool.cc b/chromium/cc/resources/resource_pool.cc
index cef86ded178..6abfd7c4a3d 100644
--- a/chromium/cc/resources/resource_pool.cc
+++ b/chromium/cc/resources/resource_pool.cc
@@ -5,31 +5,16 @@
#include "cc/resources/resource_pool.h"
#include "cc/resources/resource_provider.h"
+#include "cc/resources/scoped_resource.h"
namespace cc {
-ResourcePool::Resource::Resource(cc::ResourceProvider* resource_provider,
- gfx::Size size,
- ResourceFormat format)
- : cc::Resource(resource_provider->CreateManagedResource(
- size,
- GL_CLAMP_TO_EDGE,
- ResourceProvider::TextureUsageAny,
- format),
- size,
- format),
- resource_provider_(resource_provider) {
- DCHECK(id());
-}
-
-ResourcePool::Resource::~Resource() {
- DCHECK(id());
- DCHECK(resource_provider_);
- resource_provider_->DeleteResource(id());
-}
-
-ResourcePool::ResourcePool(ResourceProvider* resource_provider)
+ResourcePool::ResourcePool(ResourceProvider* resource_provider,
+ GLenum target,
+ ResourceFormat format)
: resource_provider_(resource_provider),
+ target_(target),
+ format_(format),
max_memory_usage_bytes_(0),
max_unused_memory_usage_bytes_(0),
max_resource_count_(0),
@@ -39,21 +24,26 @@ ResourcePool::ResourcePool(ResourceProvider* resource_provider)
}
ResourcePool::~ResourcePool() {
+ while (!busy_resources_.empty()) {
+ DidFinishUsingResource(busy_resources_.front());
+ busy_resources_.pop_front();
+ }
+
SetResourceUsageLimits(0, 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_);
}
-scoped_ptr<ResourcePool::Resource> ResourcePool::AcquireResource(
- gfx::Size size, ResourceFormat format) {
+scoped_ptr<ScopedResource> ResourcePool::AcquireResource(gfx::Size size) {
for (ResourceList::iterator it = unused_resources_.begin();
it != unused_resources_.end(); ++it) {
- Resource* resource = *it;
+ ScopedResource* resource = *it;
+ DCHECK(resource_provider_->CanLockForWrite(resource->id()));
- if (!resource_provider_->CanLockForWrite(resource->id()))
- continue;
if (resource->size() != size)
continue;
- if (resource->format() != format)
- continue;
unused_resources_.erase(it);
unused_memory_usage_bytes_ -= resource->bytes();
@@ -61,7 +51,9 @@ scoped_ptr<ResourcePool::Resource> ResourcePool::AcquireResource(
}
// Create new resource.
- Resource* resource = new Resource(resource_provider_, size, format);
+ scoped_ptr<ScopedResource> resource =
+ ScopedResource::Create(resource_provider_);
+ resource->AllocateManaged(size, target_, format_);
// Extend all read locks on all resources until the resource is
// finished being used, such that we know when resources are
@@ -70,19 +62,11 @@ scoped_ptr<ResourcePool::Resource> ResourcePool::AcquireResource(
memory_usage_bytes_ += resource->bytes();
++resource_count_;
- return make_scoped_ptr(resource);
+ return resource.Pass();
}
-void ResourcePool::ReleaseResource(
- scoped_ptr<ResourcePool::Resource> resource) {
- if (ResourceUsageTooHigh()) {
- memory_usage_bytes_ -= resource->bytes();
- --resource_count_;
- return;
- }
-
- unused_memory_usage_bytes_ += resource->bytes();
- unused_resources_.push_back(resource.release());
+void ResourcePool::ReleaseResource(scoped_ptr<ScopedResource> resource) {
+ busy_resources_.push_back(resource.release());
}
void ResourcePool::SetResourceUsageLimits(
@@ -108,7 +92,7 @@ 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.
- Resource* resource = unused_resources_.front();
+ ScopedResource* resource = unused_resources_.front();
unused_resources_.pop_front();
memory_usage_bytes_ -= resource->bytes();
unused_memory_usage_bytes_ -= resource->bytes();
@@ -127,4 +111,24 @@ bool ResourcePool::ResourceUsageTooHigh() {
return false;
}
+void ResourcePool::CheckBusyResources() {
+ ResourceList::iterator it = busy_resources_.begin();
+
+ while (it != busy_resources_.end()) {
+ ScopedResource* resource = *it;
+
+ if (resource_provider_->CanLockForWrite(resource->id())) {
+ DidFinishUsingResource(resource);
+ it = busy_resources_.erase(it);
+ } else {
+ ++it;
+ }
+ }
+}
+
+void ResourcePool::DidFinishUsingResource(ScopedResource* resource) {
+ unused_memory_usage_bytes_ += resource->bytes();
+ unused_resources_.push_back(resource);
+}
+
} // namespace cc
diff --git a/chromium/cc/resources/resource_pool.h b/chromium/cc/resources/resource_pool.h
index 21bbb0a70d0..3c6b23f642a 100644
--- a/chromium/cc/resources/resource_pool.h
+++ b/chromium/cc/resources/resource_pool.h
@@ -14,37 +14,29 @@
#include "cc/resources/resource_format.h"
namespace cc {
+class ScopedResource;
class CC_EXPORT ResourcePool {
public:
- class CC_EXPORT Resource : public cc::Resource {
- public:
- Resource(ResourceProvider* resource_provider,
- gfx::Size size,
- ResourceFormat format);
- ~Resource();
-
- private:
- ResourceProvider* resource_provider_;
-
- DISALLOW_COPY_AND_ASSIGN(Resource);
- };
-
- static scoped_ptr<ResourcePool> Create(ResourceProvider* resource_provider) {
- return make_scoped_ptr(new ResourcePool(resource_provider));
+ static scoped_ptr<ResourcePool> Create(ResourceProvider* resource_provider,
+ GLenum target,
+ ResourceFormat format) {
+ return make_scoped_ptr(new ResourcePool(resource_provider,
+ target,
+ format));
}
virtual ~ResourcePool();
- scoped_ptr<ResourcePool::Resource> AcquireResource(
- gfx::Size size, ResourceFormat format);
- void ReleaseResource(scoped_ptr<ResourcePool::Resource>);
+ scoped_ptr<ScopedResource> AcquireResource(gfx::Size size);
+ void ReleaseResource(scoped_ptr<ScopedResource>);
void SetResourceUsageLimits(size_t max_memory_usage_bytes,
size_t max_unused_memory_usage_bytes,
size_t max_resource_count);
void ReduceResourceUsage();
+ void CheckBusyResources();
size_t total_memory_usage_bytes() const {
return memory_usage_bytes_;
@@ -57,12 +49,18 @@ class CC_EXPORT ResourcePool {
}
protected:
- explicit ResourcePool(ResourceProvider* resource_provider);
+ ResourcePool(ResourceProvider* resource_provider,
+ GLenum target,
+ ResourceFormat format);
bool ResourceUsageTooHigh();
private:
+ void DidFinishUsingResource(ScopedResource* resource);
+
ResourceProvider* resource_provider_;
+ const GLenum target_;
+ const ResourceFormat format_;
size_t max_memory_usage_bytes_;
size_t max_unused_memory_usage_bytes_;
size_t max_resource_count_;
@@ -70,8 +68,9 @@ class CC_EXPORT ResourcePool {
size_t unused_memory_usage_bytes_;
size_t resource_count_;
- typedef std::list<Resource*> ResourceList;
+ typedef std::list<ScopedResource*> ResourceList;
ResourceList unused_resources_;
+ ResourceList busy_resources_;
DISALLOW_COPY_AND_ASSIGN(ResourcePool);
};
diff --git a/chromium/cc/resources/resource_provider.cc b/chromium/cc/resources/resource_provider.cc
index ee761d17564..1331ca2f1cf 100644
--- a/chromium/cc/resources/resource_provider.cc
+++ b/chromium/cc/resources/resource_provider.cc
@@ -8,6 +8,7 @@
#include <limits>
#include "base/containers/hash_tables.h"
+#include "base/debug/trace_event.h"
#include "base/stl_util.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
@@ -15,19 +16,42 @@
#include "cc/output/gl_renderer.h" // For the GLC() macro.
#include "cc/resources/platform_color.h"
#include "cc/resources/returned_resource.h"
+#include "cc/resources/shared_bitmap_manager.h"
#include "cc/resources/transferable_resource.h"
#include "cc/scheduler/texture_uploader.h"
#include "gpu/GLES2/gl2extchromium.h"
-#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/khronos/GLES2/gl2ext.h"
+#include "ui/gfx/frame_time.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/vector2d.h"
-using WebKit::WebGraphicsContext3D;
+using gpu::gles2::GLES2Interface;
namespace cc {
+class IdAllocator {
+ public:
+ virtual ~IdAllocator() {}
+
+ virtual GLuint NextId() = 0;
+
+ protected:
+ IdAllocator(GLES2Interface* gl, size_t id_allocation_chunk_size)
+ : gl_(gl),
+ id_allocation_chunk_size_(id_allocation_chunk_size),
+ ids_(new GLuint[id_allocation_chunk_size]),
+ next_id_index_(id_allocation_chunk_size) {
+ DCHECK(id_allocation_chunk_size_);
+ }
+
+ GLES2Interface* gl_;
+ const size_t id_allocation_chunk_size_;
+ scoped_ptr<GLuint[]> ids_;
+ size_t next_id_index_;
+};
+
namespace {
// Measured in seconds.
@@ -45,6 +69,7 @@ GLenum TextureToStorageFormat(ResourceFormat format) {
case RGBA_4444:
case LUMINANCE_8:
case RGB_565:
+ case ETC1:
NOTREACHED();
break;
}
@@ -60,6 +85,7 @@ bool IsFormatSupportedForStorage(ResourceFormat format) {
case RGBA_4444:
case LUMINANCE_8:
case RGB_565:
+ case ETC1:
return false;
}
return false;
@@ -67,25 +93,72 @@ bool IsFormatSupportedForStorage(ResourceFormat format) {
class ScopedSetActiveTexture {
public:
- ScopedSetActiveTexture(WebGraphicsContext3D* context3d, GLenum unit)
- : context3d_(context3d), unit_(unit) {
- DCHECK_EQ(GL_TEXTURE0, ResourceProvider::GetActiveTextureUnit(context3d_));
+ ScopedSetActiveTexture(GLES2Interface* gl, GLenum unit)
+ : gl_(gl), unit_(unit) {
+ DCHECK_EQ(GL_TEXTURE0, ResourceProvider::GetActiveTextureUnit(gl_));
if (unit_ != GL_TEXTURE0)
- GLC(context3d_, context3d_->activeTexture(unit_));
+ GLC(gl_, gl_->ActiveTexture(unit_));
}
~ScopedSetActiveTexture() {
// Active unit being GL_TEXTURE0 is effectively the ground state.
if (unit_ != GL_TEXTURE0)
- GLC(context3d_, context3d_->activeTexture(GL_TEXTURE0));
+ GLC(gl_, gl_->ActiveTexture(GL_TEXTURE0));
}
private:
- WebGraphicsContext3D* context3d_;
+ GLES2Interface* gl_;
GLenum unit_;
};
+class TextureIdAllocator : public IdAllocator {
+ public:
+ TextureIdAllocator(GLES2Interface* gl,
+ size_t texture_id_allocation_chunk_size)
+ : IdAllocator(gl, texture_id_allocation_chunk_size) {}
+ virtual ~TextureIdAllocator() {
+ gl_->DeleteTextures(id_allocation_chunk_size_ - next_id_index_,
+ ids_.get() + next_id_index_);
+ }
+
+ // Overridden from IdAllocator:
+ virtual GLuint NextId() OVERRIDE {
+ if (next_id_index_ == id_allocation_chunk_size_) {
+ gl_->GenTextures(id_allocation_chunk_size_, ids_.get());
+ next_id_index_ = 0;
+ }
+
+ return ids_[next_id_index_++];
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TextureIdAllocator);
+};
+
+class BufferIdAllocator : public IdAllocator {
+ public:
+ BufferIdAllocator(GLES2Interface* gl, size_t buffer_id_allocation_chunk_size)
+ : IdAllocator(gl, buffer_id_allocation_chunk_size) {}
+ virtual ~BufferIdAllocator() {
+ gl_->DeleteBuffers(id_allocation_chunk_size_ - next_id_index_,
+ ids_.get() + next_id_index_);
+ }
+
+ // Overridden from IdAllocator:
+ virtual GLuint NextId() OVERRIDE {
+ if (next_id_index_ == id_allocation_chunk_size_) {
+ gl_->GenBuffers(id_allocation_chunk_size_, ids_.get());
+ next_id_index_ = 0;
+ }
+
+ return ids_[next_id_index_++];
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BufferIdAllocator);
+};
+
} // namespace
ResourceProvider::Resource::Resource()
@@ -107,21 +180,25 @@ ResourceProvider::Resource::Resource()
enable_read_lock_fences(false),
read_lock_fence(NULL),
size(),
+ target(0),
original_filter(0),
filter(0),
- target(0),
image_id(0),
+ bound_image_id(0),
+ dirty_image(false),
texture_pool(0),
wrap_mode(0),
lost(false),
hint(TextureUsageAny),
type(static_cast<ResourceType>(0)),
- format(RGBA_8888) {}
+ format(RGBA_8888),
+ shared_bitmap(NULL) {}
ResourceProvider::Resource::~Resource() {}
-ResourceProvider::Resource::Resource(unsigned texture_id,
+ResourceProvider::Resource::Resource(GLuint texture_id,
gfx::Size size,
+ GLenum target,
GLenum filter,
GLenum texture_pool,
GLint wrap_mode,
@@ -145,20 +222,24 @@ ResourceProvider::Resource::Resource(unsigned texture_id,
enable_read_lock_fences(false),
read_lock_fence(NULL),
size(size),
+ target(target),
original_filter(filter),
filter(filter),
- target(0),
image_id(0),
+ bound_image_id(0),
+ dirty_image(false),
texture_pool(texture_pool),
wrap_mode(wrap_mode),
lost(false),
hint(hint),
type(GLTexture),
- format(format) {
+ format(format),
+ shared_bitmap(NULL) {
DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT);
}
ResourceProvider::Resource::Resource(uint8_t* pixels,
+ SharedBitmap* bitmap,
gfx::Size size,
GLenum filter,
GLint wrap_mode)
@@ -180,34 +261,41 @@ ResourceProvider::Resource::Resource(uint8_t* pixels,
enable_read_lock_fences(false),
read_lock_fence(NULL),
size(size),
+ target(0),
original_filter(filter),
filter(filter),
- target(0),
image_id(0),
+ bound_image_id(0),
+ dirty_image(false),
texture_pool(0),
wrap_mode(wrap_mode),
lost(false),
hint(TextureUsageAny),
type(Bitmap),
- format(RGBA_8888) {
+ format(RGBA_8888),
+ shared_bitmap(bitmap) {
DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT);
}
-ResourceProvider::Child::Child() {}
+ResourceProvider::Child::Child() : marked_for_deletion(false) {}
ResourceProvider::Child::~Child() {}
scoped_ptr<ResourceProvider> ResourceProvider::Create(
OutputSurface* output_surface,
+ SharedBitmapManager* shared_bitmap_manager,
int highp_threshold_min,
- bool use_rgba_4444_texture_format) {
+ bool use_rgba_4444_texture_format,
+ size_t id_allocation_chunk_size) {
scoped_ptr<ResourceProvider> resource_provider(
new ResourceProvider(output_surface,
+ shared_bitmap_manager,
highp_threshold_min,
- use_rgba_4444_texture_format));
+ use_rgba_4444_texture_format,
+ id_allocation_chunk_size));
bool success = false;
- if (resource_provider->Context3d()) {
+ if (resource_provider->ContextGL()) {
success = resource_provider->InitializeGL();
} else {
resource_provider->InitializeSoftware();
@@ -223,7 +311,7 @@ scoped_ptr<ResourceProvider> ResourceProvider::Create(
ResourceProvider::~ResourceProvider() {
while (!children_.empty())
- DestroyChild(children_.begin()->first);
+ DestroyChildInternal(children_.begin(), ForShutdown);
while (!resources_.empty())
DeleteResourceInternal(resources_.begin(), ForShutdown);
@@ -250,13 +338,14 @@ ResourceProvider::ResourceId ResourceProvider::CreateResource(
switch (default_resource_type_) {
case GLTexture:
return CreateGLTexture(size,
+ GL_TEXTURE_2D,
GL_TEXTURE_POOL_UNMANAGED_CHROMIUM,
wrap_mode,
hint,
format);
case Bitmap:
DCHECK_EQ(RGBA_8888, format);
- return CreateBitmap(size);
+ return CreateBitmap(size, wrap_mode);
case InvalidType:
break;
}
@@ -267,6 +356,7 @@ ResourceProvider::ResourceId ResourceProvider::CreateResource(
ResourceProvider::ResourceId ResourceProvider::CreateManagedResource(
gfx::Size size,
+ GLenum target,
GLint wrap_mode,
TextureUsageHint hint,
ResourceFormat format) {
@@ -274,13 +364,14 @@ ResourceProvider::ResourceId ResourceProvider::CreateManagedResource(
switch (default_resource_type_) {
case GLTexture:
return CreateGLTexture(size,
+ target,
GL_TEXTURE_POOL_MANAGED_CHROMIUM,
wrap_mode,
hint,
format);
case Bitmap:
DCHECK_EQ(RGBA_8888, format);
- return CreateBitmap(size);
+ return CreateBitmap(size, wrap_mode);
case InvalidType:
break;
}
@@ -291,6 +382,7 @@ ResourceProvider::ResourceId ResourceProvider::CreateManagedResource(
ResourceProvider::ResourceId ResourceProvider::CreateGLTexture(
gfx::Size size,
+ GLenum target,
GLenum texture_pool,
GLint wrap_mode,
TextureUsageHint hint,
@@ -300,19 +392,30 @@ ResourceProvider::ResourceId ResourceProvider::CreateGLTexture(
DCHECK(thread_checker_.CalledOnValidThread());
ResourceId id = next_id_++;
- Resource resource(0, size, GL_LINEAR, texture_pool, wrap_mode, hint, format);
+ Resource resource(
+ 0, size, target, GL_LINEAR, texture_pool, wrap_mode, hint, format);
resource.allocated = false;
resources_[id] = resource;
return id;
}
-ResourceProvider::ResourceId ResourceProvider::CreateBitmap(gfx::Size size) {
+ResourceProvider::ResourceId ResourceProvider::CreateBitmap(
+ gfx::Size size, GLint wrap_mode) {
DCHECK(thread_checker_.CalledOnValidThread());
- uint8_t* pixels = new uint8_t[4 * size.GetArea()];
+ scoped_ptr<SharedBitmap> bitmap;
+ if (shared_bitmap_manager_)
+ bitmap = shared_bitmap_manager_->AllocateSharedBitmap(size);
+
+ uint8_t* pixels;
+ if (bitmap)
+ pixels = bitmap->pixels();
+ else
+ pixels = new uint8_t[4 * size.GetArea()];
ResourceId id = next_id_++;
- Resource resource(pixels, size, GL_LINEAR, GL_CLAMP_TO_EDGE);
+ Resource resource(
+ pixels, bitmap.release(), size, GL_LINEAR, wrap_mode);
resource.allocated = true;
resources_[id] = resource;
return id;
@@ -320,25 +423,24 @@ ResourceProvider::ResourceId ResourceProvider::CreateBitmap(gfx::Size size) {
ResourceProvider::ResourceId
ResourceProvider::CreateResourceFromExternalTexture(
- unsigned texture_target,
- unsigned texture_id) {
+ GLuint texture_target,
+ GLuint texture_id) {
DCHECK(thread_checker_.CalledOnValidThread());
- WebGraphicsContext3D* context3d = Context3d();
- DCHECK(context3d);
- GLC(context3d, context3d->bindTexture(texture_target, texture_id));
- GLC(context3d, context3d->texParameteri(
- texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
- GLC(context3d, context3d->texParameteri(
- texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
- GLC(context3d, context3d->texParameteri(
- texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
- GLC(context3d, context3d->texParameteri(
- texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
+ GLES2Interface* gl = ContextGL();
+ DCHECK(gl);
+ GLC(gl, gl->BindTexture(texture_target, texture_id));
+ GLC(gl, gl->TexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
+ GLC(gl, gl->TexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
+ GLC(gl,
+ gl->TexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
+ GLC(gl,
+ gl->TexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
ResourceId id = next_id_++;
Resource resource(texture_id,
gfx::Size(),
+ texture_target,
GL_LINEAR,
0,
GL_CLAMP_TO_EDGE,
@@ -361,6 +463,7 @@ ResourceProvider::ResourceId ResourceProvider::CreateResourceFromTextureMailbox(
if (mailbox.IsTexture()) {
resource = Resource(0,
gfx::Size(),
+ mailbox.target(),
GL_LINEAR,
0,
GL_CLAMP_TO_EDGE,
@@ -371,8 +474,16 @@ ResourceProvider::ResourceId ResourceProvider::CreateResourceFromTextureMailbox(
base::SharedMemory* shared_memory = mailbox.shared_memory();
DCHECK(shared_memory->memory());
uint8_t* pixels = reinterpret_cast<uint8_t*>(shared_memory->memory());
- resource = Resource(
- pixels, mailbox.shared_memory_size(), GL_LINEAR, GL_CLAMP_TO_EDGE);
+ scoped_ptr<SharedBitmap> shared_bitmap;
+ if (shared_bitmap_manager_) {
+ shared_bitmap =
+ shared_bitmap_manager_->GetBitmapForSharedMemory(shared_memory);
+ }
+ resource = Resource(pixels,
+ shared_bitmap.release(),
+ mailbox.shared_memory_size(),
+ GL_LINEAR,
+ GL_CLAMP_TO_EDGE);
}
resource.external = true;
resource.allocated = true;
@@ -403,53 +514,61 @@ void ResourceProvider::DeleteResource(ResourceId id) {
void ResourceProvider::DeleteResourceInternal(ResourceMap::iterator it,
DeleteStyle style) {
+ TRACE_EVENT0("cc", "ResourceProvider::DeleteResourceInternal");
Resource* resource = &it->second;
- bool lost_resource = lost_output_surface_ || resource->lost;
+ bool lost_resource = resource->lost;
DCHECK(resource->exported_count == 0 || style != Normal);
if (style == ForShutdown && resource->exported_count > 0)
lost_resource = true;
if (resource->image_id) {
- WebGraphicsContext3D* context3d = Context3d();
- DCHECK(context3d);
- GLC(context3d, context3d->destroyImageCHROMIUM(resource->image_id));
+ GLES2Interface* gl = ContextGL();
+ DCHECK(gl);
+ GLC(gl, gl->DestroyImageCHROMIUM(resource->image_id));
}
if (resource->gl_id && !resource->external) {
- WebGraphicsContext3D* context3d = Context3d();
- DCHECK(context3d);
- GLC(context3d, context3d->deleteTexture(resource->gl_id));
+ GLES2Interface* gl = ContextGL();
+ DCHECK(gl);
+ GLC(gl, gl->DeleteTextures(1, &resource->gl_id));
}
if (resource->gl_upload_query_id) {
- WebGraphicsContext3D* context3d = Context3d();
- DCHECK(context3d);
- GLC(context3d, context3d->deleteQueryEXT(resource->gl_upload_query_id));
+ GLES2Interface* gl = ContextGL();
+ DCHECK(gl);
+ GLC(gl, gl->DeleteQueriesEXT(1, &resource->gl_upload_query_id));
}
if (resource->gl_pixel_buffer_id) {
- WebGraphicsContext3D* context3d = Context3d();
- DCHECK(context3d);
- GLC(context3d, context3d->deleteBuffer(resource->gl_pixel_buffer_id));
+ GLES2Interface* gl = ContextGL();
+ DCHECK(gl);
+ GLC(gl, gl->DeleteBuffers(1, &resource->gl_pixel_buffer_id));
}
if (resource->mailbox.IsValid() && resource->external) {
- unsigned sync_point = resource->mailbox.sync_point();
+ GLuint sync_point = resource->mailbox.sync_point();
if (resource->mailbox.IsTexture()) {
- WebGraphicsContext3D* context3d = Context3d();
- DCHECK(context3d);
+ lost_resource |= lost_output_surface_;
+ GLES2Interface* gl = ContextGL();
+ DCHECK(gl);
if (resource->gl_id)
- GLC(context3d, context3d->deleteTexture(resource->gl_id));
+ GLC(gl, gl->DeleteTextures(1, &resource->gl_id));
if (!lost_resource && resource->gl_id)
- sync_point = context3d->insertSyncPoint();
+ sync_point = gl->InsertSyncPointCHROMIUM();
} else {
DCHECK(resource->mailbox.IsSharedMemory());
base::SharedMemory* shared_memory = resource->mailbox.shared_memory();
if (resource->pixels && shared_memory) {
DCHECK(shared_memory->memory() == resource->pixels);
resource->pixels = NULL;
+ delete resource->shared_bitmap;
+ resource->shared_bitmap = NULL;
}
}
resource->release_callback.Run(sync_point, lost_resource);
}
+ if (resource->shared_bitmap) {
+ delete resource->shared_bitmap;
+ resource->pixels = NULL;
+ }
if (resource->pixels)
delete[] resource->pixels;
if (resource->pixel_buffer)
@@ -478,10 +597,11 @@ void ResourceProvider::SetPixels(ResourceId id,
if (resource->gl_id) {
DCHECK(!resource->pending_set_pixels);
- WebGraphicsContext3D* context3d = Context3d();
- DCHECK(context3d);
+ DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D));
+ GLES2Interface* gl = ContextGL();
+ DCHECK(gl);
DCHECK(texture_uploader_.get());
- context3d->bindTexture(GL_TEXTURE_2D, resource->gl_id);
+ gl->BindTexture(GL_TEXTURE_2D, resource->gl_id);
texture_uploader_->Upload(image,
image_rect,
source_rect,
@@ -525,11 +645,14 @@ void ResourceProvider::MarkPendingUploadsAsNonBlocking() {
texture_uploader_->MarkPendingUploadsAsNonBlocking();
}
-double ResourceProvider::EstimatedUploadsPerSecond() {
+size_t ResourceProvider::EstimatedUploadsPerTick() {
if (!texture_uploader_)
- return 0.0;
+ return 1u;
- return texture_uploader_->EstimatedTexturesPerSecond();
+ double textures_per_second = texture_uploader_->EstimatedTexturesPerSecond();
+ size_t textures_per_tick = floor(
+ kTextureUploadTickRate * textures_per_second);
+ return textures_per_tick ? textures_per_tick : 1u;
}
void ResourceProvider::FlushUploads() {
@@ -546,36 +669,48 @@ void ResourceProvider::ReleaseCachedData() {
texture_uploader_->ReleaseCachedQueries();
}
-base::TimeDelta ResourceProvider::TextureUpdateTickRate() {
+base::TimeTicks ResourceProvider::EstimatedUploadCompletionTime(
+ size_t uploads_per_tick) {
+ if (lost_output_surface_)
+ return base::TimeTicks();
+
// Software resource uploads happen on impl thread, so don't bother batching
// them up and trying to wait for them to complete.
- double rate =
- texture_uploader_ ? kTextureUploadTickRate : kSoftwareUploadTickRate;
- return base::TimeDelta::FromMicroseconds(base::Time::kMicrosecondsPerSecond *
- rate);
+ if (!texture_uploader_) {
+ return gfx::FrameTime::Now() + base::TimeDelta::FromMicroseconds(
+ base::Time::kMicrosecondsPerSecond * kSoftwareUploadTickRate);
+ }
+
+ base::TimeDelta upload_one_texture_time =
+ base::TimeDelta::FromMicroseconds(
+ base::Time::kMicrosecondsPerSecond * kTextureUploadTickRate) /
+ uploads_per_tick;
+
+ size_t total_uploads = NumBlockingUploads() + uploads_per_tick;
+ return gfx::FrameTime::Now() + upload_one_texture_time * total_uploads;
}
void ResourceProvider::Flush() {
DCHECK(thread_checker_.CalledOnValidThread());
- WebGraphicsContext3D* context3d = Context3d();
- if (context3d)
- context3d->flush();
+ GLES2Interface* gl = ContextGL();
+ if (gl)
+ gl->Flush();
}
void ResourceProvider::Finish() {
DCHECK(thread_checker_.CalledOnValidThread());
- WebGraphicsContext3D* context3d = Context3d();
- if (context3d)
- context3d->finish();
+ GLES2Interface* gl = ContextGL();
+ if (gl)
+ gl->Finish();
}
bool ResourceProvider::ShallowFlushIfSupported() {
DCHECK(thread_checker_.CalledOnValidThread());
- WebGraphicsContext3D* context3d = Context3d();
- if (!context3d || !use_shallow_flush_)
+ GLES2Interface* gl = ContextGL();
+ if (!gl)
return false;
- context3d->shallowFlushCHROMIUM();
+ gl->ShallowFlushCHROMIUM();
return true;
}
@@ -600,18 +735,17 @@ const ResourceProvider::Resource* ResourceProvider::LockForRead(ResourceId id) {
if (resource->external) {
if (!resource->gl_id && resource->mailbox.IsTexture()) {
- WebGraphicsContext3D* context3d = Context3d();
- DCHECK(context3d);
+ GLES2Interface* gl = ContextGL();
+ DCHECK(gl);
if (resource->mailbox.sync_point()) {
- GLC(context3d,
- context3d->waitSyncPoint(resource->mailbox.sync_point()));
+ GLC(gl, gl->WaitSyncPointCHROMIUM(resource->mailbox.sync_point()));
resource->mailbox.ResetSyncPoint();
}
- resource->gl_id = context3d->createTexture();
- GLC(context3d, context3d->bindTexture(
- resource->mailbox.target(), resource->gl_id));
- GLC(context3d, context3d->consumeTextureCHROMIUM(
- resource->mailbox.target(), resource->mailbox.data()));
+ resource->gl_id = texture_id_allocator_->NextId();
+ GLC(gl, gl->BindTexture(resource->target, resource->gl_id));
+ GLC(gl,
+ gl->ConsumeTextureCHROMIUM(resource->target,
+ resource->mailbox.data()));
}
}
@@ -675,28 +809,23 @@ ResourceProvider::ScopedReadLockGL::~ScopedReadLockGL() {
ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
ResourceProvider* resource_provider,
ResourceProvider::ResourceId resource_id,
- GLenum target,
GLenum filter)
: ScopedReadLockGL(resource_provider, resource_id),
- target_(target),
- unit_(GL_TEXTURE0) {
- resource_provider->BindForSampling(resource_id, target, unit_, filter);
+ unit_(GL_TEXTURE0),
+ target_(resource_provider->BindForSampling(resource_id, unit_, filter)) {
}
ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
ResourceProvider* resource_provider,
ResourceProvider::ResourceId resource_id,
- GLenum target,
GLenum unit,
GLenum filter)
: ScopedReadLockGL(resource_provider, resource_id),
- target_(target),
- unit_(unit) {
- resource_provider->BindForSampling(resource_id, target, unit, filter);
+ unit_(unit),
+ target_(resource_provider->BindForSampling(resource_id, unit_, filter)) {
}
ResourceProvider::ScopedSamplerGL::~ScopedSamplerGL() {
- resource_provider_->UnbindForSampling(resource_id_, target_, unit_);
}
ResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL(
@@ -727,8 +856,9 @@ ResourceProvider::ScopedReadLockSoftware::ScopedReadLockSoftware(
ResourceProvider::ResourceId resource_id)
: resource_provider_(resource_provider),
resource_id_(resource_id) {
- ResourceProvider::PopulateSkBitmapWithResource(
- &sk_bitmap_, resource_provider->LockForRead(resource_id));
+ const Resource* resource = resource_provider->LockForRead(resource_id);
+ wrap_mode_ = resource->wrap_mode;
+ ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_, resource);
}
ResourceProvider::ScopedReadLockSoftware::~ScopedReadLockSoftware() {
@@ -750,9 +880,12 @@ ResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware() {
}
ResourceProvider::ResourceProvider(OutputSurface* output_surface,
+ SharedBitmapManager* shared_bitmap_manager,
int highp_threshold_min,
- bool use_rgba_4444_texture_format)
+ bool use_rgba_4444_texture_format,
+ size_t id_allocation_chunk_size)
: output_surface_(output_surface),
+ shared_bitmap_manager_(shared_bitmap_manager),
lost_output_surface_(false),
highp_threshold_min_(highp_threshold_min),
next_id_(1),
@@ -760,11 +893,13 @@ ResourceProvider::ResourceProvider(OutputSurface* output_surface,
default_resource_type_(InvalidType),
use_texture_storage_ext_(false),
use_texture_usage_hint_(false),
- use_shallow_flush_(false),
+ use_compressed_texture_etc1_(false),
max_texture_size_(0),
best_texture_format_(RGBA_8888),
- use_rgba_4444_texture_format_(use_rgba_4444_texture_format) {
+ use_rgba_4444_texture_format_(use_rgba_4444_texture_format),
+ id_allocation_chunk_size_(id_allocation_chunk_size) {
DCHECK(output_surface_->HasClient());
+ DCHECK(id_allocation_chunk_size_);
}
void ResourceProvider::InitializeSoftware() {
@@ -774,7 +909,8 @@ void ResourceProvider::InitializeSoftware() {
CleanUpGLIfNeeded();
default_resource_type_ = Bitmap;
- max_texture_size_ = INT_MAX / 2;
+ // Pick an arbitrary limit here similar to what hardware might.
+ max_texture_size_ = 16 * 1024;
best_texture_format_ = RGBA_8888;
}
@@ -782,45 +918,48 @@ bool ResourceProvider::InitializeGL() {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(!texture_uploader_);
DCHECK_NE(GLTexture, default_resource_type_);
-
- WebGraphicsContext3D* context3d = Context3d();
- DCHECK(context3d);
-
- if (!context3d->makeContextCurrent())
- return false;
+ DCHECK(!texture_id_allocator_);
+ DCHECK(!buffer_id_allocator_);
default_resource_type_ = GLTexture;
const ContextProvider::Capabilities& caps =
output_surface_->context_provider()->ContextCapabilities();
- bool use_map_sub = caps.map_sub;
bool use_bgra = caps.texture_format_bgra8888;
use_texture_storage_ext_ = caps.texture_storage;
- use_shallow_flush_ = caps.shallow_flush;
use_texture_usage_hint_ = caps.texture_usage;
+ use_compressed_texture_etc1_ = caps.texture_format_etc1;
+
+ GLES2Interface* gl = ContextGL();
+ DCHECK(gl);
- texture_uploader_ =
- TextureUploader::Create(context3d, use_map_sub, use_shallow_flush_);
- GLC(context3d, context3d->getIntegerv(GL_MAX_TEXTURE_SIZE,
- &max_texture_size_));
+ texture_uploader_ = TextureUploader::Create(gl);
+ max_texture_size_ = 0; // Context expects cleared value.
+ GLC(gl, gl->GetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size_));
best_texture_format_ = PlatformColor::BestTextureFormat(use_bgra);
+ texture_id_allocator_.reset(
+ new TextureIdAllocator(gl, id_allocation_chunk_size_));
+ buffer_id_allocator_.reset(
+ new BufferIdAllocator(gl, id_allocation_chunk_size_));
+
return true;
}
void ResourceProvider::CleanUpGLIfNeeded() {
- WebGraphicsContext3D* context3d = Context3d();
+ GLES2Interface* gl = ContextGL();
if (default_resource_type_ != GLTexture) {
// We are not in GL mode, but double check before returning.
- DCHECK(!context3d);
+ DCHECK(!gl);
DCHECK(!texture_uploader_);
return;
}
- DCHECK(context3d);
- context3d->makeContextCurrent();
+ DCHECK(gl);
texture_uploader_.reset();
+ texture_id_allocator_.reset();
+ buffer_id_allocator_.reset();
Finish();
}
@@ -836,11 +975,17 @@ int ResourceProvider::CreateChild(const ReturnCallback& return_callback) {
}
void ResourceProvider::DestroyChild(int child_id) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
ChildMap::iterator it = children_.find(child_id);
DCHECK(it != children_.end());
+ DestroyChildInternal(it, Normal);
+}
+
+void ResourceProvider::DestroyChildInternal(ChildMap::iterator it,
+ DeleteStyle style) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
Child& child = it->second;
+ DCHECK(style == ForShutdown || !child.marked_for_deletion);
ResourceIdArray resources_for_child;
@@ -853,11 +998,9 @@ void ResourceProvider::DestroyChild(int child_id) {
// If the child is going away, don't consider any resources in use.
child.in_use_resources.clear();
+ child.marked_for_deletion = true;
- DeleteAndReturnUnusedResourcesToChild(
- &child, ForShutdown, resources_for_child);
-
- children_.erase(it);
+ DeleteAndReturnUnusedResourcesToChild(it, style, resources_for_child);
}
const ResourceProvider::ResourceIdMap& ResourceProvider::GetChildToParentMap(
@@ -865,30 +1008,27 @@ const ResourceProvider::ResourceIdMap& ResourceProvider::GetChildToParentMap(
DCHECK(thread_checker_.CalledOnValidThread());
ChildMap::const_iterator it = children_.find(child);
DCHECK(it != children_.end());
+ DCHECK(!it->second.marked_for_deletion);
return it->second.child_to_parent_map;
}
void ResourceProvider::PrepareSendToParent(const ResourceIdArray& resources,
TransferableResourceArray* list) {
DCHECK(thread_checker_.CalledOnValidThread());
- WebGraphicsContext3D* context3d = Context3d();
- if (!context3d || !context3d->makeContextCurrent()) {
- // TODO(skaslev): Implement this path for software compositing.
- return;
- }
+ GLES2Interface* gl = ContextGL();
bool need_sync_point = false;
for (ResourceIdArray::const_iterator it = resources.begin();
it != resources.end();
++it) {
TransferableResource resource;
- TransferResource(context3d, *it, &resource);
- if (!resource.sync_point)
+ TransferResource(gl, *it, &resource);
+ if (!resource.sync_point && !resource.is_software)
need_sync_point = true;
++resources_.find(*it)->second.exported_count;
list->push_back(resource);
}
if (need_sync_point) {
- unsigned int sync_point = context3d->insertSyncPoint();
+ GLuint sync_point = gl->InsertSyncPointCHROMIUM();
for (TransferableResourceArray::iterator it = list->begin();
it != list->end();
++it) {
@@ -901,12 +1041,9 @@ void ResourceProvider::PrepareSendToParent(const ResourceIdArray& resources,
void ResourceProvider::ReceiveFromChild(
int child, const TransferableResourceArray& resources) {
DCHECK(thread_checker_.CalledOnValidThread());
- WebGraphicsContext3D* context3d = Context3d();
- if (!context3d || !context3d->makeContextCurrent()) {
- // TODO(skaslev): Implement this path for software compositing.
- return;
- }
+ GLES2Interface* gl = ContextGL();
Child& child_info = children_.find(child)->second;
+ DCHECK(!child_info.marked_for_deletion);
for (TransferableResourceArray::const_iterator it = resources.begin();
it != resources.end();
++it) {
@@ -916,33 +1053,57 @@ void ResourceProvider::ReceiveFromChild(
resources_[resource_in_map_it->second].imported_count++;
continue;
}
- unsigned texture_id;
- // NOTE: If the parent is a browser and the child a renderer, the parent
- // is not supposed to have its context wait, because that could induce
- // deadlocks and/or security issues. The caller is responsible for
- // waiting asynchronously, and resetting sync_point before calling this.
- // However if the parent is a renderer (e.g. browser tag), it may be ok
- // (and is simpler) to wait.
- if (it->sync_point)
- GLC(context3d, context3d->waitSyncPoint(it->sync_point));
- GLC(context3d, texture_id = context3d->createTexture());
- GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, texture_id));
- GLC(context3d, context3d->consumeTextureCHROMIUM(GL_TEXTURE_2D,
- it->mailbox.name));
+
+ scoped_ptr<SharedBitmap> bitmap;
+ uint8_t* pixels = NULL;
+ if (it->is_software) {
+ if (shared_bitmap_manager_)
+ bitmap = shared_bitmap_manager_->GetSharedBitmapFromId(it->size,
+ it->mailbox);
+ if (bitmap)
+ pixels = bitmap->pixels();
+ }
+
+ if ((!it->is_software && !gl) || (it->is_software && !pixels)) {
+ TRACE_EVENT0("cc", "ResourceProvider::ReceiveFromChild dropping invalid");
+ ReturnedResourceArray to_return;
+ to_return.push_back(it->ToReturnedResource());
+ child_info.return_callback.Run(to_return);
+ continue;
+ }
+
ResourceId local_id = next_id_++;
- Resource resource(texture_id,
- it->size,
- it->filter,
- 0,
- GL_CLAMP_TO_EDGE,
- TextureUsageAny,
- it->format);
- resource.mailbox.SetName(it->mailbox);
+ Resource& resource = resources_[local_id];
+ if (it->is_software) {
+ resource = Resource(
+ pixels, bitmap.release(), it->size, GL_LINEAR, GL_CLAMP_TO_EDGE);
+ } else {
+ GLuint texture_id;
+ // NOTE: If the parent is a browser and the child a renderer, the parent
+ // is not supposed to have its context wait, because that could induce
+ // deadlocks and/or security issues. The caller is responsible for
+ // waiting asynchronously, and resetting sync_point before calling this.
+ // However if the parent is a renderer (e.g. browser tag), it may be ok
+ // (and is simpler) to wait.
+ if (it->sync_point)
+ GLC(gl, gl->WaitSyncPointCHROMIUM(it->sync_point));
+ texture_id = texture_id_allocator_->NextId();
+ GLC(gl, gl->BindTexture(it->target, texture_id));
+ GLC(gl, gl->ConsumeTextureCHROMIUM(it->target, it->mailbox.name));
+ resource = Resource(texture_id,
+ it->size,
+ it->target,
+ it->filter,
+ 0,
+ GL_CLAMP_TO_EDGE,
+ TextureUsageAny,
+ it->format);
+ resource.mailbox.SetName(it->mailbox);
+ }
resource.child_id = child;
// Don't allocate a texture for a child.
resource.allocated = true;
resource.imported_count = 1;
- resources_[local_id] = resource;
child_info.parent_to_child_map[local_id] = it->id;
child_info.child_to_parent_map[it->id] = local_id;
}
@@ -953,7 +1114,10 @@ void ResourceProvider::DeclareUsedResourcesFromChild(
const ResourceIdArray& resources_from_child) {
DCHECK(thread_checker_.CalledOnValidThread());
- Child& child_info = children_.find(child)->second;
+ ChildMap::iterator child_it = children_.find(child);
+ DCHECK(child_it != children_.end());
+ Child& child_info = child_it->second;
+ DCHECK(!child_info.marked_for_deletion);
child_info.in_use_resources.clear();
for (size_t i = 0; i < resources_from_child.size(); ++i) {
@@ -974,7 +1138,7 @@ void ResourceProvider::DeclareUsedResourcesFromChild(
if (!resource_is_in_use)
unused.push_back(local_id);
}
- DeleteAndReturnUnusedResourcesToChild(&child_info, Normal, unused);
+ DeleteAndReturnUnusedResourcesToChild(child_it, Normal, unused);
}
// static
@@ -991,14 +1155,9 @@ bool ResourceProvider::CompareResourceMapIteratorsByChildId(
void ResourceProvider::ReceiveReturnsFromParent(
const ReturnedResourceArray& resources) {
DCHECK(thread_checker_.CalledOnValidThread());
- WebGraphicsContext3D* context3d = Context3d();
- if (!context3d || !context3d->makeContextCurrent()) {
- // TODO(skaslev): Implement this path for software compositing.
- return;
- }
+ GLES2Interface* gl = ContextGL();
int child_id = 0;
- Child* child_info = NULL;
ResourceIdArray resources_for_child;
std::vector<std::pair<ReturnedResource, ResourceMap::iterator> >
@@ -1023,6 +1182,7 @@ void ResourceProvider::ReceiveReturnsFromParent(
sorted_resources.end(),
CompareResourceMapIteratorsByChildId);
+ ChildMap::iterator child_it = children_.end();
for (size_t i = 0; i < sorted_resources.size(); ++i) {
ReturnedResource& returned = sorted_resources[i].first;
ResourceMap::iterator& map_iterator = sorted_resources[i].second;
@@ -1037,8 +1197,8 @@ void ResourceProvider::ReceiveReturnsFromParent(
if (resource->gl_id) {
if (returned.sync_point)
- GLC(context3d, context3d->waitSyncPoint(returned.sync_point));
- } else {
+ GLC(gl, gl->WaitSyncPointCHROMIUM(returned.sync_point));
+ } else if (!resource->shared_bitmap) {
resource->mailbox =
TextureMailbox(resource->mailbox.name(), returned.sync_point);
}
@@ -1054,17 +1214,16 @@ void ResourceProvider::ReceiveReturnsFromParent(
// Delete the resource and return it to the child it came from one.
if (resource->child_id != child_id) {
- ChildMap::iterator child_it = children_.find(resource->child_id);
- DCHECK(child_it != children_.end());
-
if (child_id) {
DCHECK_NE(resources_for_child.size(), 0u);
+ DCHECK(child_it != children_.end());
DeleteAndReturnUnusedResourcesToChild(
- child_info, Normal, resources_for_child);
+ child_it, Normal, resources_for_child);
resources_for_child.clear();
}
- child_info = &child_it->second;
+ child_it = children_.find(resource->child_id);
+ DCHECK(child_it != children_.end());
child_id = resource->child_id;
}
resources_for_child.push_back(local_id);
@@ -1072,12 +1231,13 @@ void ResourceProvider::ReceiveReturnsFromParent(
if (child_id) {
DCHECK_NE(resources_for_child.size(), 0u);
+ DCHECK(child_it != children_.end());
DeleteAndReturnUnusedResourcesToChild(
- child_info, Normal, resources_for_child);
+ child_it, Normal, resources_for_child);
}
}
-void ResourceProvider::TransferResource(WebGraphicsContext3D* context,
+void ResourceProvider::TransferResource(GLES2Interface* gl,
ResourceId id,
TransferableResource* resource) {
Resource* source = GetResource(id);
@@ -1085,24 +1245,27 @@ void ResourceProvider::TransferResource(WebGraphicsContext3D* context,
DCHECK(!source->lock_for_read_count);
DCHECK(!source->external || (source->external && source->mailbox.IsValid()));
DCHECK(source->allocated);
+ DCHECK_EQ(source->wrap_mode, GL_CLAMP_TO_EDGE);
resource->id = id;
resource->format = source->format;
+ resource->target = source->target;
resource->filter = source->filter;
resource->size = source->size;
- // TODO(skaslev) Implement this path for shared memory resources.
- DCHECK(!source->mailbox.IsSharedMemory());
-
- if (!source->mailbox.IsTexture()) {
+ if (source->shared_bitmap) {
+ resource->mailbox = source->shared_bitmap->id();
+ resource->is_software = true;
+ } else if (!source->mailbox.IsValid()) {
// This is a resource allocated by the compositor, we need to produce it.
// Don't set a sync point, the caller will do it.
DCHECK(source->gl_id);
- GLC(context, context->bindTexture(GL_TEXTURE_2D, source->gl_id));
- GLC(context, context->genMailboxCHROMIUM(resource->mailbox.name));
- GLC(context, context->produceTextureCHROMIUM(GL_TEXTURE_2D,
- resource->mailbox.name));
+ GLC(gl, gl->BindTexture(resource->target, source->gl_id));
+ GLC(gl, gl->GenMailboxCHROMIUM(resource->mailbox.name));
+ GLC(gl,
+ gl->ProduceTextureCHROMIUM(resource->target, resource->mailbox.name));
source->mailbox.SetName(resource->mailbox);
} else {
+ DCHECK(source->mailbox.IsTexture());
// This is either an external resource, or a compositor resource that we
// already exported. Make sure to forward the sync point that we were given.
resource->mailbox = source->mailbox.name();
@@ -1112,23 +1275,19 @@ void ResourceProvider::TransferResource(WebGraphicsContext3D* context,
}
void ResourceProvider::DeleteAndReturnUnusedResourcesToChild(
- Child* child_info,
+ ChildMap::iterator child_it,
DeleteStyle style,
const ResourceIdArray& unused) {
DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(child_info);
-
- if (unused.empty())
- return;
+ DCHECK(child_it != children_.end());
+ Child* child_info = &child_it->second;
- WebGraphicsContext3D* context3d = Context3d();
- if (!context3d || !context3d->makeContextCurrent()) {
- // TODO(skaslev): Implement this path for software compositing.
+ if (unused.empty() && !child_info->marked_for_deletion)
return;
- }
ReturnedResourceArray to_return;
+ GLES2Interface* gl = ContextGL();
bool need_sync_point = false;
for (size_t i = 0; i < unused.size(); ++i) {
ResourceId local_id = unused[i];
@@ -1145,7 +1304,8 @@ void ResourceProvider::DeleteAndReturnUnusedResourcesToChild(
ResourceId child_id = child_info->parent_to_child_map[local_id];
DCHECK(child_info->child_to_parent_map.count(child_id));
- bool is_lost = resource.lost || lost_output_surface_;
+ bool is_lost =
+ resource.lost || (!resource.shared_bitmap && lost_output_surface_);
if (resource.exported_count > 0) {
if (style != ForShutdown) {
// Defer this until we receive the resource back from the parent.
@@ -1157,25 +1317,25 @@ void ResourceProvider::DeleteAndReturnUnusedResourcesToChild(
is_lost = true;
}
- if (resource.filter != resource.original_filter) {
+ if (gl && resource.filter != resource.original_filter) {
DCHECK(resource.target);
DCHECK(resource.gl_id);
- GLC(context3d, context3d->bindTexture(resource.target, resource.gl_id));
- GLC(context3d,
- context3d->texParameteri(resource.target,
- GL_TEXTURE_MIN_FILTER,
- resource.original_filter));
- GLC(context3d,
- context3d->texParameteri(resource.target,
- GL_TEXTURE_MAG_FILTER,
- resource.original_filter));
+ GLC(gl, gl->BindTexture(resource.target, resource.gl_id));
+ GLC(gl,
+ gl->TexParameteri(resource.target,
+ GL_TEXTURE_MIN_FILTER,
+ resource.original_filter));
+ GLC(gl,
+ gl->TexParameteri(resource.target,
+ GL_TEXTURE_MAG_FILTER,
+ resource.original_filter));
}
ReturnedResource returned;
returned.id = child_id;
returned.sync_point = resource.mailbox.sync_point();
- if (!returned.sync_point)
+ if (!returned.sync_point && !resource.shared_bitmap)
need_sync_point = true;
returned.count = resource.imported_count;
returned.lost = is_lost;
@@ -1187,7 +1347,8 @@ void ResourceProvider::DeleteAndReturnUnusedResourcesToChild(
DeleteResourceInternal(it, style);
}
if (need_sync_point) {
- unsigned int sync_point = context3d->insertSyncPoint();
+ DCHECK(gl);
+ GLuint sync_point = gl->InsertSyncPointCHROMIUM();
for (size_t i = 0; i < to_return.size(); ++i) {
if (!to_return[i].sync_point)
to_return[i].sync_point = sync_point;
@@ -1196,6 +1357,12 @@ void ResourceProvider::DeleteAndReturnUnusedResourcesToChild(
if (!to_return.empty())
child_info->return_callback.Run(to_return);
+
+ if (child_info->marked_for_deletion &&
+ child_info->parent_to_child_map.empty()) {
+ DCHECK(child_info->child_to_parent_map.empty());
+ children_.erase(child_it);
+ }
}
void ResourceProvider::AcquirePixelBuffer(ResourceId id) {
@@ -1203,23 +1370,22 @@ void ResourceProvider::AcquirePixelBuffer(ResourceId id) {
DCHECK(!resource->external);
DCHECK_EQ(resource->exported_count, 0);
DCHECK(!resource->image_id);
+ DCHECK_NE(ETC1, resource->format);
if (resource->type == GLTexture) {
- WebGraphicsContext3D* context3d = Context3d();
- DCHECK(context3d);
+ GLES2Interface* gl = ContextGL();
+ DCHECK(gl);
if (!resource->gl_pixel_buffer_id)
- resource->gl_pixel_buffer_id = context3d->createBuffer();
- context3d->bindBuffer(
- GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
- resource->gl_pixel_buffer_id);
- unsigned bytes_per_pixel = BytesPerPixel(resource->format);
- context3d->bufferData(
- GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
- resource->size.height() * RoundUp(bytes_per_pixel
- * resource->size.width(), 4u),
- NULL,
- GL_DYNAMIC_DRAW);
- context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
+ 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() *
+ RoundUp(bytes_per_pixel * resource->size.width(), 4u),
+ NULL,
+ GL_DYNAMIC_DRAW);
+ gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
}
if (resource->pixels) {
@@ -1251,17 +1417,13 @@ void ResourceProvider::ReleasePixelBuffer(ResourceId id) {
if (resource->type == GLTexture) {
if (!resource->gl_pixel_buffer_id)
return;
- WebGraphicsContext3D* context3d = Context3d();
- DCHECK(context3d);
- context3d->bindBuffer(
- GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
- resource->gl_pixel_buffer_id);
- context3d->bufferData(
- GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
- 0,
- NULL,
- GL_DYNAMIC_DRAW);
- context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
+ 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);
}
if (resource->pixels) {
@@ -1279,16 +1441,14 @@ uint8_t* ResourceProvider::MapPixelBuffer(ResourceId id) {
DCHECK(!resource->image_id);
if (resource->type == GLTexture) {
- WebGraphicsContext3D* context3d = Context3d();
- DCHECK(context3d);
+ GLES2Interface* gl = ContextGL();
+ DCHECK(gl);
DCHECK(resource->gl_pixel_buffer_id);
- context3d->bindBuffer(
- GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
- resource->gl_pixel_buffer_id);
- uint8_t* image = static_cast<uint8_t*>(
- context3d->mapBufferCHROMIUM(
- GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, GL_WRITE_ONLY));
- context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
+ 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;
@@ -1307,62 +1467,47 @@ void ResourceProvider::UnmapPixelBuffer(ResourceId id) {
DCHECK(!resource->image_id);
if (resource->type == GLTexture) {
- WebGraphicsContext3D* context3d = Context3d();
- DCHECK(context3d);
+ GLES2Interface* gl = ContextGL();
+ DCHECK(gl);
DCHECK(resource->gl_pixel_buffer_id);
- context3d->bindBuffer(
- GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
- resource->gl_pixel_buffer_id);
- context3d->unmapBufferCHROMIUM(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM);
- context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
+ 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);
}
}
-void ResourceProvider::BindForSampling(ResourceProvider::ResourceId resource_id,
- GLenum target,
- GLenum unit,
- GLenum filter) {
+GLenum ResourceProvider::BindForSampling(
+ ResourceProvider::ResourceId resource_id,
+ GLenum unit,
+ GLenum filter) {
DCHECK(thread_checker_.CalledOnValidThread());
- WebGraphicsContext3D* context3d = Context3d();
+ GLES2Interface* gl = ContextGL();
ResourceMap::iterator it = resources_.find(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);
- ScopedSetActiveTexture scoped_active_tex(context3d, unit);
- GLC(context3d, context3d->bindTexture(target, resource->gl_id));
+ ScopedSetActiveTexture scoped_active_tex(gl, unit);
+ GLenum target = resource->target;
+ GLC(gl, gl->BindTexture(target, resource->gl_id));
if (filter != resource->filter) {
- GLC(context3d, context3d->texParameteri(target,
- GL_TEXTURE_MIN_FILTER,
- filter));
- GLC(context3d, context3d->texParameteri(target,
- GL_TEXTURE_MAG_FILTER,
- filter));
+ GLC(gl, gl->TexParameteri(target, GL_TEXTURE_MIN_FILTER, filter));
+ GLC(gl, gl->TexParameteri(target, GL_TEXTURE_MAG_FILTER, filter));
resource->filter = filter;
- if (resource->target == 0)
- resource->target = target;
- else
- DCHECK_EQ(resource->target, target);
}
- if (resource->image_id)
- context3d->bindTexImage2DCHROMIUM(target, resource->image_id);
-}
-
-void ResourceProvider::UnbindForSampling(
- ResourceProvider::ResourceId resource_id, GLenum target, GLenum unit) {
- DCHECK(thread_checker_.CalledOnValidThread());
- ResourceMap::iterator it = resources_.find(resource_id);
- DCHECK(it != resources_.end());
- Resource* resource = &it->second;
-
- if (!resource->image_id)
- return;
+ if (resource->image_id && resource->dirty_image) {
+ // Release image currently bound to texture.
+ if (resource->bound_image_id)
+ gl->ReleaseTexImage2DCHROMIUM(target, resource->bound_image_id);
+ gl->BindTexImage2DCHROMIUM(target, resource->image_id);
+ resource->bound_image_id = resource->image_id;
+ resource->dirty_image = false;
+ }
- WebGraphicsContext3D* context3d = Context3d();
- ScopedSetActiveTexture scoped_active_tex(context3d, unit);
- context3d->releaseTexImage2DCHROMIUM(target, resource->image_id);
+ return target;
}
void ResourceProvider::BeginSetPixels(ResourceId id) {
@@ -1379,43 +1524,40 @@ void ResourceProvider::BeginSetPixels(ResourceId id) {
LockForWrite(id);
if (resource->gl_id) {
- WebGraphicsContext3D* context3d = Context3d();
- DCHECK(context3d);
+ GLES2Interface* gl = ContextGL();
+ DCHECK(gl);
DCHECK(resource->gl_pixel_buffer_id);
- context3d->bindTexture(GL_TEXTURE_2D, resource->gl_id);
- context3d->bindBuffer(
- GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
- 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)
- resource->gl_upload_query_id = context3d->createQueryEXT();
- context3d->beginQueryEXT(
- GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM,
- 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) {
- context3d->asyncTexImage2DCHROMIUM(
- GL_TEXTURE_2D,
- 0, /* level */
- GetGLInternalFormat(resource->format),
- resource->size.width(),
- resource->size.height(),
- 0, /* border */
- GetGLDataFormat(resource->format),
- GetGLDataType(resource->format),
- NULL);
+ 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 {
- context3d->asyncTexSubImage2DCHROMIUM(
- GL_TEXTURE_2D,
- 0, /* level */
- 0, /* x */
- 0, /* y */
- resource->size.width(),
- resource->size.height(),
- GetGLDataFormat(resource->format),
- GetGLDataType(resource->format),
- NULL);
+ gl->AsyncTexSubImage2DCHROMIUM(GL_TEXTURE_2D,
+ 0, /* level */
+ 0, /* x */
+ 0, /* y */
+ resource->size.width(),
+ resource->size.height(),
+ GLDataFormat(resource->format),
+ GLDataType(resource->format),
+ NULL);
}
- context3d->endQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM);
- context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
+ gl->EndQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM);
+ gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
}
if (resource->pixels) {
@@ -1439,10 +1581,10 @@ void ResourceProvider::ForceSetPixelsToComplete(ResourceId id) {
DCHECK(!resource->set_pixels_completion_forced);
if (resource->gl_id) {
- WebGraphicsContext3D* context3d = Context3d();
- GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, resource->gl_id));
- GLC(context3d, context3d->waitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D));
- GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, 0));
+ GLES2Interface* gl = ContextGL();
+ GLC(gl, gl->BindTexture(GL_TEXTURE_2D, resource->gl_id));
+ GLC(gl, gl->WaitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D));
+ GLC(gl, gl->BindTexture(GL_TEXTURE_2D, 0));
}
resource->set_pixels_completion_forced = true;
@@ -1454,14 +1596,12 @@ bool ResourceProvider::DidSetPixelsComplete(ResourceId id) {
DCHECK(resource->pending_set_pixels);
if (resource->gl_id) {
- WebGraphicsContext3D* context3d = Context3d();
- DCHECK(context3d);
+ GLES2Interface* gl = ContextGL();
+ DCHECK(gl);
DCHECK(resource->gl_upload_query_id);
- unsigned complete = 1;
- context3d->getQueryObjectuivEXT(
- resource->gl_upload_query_id,
- GL_QUERY_RESULT_AVAILABLE_EXT,
- &complete);
+ GLuint complete = 1;
+ gl->GetQueryObjectuivEXT(
+ resource->gl_upload_query_id, GL_QUERY_RESULT_AVAILABLE_EXT, &complete);
if (!complete)
return false;
}
@@ -1476,9 +1616,9 @@ void ResourceProvider::CreateForTesting(ResourceId id) {
LazyCreate(GetResource(id));
}
-GLint ResourceProvider::WrapModeForTesting(ResourceId id) {
+GLenum ResourceProvider::TargetForTesting(ResourceId id) {
Resource* resource = GetResource(id);
- return resource->wrap_mode;
+ return resource->target;
}
void ResourceProvider::LazyCreate(Resource* resource) {
@@ -1489,27 +1629,31 @@ void ResourceProvider::LazyCreate(Resource* resource) {
if (resource->texture_pool == 0)
return;
- WebGraphicsContext3D* context3d = Context3d();
- DCHECK(context3d);
+ resource->gl_id = texture_id_allocator_->NextId();
+
+ GLES2Interface* gl = ContextGL();
+ DCHECK(gl);
// Create and set texture properties. Allocation is delayed until needed.
- GLC(context3d, resource->gl_id = context3d->createTexture());
- GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, resource->gl_id));
- GLC(context3d, context3d->texParameteri(
- GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
- GLC(context3d, context3d->texParameteri(
- GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
- GLC(context3d, context3d->texParameteri(
- GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, resource->wrap_mode));
- GLC(context3d, context3d->texParameteri(
- GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, resource->wrap_mode));
- GLC(context3d, context3d->texParameteri(GL_TEXTURE_2D,
- GL_TEXTURE_POOL_CHROMIUM,
- resource->texture_pool));
+ GLC(gl, gl->BindTexture(resource->target, resource->gl_id));
+ GLC(gl,
+ gl->TexParameteri(resource->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
+ GLC(gl,
+ gl->TexParameteri(resource->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
+ GLC(gl,
+ gl->TexParameteri(
+ resource->target, GL_TEXTURE_WRAP_S, resource->wrap_mode));
+ GLC(gl,
+ gl->TexParameteri(
+ resource->target, GL_TEXTURE_WRAP_T, resource->wrap_mode));
+ GLC(gl,
+ gl->TexParameteri(
+ resource->target, GL_TEXTURE_POOL_CHROMIUM, resource->texture_pool));
if (use_texture_usage_hint_ && resource->hint == TextureUsageFramebuffer) {
- GLC(context3d, context3d->texParameteri(GL_TEXTURE_2D,
- GL_TEXTURE_USAGE_ANGLE,
- GL_FRAMEBUFFER_ATTACHMENT_ANGLE));
+ GLC(gl,
+ gl->TexParameteri(resource->target,
+ GL_TEXTURE_USAGE_ANGLE,
+ GL_FRAMEBUFFER_ATTACHMENT_ANGLE));
}
}
@@ -1525,27 +1669,31 @@ void ResourceProvider::LazyAllocate(Resource* resource) {
if (resource->allocated || !resource->gl_id)
return;
resource->allocated = true;
- WebGraphicsContext3D* context3d = Context3d();
+ GLES2Interface* gl = ContextGL();
gfx::Size& size = resource->size;
+ DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D));
ResourceFormat format = resource->format;
- GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, resource->gl_id));
- if (use_texture_storage_ext_ && IsFormatSupportedForStorage(format)) {
+ GLC(gl, gl->BindTexture(GL_TEXTURE_2D, resource->gl_id));
+ if (use_texture_storage_ext_ && IsFormatSupportedForStorage(format) &&
+ resource->hint != TextureUsageFramebuffer) {
GLenum storage_format = TextureToStorageFormat(format);
- GLC(context3d, context3d->texStorage2DEXT(GL_TEXTURE_2D,
- 1,
- storage_format,
- size.width(),
- size.height()));
+ GLC(gl,
+ gl->TexStorage2DEXT(
+ GL_TEXTURE_2D, 1, storage_format, size.width(), size.height()));
} else {
- GLC(context3d, context3d->texImage2D(GL_TEXTURE_2D,
- 0,
- GetGLInternalFormat(format),
- size.width(),
- size.height(),
- 0,
- GetGLDataFormat(format),
- GetGLDataType(format),
- NULL));
+ // ETC1 does not support preallocation.
+ if (format != ETC1) {
+ GLC(gl,
+ gl->TexImage2D(GL_TEXTURE_2D,
+ 0,
+ GLInternalFormat(format),
+ size.width(),
+ size.height(),
+ 0,
+ GLDataFormat(format),
+ GLDataType(format),
+ NULL));
+ }
}
}
@@ -1567,11 +1715,12 @@ void ResourceProvider::AcquireImage(ResourceId id) {
return;
resource->allocated = true;
- WebGraphicsContext3D* context3d = Context3d();
- DCHECK(context3d);
- DCHECK_EQ(RGBA_8888, resource->format);
- resource->image_id = context3d->createImageCHROMIUM(
- resource->size.width(), resource->size.height(), GL_RGBA8_OES);
+ GLES2Interface* gl = ContextGL();
+ DCHECK(gl);
+ resource->image_id =
+ gl->CreateImageCHROMIUM(resource->size.width(),
+ resource->size.height(),
+ TextureToStorageFormat(resource->format));
DCHECK(resource->image_id);
}
@@ -1583,10 +1732,12 @@ void ResourceProvider::ReleaseImage(ResourceId id) {
if (!resource->image_id)
return;
- WebGraphicsContext3D* context3d = Context3d();
- DCHECK(context3d);
- context3d->destroyImageCHROMIUM(resource->image_id);
+ GLES2Interface* gl = ContextGL();
+ DCHECK(gl);
+ gl->DestroyImageCHROMIUM(resource->image_id);
resource->image_id = 0;
+ resource->bound_image_id = 0;
+ resource->dirty_image = false;
resource->allocated = false;
}
@@ -1597,10 +1748,10 @@ uint8_t* ResourceProvider::MapImage(ResourceId id) {
DCHECK_EQ(resource->exported_count, 0);
if (resource->image_id) {
- WebGraphicsContext3D* context3d = Context3d();
- DCHECK(context3d);
+ GLES2Interface* gl = ContextGL();
+ DCHECK(gl);
return static_cast<uint8_t*>(
- context3d->mapImageCHROMIUM(resource->image_id, GL_READ_WRITE));
+ gl->MapImageCHROMIUM(resource->image_id, GL_READ_WRITE));
}
if (resource->pixels)
@@ -1615,9 +1766,10 @@ void ResourceProvider::UnmapImage(ResourceId id) {
DCHECK_EQ(resource->exported_count, 0);
if (resource->image_id) {
- WebGraphicsContext3D* context3d = Context3d();
- DCHECK(context3d);
- context3d->unmapImageCHROMIUM(resource->image_id);
+ GLES2Interface* gl = ContextGL();
+ DCHECK(gl);
+ gl->UnmapImageCHROMIUM(resource->image_id);
+ resource->dirty_image = true;
}
}
@@ -1629,74 +1781,34 @@ int ResourceProvider::GetImageStride(ResourceId id) {
int stride = 0;
if (resource->image_id) {
- WebGraphicsContext3D* context3d = Context3d();
- DCHECK(context3d);
- context3d->getImageParameterivCHROMIUM(
+ GLES2Interface* gl = ContextGL();
+ DCHECK(gl);
+ gl->GetImageParameterivCHROMIUM(
resource->image_id, GL_IMAGE_ROWBYTES_CHROMIUM, &stride);
}
return stride;
}
-GLint ResourceProvider::GetActiveTextureUnit(WebGraphicsContext3D* context) {
- GLint active_unit = 0;
- context->getIntegerv(GL_ACTIVE_TEXTURE, &active_unit);
- return active_unit;
-}
-
-WebKit::WebGraphicsContext3D* ResourceProvider::Context3d() const {
- ContextProvider* context_provider = output_surface_->context_provider();
- return context_provider ? context_provider->Context3d() : NULL;
-}
+base::SharedMemory* ResourceProvider::GetSharedMemory(ResourceId id) {
+ Resource* resource = GetResource(id);
+ DCHECK(!resource->external);
+ DCHECK_EQ(resource->exported_count, 0);
-size_t ResourceProvider::BytesPerPixel(ResourceFormat format) {
- switch (format) {
- case RGBA_8888:
- case BGRA_8888:
- return 4;
- case RGBA_4444:
- case RGB_565:
- return 2;
- case LUMINANCE_8:
- return 1;
- }
- NOTREACHED();
- return 4;
+ if (!resource->shared_bitmap)
+ return NULL;
+ return resource->shared_bitmap->memory();
}
-GLenum ResourceProvider::GetGLDataType(ResourceFormat format) {
- switch (format) {
- case RGBA_4444:
- return GL_UNSIGNED_SHORT_4_4_4_4;
- case RGBA_8888:
- case BGRA_8888:
- case LUMINANCE_8:
- return GL_UNSIGNED_BYTE;
- case RGB_565:
- return GL_UNSIGNED_SHORT_5_6_5;
- }
- NOTREACHED();
- return GL_UNSIGNED_BYTE;
-}
-
-GLenum ResourceProvider::GetGLDataFormat(ResourceFormat format) {
- switch (format) {
- case RGBA_8888:
- case RGBA_4444:
- return GL_RGBA;
- case BGRA_8888:
- return GL_BGRA_EXT;
- case LUMINANCE_8:
- return GL_LUMINANCE;
- case RGB_565:
- return GL_RGB;
- }
- NOTREACHED();
- return GL_RGBA;
+GLint ResourceProvider::GetActiveTextureUnit(GLES2Interface* gl) {
+ GLint active_unit = 0;
+ gl->GetIntegerv(GL_ACTIVE_TEXTURE, &active_unit);
+ return active_unit;
}
-GLenum ResourceProvider::GetGLInternalFormat(ResourceFormat format) {
- return GetGLDataFormat(format);
+GLES2Interface* ResourceProvider::ContextGL() const {
+ ContextProvider* context_provider = output_surface_->context_provider();
+ return context_provider ? context_provider->ContextGL() : NULL;
}
} // namespace cc
diff --git a/chromium/cc/resources/resource_provider.h b/chromium/cc/resources/resource_provider.h
index 928d4f9aa2a..2478661d62c 100644
--- a/chromium/cc/resources/resource_provider.h
+++ b/chromium/cc/resources/resource_provider.h
@@ -29,18 +29,24 @@
#include "third_party/skia/include/core/SkCanvas.h"
#include "ui/gfx/size.h"
+namespace gpu {
+namespace gles {
+class GLES2Interface;
+}
+}
// A correct fix would be not to use GL types in this interal API file.
typedef unsigned int GLenum;
typedef int GLint;
-namespace WebKit { class WebGraphicsContext3D; }
-
namespace gfx {
class Rect;
class Vector2d;
}
namespace cc {
+class IdAllocator;
+class SharedBitmap;
+class SharedBitmapManager;
class TextureUploader;
// This class is not thread-safe and can only be called from the thread it was
@@ -61,9 +67,12 @@ class CC_EXPORT ResourceProvider {
Bitmap,
};
- static scoped_ptr<ResourceProvider> Create(OutputSurface* output_surface,
- int highp_threshold_min,
- bool use_rgba_4444_texture_format);
+ static scoped_ptr<ResourceProvider> Create(
+ OutputSurface* output_surface,
+ SharedBitmapManager* shared_bitmap_manager,
+ int highp_threshold_min,
+ bool use_rgba_4444_texture_format,
+ size_t id_allocation_chunk_size);
virtual ~ResourceProvider();
void InitializeSoftware();
@@ -97,18 +106,20 @@ class CC_EXPORT ResourceProvider {
// Creates a resource which is tagged as being managed for GPU memory
// accounting purposes.
ResourceId CreateManagedResource(gfx::Size size,
+ GLenum target,
GLint wrap_mode,
TextureUsageHint hint,
ResourceFormat format);
// You can also explicitly create a specific resource type.
ResourceId CreateGLTexture(gfx::Size size,
+ GLenum target,
GLenum texture_pool,
GLint wrap_mode,
TextureUsageHint hint,
ResourceFormat format);
- ResourceId CreateBitmap(gfx::Size size);
+ ResourceId CreateBitmap(gfx::Size size, GLint wrap_mode);
// Wraps an external texture into a GL resource.
ResourceId CreateResourceFromExternalTexture(
unsigned texture_target,
@@ -132,10 +143,10 @@ class CC_EXPORT ResourceProvider {
// Check upload status.
size_t NumBlockingUploads();
void MarkPendingUploadsAsNonBlocking();
- double EstimatedUploadsPerSecond();
+ size_t EstimatedUploadsPerTick();
void FlushUploads();
void ReleaseCachedData();
- base::TimeDelta TextureUpdateTickRate();
+ base::TimeTicks EstimatedUploadCompletionTime(size_t uploads_per_tick);
// Flush all context operations, kicking uploads and ensuring ordering with
// respect to other contexts.
@@ -217,18 +228,18 @@ class CC_EXPORT ResourceProvider {
public:
ScopedSamplerGL(ResourceProvider* resource_provider,
ResourceProvider::ResourceId resource_id,
- GLenum target,
GLenum filter);
ScopedSamplerGL(ResourceProvider* resource_provider,
ResourceProvider::ResourceId resource_id,
- GLenum target,
GLenum unit,
GLenum filter);
virtual ~ScopedSamplerGL();
+ GLenum target() const { return target_; }
+
private:
- GLenum target_;
GLenum unit_;
+ GLenum target_;
DISALLOW_COPY_AND_ASSIGN(ScopedSamplerGL);
};
@@ -256,11 +267,13 @@ class CC_EXPORT ResourceProvider {
~ScopedReadLockSoftware();
const SkBitmap* sk_bitmap() const { return &sk_bitmap_; }
+ GLint wrap_mode() const { return wrap_mode_; }
private:
ResourceProvider* resource_provider_;
ResourceProvider::ResourceId resource_id_;
SkBitmap sk_bitmap_;
+ GLint wrap_mode_;
DISALLOW_COPY_AND_ASSIGN(ScopedReadLockSoftware);
};
@@ -322,6 +335,8 @@ class CC_EXPORT ResourceProvider {
// Returns the stride for the image.
int GetImageStride(ResourceId id);
+ base::SharedMemory* GetSharedMemory(ResourceId id);
+
// For tests only! This prevents detecting uninitialized reads.
// Use SetPixels or LockForWrite to allocate implicitly.
void AllocateForTesting(ResourceId id);
@@ -329,7 +344,7 @@ class CC_EXPORT ResourceProvider {
// For tests only!
void CreateForTesting(ResourceId id);
- GLint WrapModeForTesting(ResourceId id);
+ GLenum TargetForTesting(ResourceId id);
// Sets the current read fence. If a resource is locked for read
// and has read fences enabled, the resource will not allow writes
@@ -345,11 +360,7 @@ class CC_EXPORT ResourceProvider {
// Indicates if we can currently lock this resource for write.
bool CanLockForWrite(ResourceId id);
- static GLint GetActiveTextureUnit(WebKit::WebGraphicsContext3D* context);
- static size_t BytesPerPixel(ResourceFormat format);
- static GLenum GetGLDataType(ResourceFormat format);
- static GLenum GetGLDataFormat(ResourceFormat format);
- static GLenum GetGLInternalFormat(ResourceFormat format);
+ static GLint GetActiveTextureUnit(gpu::gles2::GLES2Interface* gl);
private:
struct Resource {
@@ -357,12 +368,14 @@ class CC_EXPORT ResourceProvider {
~Resource();
Resource(unsigned texture_id,
gfx::Size size,
+ GLenum target,
GLenum filter,
GLenum texture_pool,
GLint wrap_mode,
TextureUsageHint hint,
ResourceFormat format);
Resource(uint8_t* pixels,
+ SharedBitmap* bitmap,
gfx::Size size,
GLenum filter,
GLint wrap_mode);
@@ -389,17 +402,20 @@ class CC_EXPORT ResourceProvider {
bool enable_read_lock_fences;
scoped_refptr<Fence> read_lock_fence;
gfx::Size size;
+ GLenum target;
// TODO(skyostil): Use a separate sampler object for filter state.
GLenum original_filter;
GLenum filter;
- GLenum target;
unsigned image_id;
+ unsigned bound_image_id;
+ bool dirty_image;
GLenum texture_pool;
GLint wrap_mode;
bool lost;
TextureUsageHint hint;
ResourceType type;
ResourceFormat format;
+ SharedBitmap* shared_bitmap;
};
typedef base::hash_map<ResourceId, Resource> ResourceMap;
@@ -415,6 +431,7 @@ class CC_EXPORT ResourceProvider {
ResourceIdMap parent_to_child_map;
ReturnCallback return_callback;
ResourceIdSet in_use_resources;
+ bool marked_for_deletion;
};
typedef base::hash_map<int, Child> ChildMap;
@@ -424,8 +441,10 @@ class CC_EXPORT ResourceProvider {
}
ResourceProvider(OutputSurface* output_surface,
+ SharedBitmapManager* shared_bitmap_manager,
int highp_threshold_min,
- bool use_rgba_4444_texture_format);
+ bool use_rgba_4444_texture_format,
+ size_t id_allocation_chunk_size);
void CleanUpGLIfNeeded();
@@ -437,7 +456,7 @@ class CC_EXPORT ResourceProvider {
static void PopulateSkBitmapWithResource(SkBitmap* sk_bitmap,
const Resource* resource);
- void TransferResource(WebKit::WebGraphicsContext3D* context,
+ void TransferResource(gpu::gles2::GLES2Interface* gl,
ResourceId id,
TransferableResource* resource);
enum DeleteStyle {
@@ -445,27 +464,25 @@ class CC_EXPORT ResourceProvider {
ForShutdown,
};
void DeleteResourceInternal(ResourceMap::iterator it, DeleteStyle style);
- void DeleteAndReturnUnusedResourcesToChild(Child* child_info,
+ void DeleteAndReturnUnusedResourcesToChild(ChildMap::iterator child_it,
DeleteStyle style,
const ResourceIdArray& unused);
+ void DestroyChildInternal(ChildMap::iterator it, DeleteStyle style);
void LazyCreate(Resource* resource);
void LazyAllocate(Resource* resource);
// Binds the given GL resource to a texture target for sampling using the
- // specified filter for both minification and magnification. The resource
- // must be locked for reading.
- void BindForSampling(ResourceProvider::ResourceId resource_id,
- GLenum target,
- GLenum unit,
- GLenum filter);
- void UnbindForSampling(ResourceProvider::ResourceId resource_id,
- GLenum target,
- GLenum unit);
+ // specified filter for both minification and magnification. Returns the
+ // texture target used. The resource must be locked for reading.
+ GLenum BindForSampling(ResourceProvider::ResourceId resource_id,
+ GLenum unit,
+ GLenum filter);
// Returns NULL if the output_surface_ does not have a ContextProvider.
- WebKit::WebGraphicsContext3D* Context3d() const;
+ gpu::gles2::GLES2Interface* ContextGL() const;
OutputSurface* output_surface_;
+ SharedBitmapManager* shared_bitmap_manager_;
bool lost_output_surface_;
int highp_threshold_min_;
ResourceId next_id_;
@@ -476,7 +493,7 @@ class CC_EXPORT ResourceProvider {
ResourceType default_resource_type_;
bool use_texture_storage_ext_;
bool use_texture_usage_hint_;
- bool use_shallow_flush_;
+ bool use_compressed_texture_etc1_;
scoped_ptr<TextureUploader> texture_uploader_;
int max_texture_size_;
ResourceFormat best_texture_format_;
@@ -486,9 +503,29 @@ class CC_EXPORT ResourceProvider {
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_;
+
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 unsigned BitsPerPixel(ResourceFormat format) {
+ DCHECK_LE(format, RESOURCE_FORMAT_MAX);
+ static const unsigned format_bits_per_pixel[RESOURCE_FORMAT_MAX + 1] = {
+ 32, // RGBA_8888
+ 16, // RGBA_4444
+ 32, // BGRA_8888
+ 8, // LUMINANCE_8
+ 16, // RGB_565,
+ 4 // ETC1
+ };
+ return format_bits_per_pixel[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 fed3016e2e5..e40c9a7e6fe 100644
--- a/chromium/cc/resources/resource_provider_unittest.cc
+++ b/chromium/cc/resources/resource_provider_unittest.cc
@@ -5,22 +5,24 @@
#include "cc/resources/resource_provider.h"
#include <algorithm>
+#include <map>
#include "base/bind.h"
#include "base/containers/hash_tables.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "cc/base/scoped_ptr_deque.h"
-#include "cc/debug/test_web_graphics_context_3d.h"
#include "cc/output/output_surface.h"
#include "cc/resources/returned_resource.h"
+#include "cc/resources/shared_bitmap_manager.h"
#include "cc/resources/single_release_callback.h"
#include "cc/test/fake_output_surface.h"
#include "cc/test/fake_output_surface_client.h"
+#include "cc/test/test_texture.h"
+#include "cc/test/test_web_graphics_context_3d.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/khronos/GLES2/gl2ext.h"
#include "ui/gfx/rect.h"
@@ -31,57 +33,65 @@ using testing::Return;
using testing::SetArgPointee;
using testing::StrictMock;
using testing::_;
-using WebKit::WGC3Dbyte;
-using WebKit::WGC3Denum;
-using WebKit::WGC3Dint;
-using WebKit::WGC3Dsizei;
-using WebKit::WGC3Duint;
-using WebKit::WebGLId;
namespace cc {
namespace {
-size_t TextureSize(gfx::Size size, ResourceFormat format) {
- unsigned int components_per_pixel = 4;
- unsigned int bytes_per_component = 1;
- return size.width() * size.height() * components_per_pixel *
- bytes_per_component;
+static void EmptyReleaseCallback(unsigned sync_point, bool lost_resource) {}
+
+static void SharedMemoryReleaseCallback(scoped_ptr<base::SharedMemory> memory,
+ unsigned sync_point,
+ bool lost_resource) {}
+
+static void ReleaseTextureMailbox(unsigned* release_sync_point,
+ bool* release_lost_resource,
+ unsigned sync_point,
+ bool lost_resource) {
+ *release_sync_point = sync_point;
+ *release_lost_resource = lost_resource;
+}
+
+static void ReleaseSharedMemoryCallback(
+ scoped_ptr<base::SharedMemory> shared_memory,
+ bool* release_called,
+ unsigned* release_sync_point,
+ bool* lost_resource_result,
+ unsigned sync_point,
+ bool lost_resource) {
+ *release_called = true;
+ *release_sync_point = sync_point;
+ *lost_resource_result = lost_resource;
+}
+
+static scoped_ptr<base::SharedMemory> CreateAndFillSharedMemory(
+ gfx::Size size,
+ uint32_t value) {
+ scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory);
+ CHECK(shared_memory->CreateAndMapAnonymous(4 * size.GetArea()));
+ uint32_t* pixels = reinterpret_cast<uint32_t*>(shared_memory->memory());
+ CHECK(pixels);
+ std::fill_n(pixels, size.GetArea(), value);
+ return shared_memory.Pass();
}
class TextureStateTrackingContext : public TestWebGraphicsContext3D {
public:
- MOCK_METHOD2(bindTexture, void(WGC3Denum target, WebGLId texture));
- MOCK_METHOD3(texParameteri,
- void(WGC3Denum target, WGC3Denum pname, WGC3Dint param));
+ MOCK_METHOD2(bindTexture, void(GLenum target, GLuint texture));
+ MOCK_METHOD3(texParameteri, void(GLenum target, GLenum pname, GLint param));
MOCK_METHOD1(waitSyncPoint, void(unsigned sync_point));
MOCK_METHOD0(insertSyncPoint, unsigned(void));
- MOCK_METHOD2(produceTextureCHROMIUM, void(WGC3Denum target,
- const WGC3Dbyte* mailbox));
- MOCK_METHOD2(consumeTextureCHROMIUM, void(WGC3Denum target,
- const WGC3Dbyte* mailbox));
-
- // Force all textures to be "1" so we can test for them.
- virtual WebKit::WebGLId NextTextureId() OVERRIDE { return 1; }
-};
-
-struct Texture : public base::RefCounted<Texture> {
- Texture() : format(RGBA_8888),
- filter(GL_NEAREST_MIPMAP_LINEAR) {}
-
- void Reallocate(gfx::Size size, ResourceFormat format) {
- this->size = size;
- this->format = format;
- this->data.reset(new uint8_t[TextureSize(size, format)]);
- }
-
- gfx::Size size;
- ResourceFormat format;
- WGC3Denum filter;
- scoped_ptr<uint8_t[]> data;
-
- private:
- friend class base::RefCounted<Texture>;
- ~Texture() {}
+ MOCK_METHOD2(produceTextureCHROMIUM,
+ void(GLenum target, const GLbyte* mailbox));
+ MOCK_METHOD2(consumeTextureCHROMIUM,
+ void(GLenum target, const GLbyte* mailbox));
+
+ // Force all textures to be consecutive numbers starting at "1",
+ // so we easily can test for them.
+ virtual GLuint NextTextureId() OVERRIDE {
+ base::AutoLock lock(namespace_->lock);
+ return namespace_->next_texture_id++;
+ }
+ virtual void RetireTextureId(GLuint) OVERRIDE {}
};
// Shared data between multiple ResourceProviderContext. This contains mailbox
@@ -94,15 +104,15 @@ class ContextSharedData {
unsigned InsertSyncPoint() { return next_sync_point_++; }
- void GenMailbox(WGC3Dbyte* mailbox) {
- memset(mailbox, 0, sizeof(WGC3Dbyte[64]));
+ void GenMailbox(GLbyte* mailbox) {
+ memset(mailbox, 0, sizeof(GLbyte[64]));
memcpy(mailbox, &next_mailbox_, sizeof(next_mailbox_));
++next_mailbox_;
}
- void ProduceTexture(const WGC3Dbyte* mailbox_name,
+ void ProduceTexture(const GLbyte* mailbox_name,
unsigned sync_point,
- scoped_refptr<Texture> texture) {
+ scoped_refptr<TestTexture> texture) {
unsigned mailbox = 0;
memcpy(&mailbox, mailbox_name, sizeof(mailbox));
ASSERT_TRUE(mailbox && mailbox < next_mailbox_);
@@ -111,8 +121,8 @@ class ContextSharedData {
sync_point_for_mailbox_[mailbox] = sync_point;
}
- scoped_refptr<Texture> ConsumeTexture(const WGC3Dbyte* mailbox_name,
- unsigned sync_point) {
+ scoped_refptr<TestTexture> ConsumeTexture(const GLbyte* mailbox_name,
+ unsigned sync_point) {
unsigned mailbox = 0;
memcpy(&mailbox, mailbox_name, sizeof(mailbox));
DCHECK(mailbox && mailbox < next_mailbox_);
@@ -122,7 +132,7 @@ class ContextSharedData {
// ProduceTexture.
if (sync_point_for_mailbox_[mailbox] > sync_point) {
NOTREACHED();
- return scoped_refptr<Texture>();
+ return scoped_refptr<TestTexture>();
}
return textures_[mailbox];
}
@@ -132,7 +142,7 @@ class ContextSharedData {
unsigned next_sync_point_;
unsigned next_mailbox_;
- typedef base::hash_map<unsigned, scoped_refptr<Texture> > TextureMap;
+ typedef base::hash_map<unsigned, scoped_refptr<TestTexture> > TextureMap;
TextureMap textures_;
base::hash_map<unsigned, unsigned> sync_point_for_mailbox_;
};
@@ -141,8 +151,7 @@ class ResourceProviderContext : public TestWebGraphicsContext3D {
public:
static scoped_ptr<ResourceProviderContext> Create(
ContextSharedData* shared_data) {
- return make_scoped_ptr(
- new ResourceProviderContext(Attributes(), shared_data));
+ return make_scoped_ptr(new ResourceProviderContext(shared_data));
}
virtual unsigned insertSyncPoint() OVERRIDE {
@@ -164,35 +173,15 @@ class ResourceProviderContext : public TestWebGraphicsContext3D {
last_waited_sync_point_ = std::max(sync_point, last_waited_sync_point_);
}
- virtual void bindTexture(WGC3Denum target, WebGLId texture) OVERRIDE {
- ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
- ASSERT_TRUE(!texture || textures_.find(texture) != textures_.end());
- current_texture_ = texture;
- }
-
- virtual WebGLId createTexture() OVERRIDE {
- WebGLId id = TestWebGraphicsContext3D::createTexture();
- textures_[id] = new Texture;
- return id;
- }
-
- virtual void deleteTexture(WebGLId id) OVERRIDE {
- TextureMap::iterator it = textures_.find(id);
- ASSERT_FALSE(it == textures_.end());
- textures_.erase(it);
- if (current_texture_ == id)
- current_texture_ = 0;
- }
-
- virtual void texStorage2DEXT(WGC3Denum target,
- WGC3Dint levels,
- WGC3Duint internalformat,
- WGC3Dint width,
- WGC3Dint height) OVERRIDE {
- ASSERT_TRUE(current_texture_);
+ virtual void texStorage2DEXT(GLenum target,
+ GLint levels,
+ GLuint internalformat,
+ GLint width,
+ GLint height) OVERRIDE {
+ CheckTextureIsBound(target);
ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
ASSERT_EQ(1, levels);
- WGC3Denum format = GL_RGBA;
+ GLenum format = GL_RGBA;
switch (internalformat) {
case GL_RGBA8_OES:
break;
@@ -205,16 +194,16 @@ class ResourceProviderContext : public TestWebGraphicsContext3D {
AllocateTexture(gfx::Size(width, height), format);
}
- virtual void texImage2D(WGC3Denum target,
- WGC3Dint level,
- WGC3Denum internalformat,
- WGC3Dsizei width,
- WGC3Dsizei height,
- WGC3Dint border,
- WGC3Denum format,
- WGC3Denum type,
+ virtual void texImage2D(GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type,
const void* pixels) OVERRIDE {
- ASSERT_TRUE(current_texture_);
+ CheckTextureIsBound(target);
ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
ASSERT_FALSE(level);
ASSERT_EQ(internalformat, format);
@@ -225,95 +214,71 @@ class ResourceProviderContext : public TestWebGraphicsContext3D {
SetPixels(0, 0, width, height, pixels);
}
- virtual void texSubImage2D(WGC3Denum target,
- WGC3Dint level,
- WGC3Dint xoffset,
- WGC3Dint yoffset,
- WGC3Dsizei width,
- WGC3Dsizei height,
- WGC3Denum format,
- WGC3Denum type,
+ virtual void texSubImage2D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
const void* pixels) OVERRIDE {
- ASSERT_TRUE(current_texture_);
+ CheckTextureIsBound(target);
ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
ASSERT_FALSE(level);
- ASSERT_TRUE(textures_[current_texture_].get());
- ASSERT_EQ(
- ResourceProvider::GetGLDataFormat(textures_[current_texture_]->format),
- format);
ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE), type);
+ {
+ base::AutoLock lock_for_texture_access(namespace_->lock);
+ ASSERT_EQ(GLDataFormat(BoundTexture(target)->format), format);
+ }
ASSERT_TRUE(pixels);
SetPixels(xoffset, yoffset, width, height, pixels);
}
- virtual void texParameteri(WGC3Denum target, WGC3Denum param, WGC3Dint value)
- OVERRIDE {
- ASSERT_TRUE(current_texture_);
- ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
- scoped_refptr<Texture> texture = textures_[current_texture_];
- ASSERT_TRUE(texture.get());
- if (param != GL_TEXTURE_MIN_FILTER)
- return;
- texture->filter = value;
- }
-
- virtual void genMailboxCHROMIUM(WGC3Dbyte* mailbox) OVERRIDE {
+ virtual void genMailboxCHROMIUM(GLbyte* mailbox) OVERRIDE {
return shared_data_->GenMailbox(mailbox);
}
- virtual void produceTextureCHROMIUM(WGC3Denum target,
- const WGC3Dbyte* mailbox) OVERRIDE {
- ASSERT_TRUE(current_texture_);
- ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
+ virtual void produceTextureCHROMIUM(GLenum target,
+ const GLbyte* mailbox) OVERRIDE {
+ CheckTextureIsBound(target);
// Delay moving the texture into the mailbox until the next
// InsertSyncPoint, so that it is not visible to other contexts that
// haven't waited on that sync point.
scoped_ptr<PendingProduceTexture> pending(new PendingProduceTexture);
memcpy(pending->mailbox, mailbox, sizeof(pending->mailbox));
- pending->texture = textures_[current_texture_];
+ base::AutoLock lock_for_texture_access(namespace_->lock);
+ pending->texture = BoundTexture(target);
pending_produce_textures_.push_back(pending.Pass());
}
- virtual void consumeTextureCHROMIUM(WGC3Denum target,
- const WGC3Dbyte* mailbox) OVERRIDE {
- ASSERT_TRUE(current_texture_);
- ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
- textures_[current_texture_] = shared_data_->ConsumeTexture(
- mailbox, last_waited_sync_point_);
+ virtual void consumeTextureCHROMIUM(GLenum target,
+ const GLbyte* mailbox) OVERRIDE {
+ CheckTextureIsBound(target);
+ base::AutoLock lock_for_texture_access(namespace_->lock);
+ scoped_refptr<TestTexture> texture =
+ shared_data_->ConsumeTexture(mailbox, last_waited_sync_point_);
+ namespace_->textures.Replace(BoundTextureId(target), texture);
}
void GetPixels(gfx::Size size, ResourceFormat format, uint8_t* pixels) {
- ASSERT_TRUE(current_texture_);
- scoped_refptr<Texture> texture = textures_[current_texture_];
- ASSERT_TRUE(texture.get());
+ CheckTextureIsBound(GL_TEXTURE_2D);
+ base::AutoLock lock_for_texture_access(namespace_->lock);
+ scoped_refptr<TestTexture> texture = BoundTexture(GL_TEXTURE_2D);
ASSERT_EQ(texture->size, size);
ASSERT_EQ(texture->format, format);
- memcpy(pixels, texture->data.get(), TextureSize(size, format));
+ memcpy(pixels, texture->data.get(), TextureSizeBytes(size, format));
}
- WGC3Denum GetTextureFilter() {
- DCHECK(current_texture_);
- scoped_refptr<Texture> texture = textures_[current_texture_];
- DCHECK(texture.get());
- return texture->filter;
- }
-
- int texture_count() { return textures_.size(); }
-
protected:
- ResourceProviderContext(const Attributes& attrs,
- ContextSharedData* shared_data)
- : TestWebGraphicsContext3D(attrs),
- shared_data_(shared_data),
- current_texture_(0),
+ explicit ResourceProviderContext(ContextSharedData* shared_data)
+ : shared_data_(shared_data),
last_waited_sync_point_(0) {}
private:
- void AllocateTexture(gfx::Size size, WGC3Denum format) {
- ASSERT_TRUE(current_texture_);
- scoped_refptr<Texture> texture = textures_[current_texture_];
- ASSERT_TRUE(texture.get());
+ void AllocateTexture(gfx::Size size, GLenum format) {
+ CheckTextureIsBound(GL_TEXTURE_2D);
ResourceFormat texture_format = RGBA_8888;
switch (format) {
case GL_RGBA:
@@ -323,7 +288,8 @@ class ResourceProviderContext : public TestWebGraphicsContext3D {
texture_format = BGRA_8888;
break;
}
- texture->Reallocate(size, texture_format);
+ base::AutoLock lock_for_texture_access(namespace_->lock);
+ BoundTexture(GL_TEXTURE_2D)->Reallocate(size, texture_format);
}
void SetPixels(int xoffset,
@@ -331,18 +297,18 @@ class ResourceProviderContext : public TestWebGraphicsContext3D {
int width,
int height,
const void* pixels) {
- ASSERT_TRUE(current_texture_);
- scoped_refptr<Texture> texture = textures_[current_texture_];
- ASSERT_TRUE(texture.get());
+ CheckTextureIsBound(GL_TEXTURE_2D);
+ base::AutoLock lock_for_texture_access(namespace_->lock);
+ scoped_refptr<TestTexture> texture = BoundTexture(GL_TEXTURE_2D);
ASSERT_TRUE(texture->data.get());
ASSERT_TRUE(xoffset >= 0 && xoffset + width <= texture->size.width());
ASSERT_TRUE(yoffset >= 0 && yoffset + height <= texture->size.height());
ASSERT_TRUE(pixels);
- size_t in_pitch = TextureSize(gfx::Size(width, 1), texture->format);
+ size_t in_pitch = TextureSizeBytes(gfx::Size(width, 1), texture->format);
size_t out_pitch =
- TextureSize(gfx::Size(texture->size.width(), 1), texture->format);
+ TextureSizeBytes(gfx::Size(texture->size.width(), 1), texture->format);
uint8_t* dest = texture->data.get() + yoffset * out_pitch +
- TextureSize(gfx::Size(xoffset, 1), texture->format);
+ TextureSizeBytes(gfx::Size(xoffset, 1), texture->format);
const uint8_t* src = static_cast<const uint8_t*>(pixels);
for (int i = 0; i < height; ++i) {
memcpy(dest, src, in_pitch);
@@ -351,19 +317,65 @@ class ResourceProviderContext : public TestWebGraphicsContext3D {
}
}
- typedef base::hash_map<WebGLId, scoped_refptr<Texture> > TextureMap;
struct PendingProduceTexture {
- WGC3Dbyte mailbox[64];
- scoped_refptr<Texture> texture;
+ GLbyte mailbox[64];
+ scoped_refptr<TestTexture> texture;
};
typedef ScopedPtrDeque<PendingProduceTexture> PendingProduceTextureList;
ContextSharedData* shared_data_;
- WebGLId current_texture_;
- TextureMap textures_;
unsigned last_waited_sync_point_;
PendingProduceTextureList pending_produce_textures_;
};
+void FreeSharedBitmap(SharedBitmap* shared_bitmap) {
+ delete shared_bitmap->memory();
+}
+
+void IgnoreSharedBitmap(SharedBitmap* shared_bitmap) {}
+
+class TestSharedBitmapManager : public SharedBitmapManager {
+ public:
+ TestSharedBitmapManager() : count_(0) {}
+ virtual ~TestSharedBitmapManager() {}
+
+ virtual scoped_ptr<SharedBitmap> AllocateSharedBitmap(gfx::Size size)
+ OVERRIDE {
+ scoped_ptr<base::SharedMemory> memory(new base::SharedMemory);
+ memory->CreateAndMapAnonymous(size.GetArea() * 4);
+ int8 name[64] = { 0 };
+ name[0] = count_++;
+ SharedBitmapId id;
+ id.SetName(name);
+ bitmap_map_[id] = memory.get();
+ return scoped_ptr<SharedBitmap>(
+ new SharedBitmap(memory.release(), id, base::Bind(&FreeSharedBitmap)));
+ }
+
+ virtual scoped_ptr<SharedBitmap> GetSharedBitmapFromId(
+ gfx::Size,
+ const SharedBitmapId& id) OVERRIDE {
+ if (bitmap_map_.find(id) == bitmap_map_.end())
+ return scoped_ptr<SharedBitmap>();
+ return scoped_ptr<SharedBitmap>(
+ new SharedBitmap(bitmap_map_[id], id, base::Bind(&IgnoreSharedBitmap)));
+ }
+
+ virtual scoped_ptr<SharedBitmap> GetBitmapForSharedMemory(
+ base::SharedMemory* memory) OVERRIDE {
+ int8 name[64] = { 0 };
+ name[0] = count_++;
+ SharedBitmapId id;
+ id.SetName(name);
+ bitmap_map_[id] = memory;
+ return scoped_ptr<SharedBitmap>(
+ new SharedBitmap(memory, id, base::Bind(&IgnoreSharedBitmap)));
+ }
+
+ private:
+ int count_;
+ std::map<SharedBitmapId, base::SharedMemory*> bitmap_map_;
+};
+
void GetResourcePixels(ResourceProvider* resource_provider,
ResourceProviderContext* context,
ResourceProvider::ResourceId id,
@@ -397,7 +409,8 @@ class ResourceProviderTest
public:
ResourceProviderTest()
: shared_data_(ContextSharedData::Create()),
- context3d_(NULL) {
+ context3d_(NULL),
+ child_context_(NULL) {
switch (GetParam()) {
case ResourceProvider::GLTexture: {
scoped_ptr<ResourceProviderContext> context3d(
@@ -409,19 +422,37 @@ class ResourceProviderTest
context3d.PassAs<TestWebGraphicsContext3D>());
output_surface_ = FakeOutputSurface::Create3d(context_provider);
+
+ scoped_ptr<ResourceProviderContext> child_context_owned =
+ ResourceProviderContext::Create(shared_data_.get());
+ child_context_ = child_context_owned.get();
+ child_output_surface_ = FakeOutputSurface::Create3d(
+ child_context_owned.PassAs<TestWebGraphicsContext3D>());
break;
}
case ResourceProvider::Bitmap:
output_surface_ = FakeOutputSurface::CreateSoftware(
make_scoped_ptr(new SoftwareOutputDevice));
+ child_output_surface_ = FakeOutputSurface::CreateSoftware(
+ make_scoped_ptr(new SoftwareOutputDevice));
break;
case ResourceProvider::InvalidType:
NOTREACHED();
break;
}
CHECK(output_surface_->BindToClient(&output_surface_client_));
+ CHECK(child_output_surface_->BindToClient(&child_output_surface_client_));
+
+ shared_bitmap_manager_.reset(new TestSharedBitmapManager());
+
resource_provider_ = ResourceProvider::Create(
- output_surface_.get(), 0, false);
+ output_surface_.get(), shared_bitmap_manager_.get(), 0, false, 1);
+ child_resource_provider_ = ResourceProvider::Create(
+ child_output_surface_.get(),
+ shared_bitmap_manager_.get(),
+ 0,
+ false,
+ 1);
}
static void CollectResources(ReturnedResourceArray* array,
@@ -435,19 +466,63 @@ class ResourceProviderTest
static void SetResourceFilter(ResourceProvider* resource_provider,
ResourceProvider::ResourceId id,
- WGC3Denum filter) {
+ GLenum filter) {
ResourceProvider::ScopedSamplerGL sampler(
resource_provider, id, GL_TEXTURE_2D, filter);
}
ResourceProviderContext* context() { return context3d_; }
+ ResourceProvider::ResourceId CreateChildMailbox(unsigned* release_sync_point,
+ bool* lost_resource,
+ bool* release_called,
+ unsigned* sync_point) {
+ if (GetParam() == ResourceProvider::GLTexture) {
+ unsigned texture = child_context_->createTexture();
+ gpu::Mailbox gpu_mailbox;
+ child_context_->bindTexture(GL_TEXTURE_2D, texture);
+ child_context_->genMailboxCHROMIUM(gpu_mailbox.name);
+ child_context_->produceTextureCHROMIUM(GL_TEXTURE_2D, gpu_mailbox.name);
+ *sync_point = child_context_->insertSyncPoint();
+ EXPECT_LT(0u, *sync_point);
+
+ scoped_ptr<base::SharedMemory> shared_memory;
+ scoped_ptr<SingleReleaseCallback> callback =
+ SingleReleaseCallback::Create(base::Bind(ReleaseSharedMemoryCallback,
+ base::Passed(&shared_memory),
+ release_called,
+ release_sync_point,
+ lost_resource));
+ return child_resource_provider_->CreateResourceFromTextureMailbox(
+ TextureMailbox(gpu_mailbox, *sync_point), callback.Pass());
+ } else {
+ gfx::Size size(64, 64);
+ scoped_ptr<base::SharedMemory> shared_memory(
+ CreateAndFillSharedMemory(size, 0));
+
+ base::SharedMemory* shared_memory_ptr = shared_memory.get();
+ scoped_ptr<SingleReleaseCallback> callback =
+ SingleReleaseCallback::Create(base::Bind(ReleaseSharedMemoryCallback,
+ base::Passed(&shared_memory),
+ release_called,
+ release_sync_point,
+ lost_resource));
+ return child_resource_provider_->CreateResourceFromTextureMailbox(
+ TextureMailbox(shared_memory_ptr, size), callback.Pass());
+ }
+ }
+
protected:
scoped_ptr<ContextSharedData> shared_data_;
ResourceProviderContext* context3d_;
+ ResourceProviderContext* child_context_;
FakeOutputSurfaceClient output_surface_client_;
+ FakeOutputSurfaceClient child_output_surface_client_;
scoped_ptr<OutputSurface> output_surface_;
+ scoped_ptr<OutputSurface> child_output_surface_;
scoped_ptr<ResourceProvider> resource_provider_;
+ scoped_ptr<ResourceProvider> child_resource_provider_;
+ scoped_ptr<TestSharedBitmapManager> shared_bitmap_manager_;
};
void CheckCreateResource(ResourceProvider::ResourceType expected_default_type,
@@ -457,20 +532,20 @@ void CheckCreateResource(ResourceProvider::ResourceType expected_default_type,
gfx::Size size(1, 1);
ResourceFormat format = RGBA_8888;
- size_t pixel_size = TextureSize(size, format);
+ size_t pixel_size = TextureSizeBytes(size, format);
ASSERT_EQ(4U, pixel_size);
ResourceProvider::ResourceId id = resource_provider->CreateResource(
size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
EXPECT_EQ(1, static_cast<int>(resource_provider->num_resources()));
if (expected_default_type == ResourceProvider::GLTexture)
- EXPECT_EQ(0, context->texture_count());
+ EXPECT_EQ(0u, context->NumTextures());
uint8_t data[4] = { 1, 2, 3, 4 };
gfx::Rect rect(size);
resource_provider->SetPixels(id, data, rect, rect, gfx::Vector2d());
if (expected_default_type == ResourceProvider::GLTexture)
- EXPECT_EQ(1, context->texture_count());
+ EXPECT_EQ(1u, context->NumTextures());
uint8_t result[4] = { 0 };
GetResourcePixels(resource_provider, context, id, size, format, result);
@@ -479,7 +554,7 @@ void CheckCreateResource(ResourceProvider::ResourceType expected_default_type,
resource_provider->DeleteResource(id);
EXPECT_EQ(0, static_cast<int>(resource_provider->num_resources()));
if (expected_default_type == ResourceProvider::GLTexture)
- EXPECT_EQ(0, context->texture_count());
+ EXPECT_EQ(0u, context->NumTextures());
}
TEST_P(ResourceProviderTest, Basic) {
@@ -489,7 +564,7 @@ TEST_P(ResourceProviderTest, Basic) {
TEST_P(ResourceProviderTest, Upload) {
gfx::Size size(2, 2);
ResourceFormat format = RGBA_8888;
- size_t pixel_size = TextureSize(size, format);
+ size_t pixel_size = TextureSizeBytes(size, format);
ASSERT_EQ(16U, pixel_size);
ResourceProvider::ResourceId id = resource_provider_->CreateResource(
@@ -553,39 +628,38 @@ TEST_P(ResourceProviderTest, Upload) {
resource_provider_->DeleteResource(id);
}
-TEST_P(ResourceProviderTest, TransferResources) {
- // Resource transfer is only supported with GL textures for now.
+TEST_P(ResourceProviderTest, TransferGLResources) {
if (GetParam() != ResourceProvider::GLTexture)
return;
-
- scoped_ptr<ResourceProviderContext> child_context_owned(
- ResourceProviderContext::Create(shared_data_.get()));
- ResourceProviderContext* child_context = child_context_owned.get();
-
- FakeOutputSurfaceClient child_output_surface_client;
- scoped_ptr<OutputSurface> child_output_surface(
- FakeOutputSurface::Create3d(
- child_context_owned.PassAs<TestWebGraphicsContext3D>()));
- CHECK(child_output_surface->BindToClient(&child_output_surface_client));
-
- scoped_ptr<ResourceProvider> child_resource_provider(
- ResourceProvider::Create(child_output_surface.get(), 0, false));
-
gfx::Size size(1, 1);
ResourceFormat format = RGBA_8888;
- size_t pixel_size = TextureSize(size, format);
+ size_t pixel_size = TextureSizeBytes(size, format);
ASSERT_EQ(4U, pixel_size);
- ResourceProvider::ResourceId id1 = child_resource_provider->CreateResource(
+ ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
uint8_t data1[4] = { 1, 2, 3, 4 };
gfx::Rect rect(size);
- child_resource_provider->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
+ child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
- ResourceProvider::ResourceId id2 = child_resource_provider->CreateResource(
+ ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
uint8_t data2[4] = { 5, 5, 5, 5 };
- child_resource_provider->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
+ child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
+
+ GLuint external_texture_id = child_context_->createExternalTexture();
+ child_context_->bindTexture(GL_TEXTURE_EXTERNAL_OES, external_texture_id);
+
+ gpu::Mailbox external_mailbox;
+ child_context_->genMailboxCHROMIUM(external_mailbox.name);
+ child_context_->produceTextureCHROMIUM(GL_TEXTURE_EXTERNAL_OES,
+ external_mailbox.name);
+ const unsigned external_sync_point = child_context_->insertSyncPoint();
+ ResourceProvider::ResourceId id3 =
+ child_resource_provider_->CreateResourceFromTextureMailbox(
+ TextureMailbox(
+ external_mailbox, GL_TEXTURE_EXTERNAL_OES, external_sync_point),
+ SingleReleaseCallback::Create(base::Bind(&EmptyReleaseCallback)));
ReturnedResourceArray returned_to_child;
int child_id =
@@ -595,28 +669,37 @@ TEST_P(ResourceProviderTest, TransferResources) {
ResourceProvider::ResourceIdArray resource_ids_to_transfer;
resource_ids_to_transfer.push_back(id1);
resource_ids_to_transfer.push_back(id2);
+ resource_ids_to_transfer.push_back(id3);
TransferableResourceArray list;
- child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
- &list);
- ASSERT_EQ(2u, list.size());
+ child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
+ &list);
+ ASSERT_EQ(3u, list.size());
EXPECT_NE(0u, list[0].sync_point);
EXPECT_NE(0u, list[1].sync_point);
- EXPECT_TRUE(child_resource_provider->InUseByConsumer(id1));
- EXPECT_TRUE(child_resource_provider->InUseByConsumer(id2));
+ EXPECT_EQ(external_sync_point, list[2].sync_point);
+ EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[0].target);
+ EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[1].target);
+ EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), list[2].target);
+ EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
+ EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
+ EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
resource_provider_->ReceiveFromChild(child_id, list);
resource_provider_->DeclareUsedResourcesFromChild(child_id,
resource_ids_to_transfer);
}
- EXPECT_EQ(2u, resource_provider_->num_resources());
+ EXPECT_EQ(3u, resource_provider_->num_resources());
ResourceProvider::ResourceIdMap resource_map =
resource_provider_->GetChildToParentMap(child_id);
ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
+ ResourceProvider::ResourceId mapped_id3 = resource_map[id3];
EXPECT_NE(0u, mapped_id1);
EXPECT_NE(0u, mapped_id2);
+ EXPECT_NE(0u, mapped_id3);
EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
+ EXPECT_FALSE(resource_provider_->InUseByConsumer(id3));
uint8_t result[4] = { 0 };
GetResourcePixels(
@@ -626,22 +709,24 @@ TEST_P(ResourceProviderTest, TransferResources) {
GetResourcePixels(
resource_provider_.get(), context(), mapped_id2, size, format, result);
EXPECT_EQ(0, memcmp(data2, result, pixel_size));
+
{
// Check that transfering again the same resource from the child to the
// parent works.
ResourceProvider::ResourceIdArray resource_ids_to_transfer;
resource_ids_to_transfer.push_back(id1);
TransferableResourceArray list;
- child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
- &list);
+ child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
+ &list);
EXPECT_EQ(1u, list.size());
EXPECT_EQ(id1, list[0].id);
+ EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[0].target);
ReturnedResourceArray returned;
TransferableResource::ReturnResources(list, &returned);
- child_resource_provider->ReceiveReturnsFromParent(returned);
+ child_resource_provider_->ReceiveReturnsFromParent(returned);
// id1 was exported twice, we returned it only once, it should still be
// in-use.
- EXPECT_TRUE(child_resource_provider->InUseByConsumer(id1));
+ EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
}
{
EXPECT_EQ(0u, returned_to_child.size());
@@ -651,29 +736,34 @@ TEST_P(ResourceProviderTest, TransferResources) {
ResourceProvider::ResourceIdArray no_resources;
resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
- ASSERT_EQ(2u, returned_to_child.size());
+ ASSERT_EQ(3u, returned_to_child.size());
EXPECT_NE(0u, returned_to_child[0].sync_point);
EXPECT_NE(0u, returned_to_child[1].sync_point);
+ EXPECT_NE(0u, returned_to_child[2].sync_point);
EXPECT_FALSE(returned_to_child[0].lost);
EXPECT_FALSE(returned_to_child[1].lost);
- child_resource_provider->ReceiveReturnsFromParent(returned_to_child);
+ EXPECT_FALSE(returned_to_child[2].lost);
+ child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
returned_to_child.clear();
}
- EXPECT_FALSE(child_resource_provider->InUseByConsumer(id1));
- EXPECT_FALSE(child_resource_provider->InUseByConsumer(id2));
+ EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1));
+ EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2));
+ EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3));
{
- ResourceProvider::ScopedReadLockGL lock(child_resource_provider.get(), id1);
+ ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
+ id1);
ASSERT_NE(0U, lock.texture_id());
- child_context->bindTexture(GL_TEXTURE_2D, lock.texture_id());
- child_context->GetPixels(size, format, result);
+ child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
+ child_context_->GetPixels(size, format, result);
EXPECT_EQ(0, memcmp(data1, result, pixel_size));
}
{
- ResourceProvider::ScopedReadLockGL lock(child_resource_provider.get(), id2);
+ ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
+ id2);
ASSERT_NE(0U, lock.texture_id());
- child_context->bindTexture(GL_TEXTURE_2D, lock.texture_id());
- child_context->GetPixels(size, format, result);
+ child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
+ child_context_->GetPixels(size, format, result);
EXPECT_EQ(0, memcmp(data2, result, pixel_size));
}
{
@@ -681,14 +771,23 @@ TEST_P(ResourceProviderTest, TransferResources) {
ResourceProvider::ResourceIdArray resource_ids_to_transfer;
resource_ids_to_transfer.push_back(id1);
resource_ids_to_transfer.push_back(id2);
+ resource_ids_to_transfer.push_back(id3);
TransferableResourceArray list;
- child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
- &list);
- ASSERT_EQ(2u, list.size());
+ child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
+ &list);
+ ASSERT_EQ(3u, list.size());
+ EXPECT_EQ(id1, list[0].id);
+ EXPECT_EQ(id2, list[1].id);
+ EXPECT_EQ(id3, list[2].id);
EXPECT_NE(0u, list[0].sync_point);
EXPECT_NE(0u, list[1].sync_point);
- EXPECT_TRUE(child_resource_provider->InUseByConsumer(id1));
- EXPECT_TRUE(child_resource_provider->InUseByConsumer(id2));
+ EXPECT_NE(0u, list[2].sync_point);
+ EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[0].target);
+ EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[1].target);
+ EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), list[2].target);
+ EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
+ EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
+ EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
resource_provider_->ReceiveFromChild(child_id, list);
resource_provider_->DeclareUsedResourcesFromChild(child_id,
resource_ids_to_transfer);
@@ -696,20 +795,251 @@ TEST_P(ResourceProviderTest, TransferResources) {
EXPECT_EQ(0u, returned_to_child.size());
- EXPECT_EQ(2u, resource_provider_->num_resources());
+ EXPECT_EQ(3u, resource_provider_->num_resources());
resource_provider_->DestroyChild(child_id);
EXPECT_EQ(0u, resource_provider_->num_resources());
- ASSERT_EQ(2u, returned_to_child.size());
+ ASSERT_EQ(3u, returned_to_child.size());
EXPECT_NE(0u, returned_to_child[0].sync_point);
EXPECT_NE(0u, returned_to_child[1].sync_point);
+ EXPECT_NE(0u, returned_to_child[2].sync_point);
EXPECT_FALSE(returned_to_child[0].lost);
EXPECT_FALSE(returned_to_child[1].lost);
+ EXPECT_FALSE(returned_to_child[2].lost);
}
-TEST_P(ResourceProviderTest, DeleteExportedResources) {
- // Resource transfer is only supported with GL textures for now.
- if (GetParam() != ResourceProvider::GLTexture)
+TEST_P(ResourceProviderTest, TransferSoftwareResources) {
+ if (GetParam() != ResourceProvider::Bitmap)
+ return;
+
+ gfx::Size size(1, 1);
+ ResourceFormat format = RGBA_8888;
+ size_t pixel_size = TextureSizeBytes(size, format);
+ ASSERT_EQ(4U, pixel_size);
+
+ ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
+ size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+ uint8_t data1[4] = { 1, 2, 3, 4 };
+ gfx::Rect rect(size);
+ child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
+
+ ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
+ size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+ uint8_t data2[4] = { 5, 5, 5, 5 };
+ child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
+
+ scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory());
+ shared_memory->CreateAndMapAnonymous(1);
+ base::SharedMemory* shared_memory_ptr = shared_memory.get();
+ ResourceProvider::ResourceId id3 =
+ child_resource_provider_->CreateResourceFromTextureMailbox(
+ TextureMailbox(shared_memory_ptr, gfx::Size(1, 1)),
+ SingleReleaseCallback::Create(base::Bind(
+ &SharedMemoryReleaseCallback, base::Passed(&shared_memory))));
+
+ ReturnedResourceArray returned_to_child;
+ int child_id =
+ resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
+ {
+ // Transfer some resources to the parent.
+ ResourceProvider::ResourceIdArray resource_ids_to_transfer;
+ resource_ids_to_transfer.push_back(id1);
+ resource_ids_to_transfer.push_back(id2);
+ resource_ids_to_transfer.push_back(id3);
+ TransferableResourceArray list;
+ child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
+ &list);
+ ASSERT_EQ(3u, list.size());
+ EXPECT_EQ(0u, list[0].sync_point);
+ EXPECT_EQ(0u, list[1].sync_point);
+ EXPECT_EQ(0u, list[2].sync_point);
+ EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
+ EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
+ EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
+ resource_provider_->ReceiveFromChild(child_id, list);
+ resource_provider_->DeclareUsedResourcesFromChild(child_id,
+ resource_ids_to_transfer);
+ }
+
+ EXPECT_EQ(3u, resource_provider_->num_resources());
+ ResourceProvider::ResourceIdMap resource_map =
+ resource_provider_->GetChildToParentMap(child_id);
+ ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
+ ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
+ ResourceProvider::ResourceId mapped_id3 = resource_map[id3];
+ EXPECT_NE(0u, mapped_id1);
+ EXPECT_NE(0u, mapped_id2);
+ EXPECT_NE(0u, mapped_id3);
+ EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
+ EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
+ EXPECT_FALSE(resource_provider_->InUseByConsumer(id3));
+
+ uint8_t result[4] = { 0 };
+ GetResourcePixels(
+ resource_provider_.get(), context(), mapped_id1, size, format, result);
+ EXPECT_EQ(0, memcmp(data1, result, pixel_size));
+
+ GetResourcePixels(
+ resource_provider_.get(), context(), mapped_id2, size, format, result);
+ EXPECT_EQ(0, memcmp(data2, result, pixel_size));
+
+ {
+ // Check that transfering again the same resource from the child to the
+ // parent works.
+ ResourceProvider::ResourceIdArray resource_ids_to_transfer;
+ resource_ids_to_transfer.push_back(id1);
+ TransferableResourceArray list;
+ child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
+ &list);
+ EXPECT_EQ(1u, list.size());
+ EXPECT_EQ(id1, list[0].id);
+ ReturnedResourceArray returned;
+ TransferableResource::ReturnResources(list, &returned);
+ child_resource_provider_->ReceiveReturnsFromParent(returned);
+ // id1 was exported twice, we returned it only once, it should still be
+ // in-use.
+ EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
+ }
+ {
+ EXPECT_EQ(0u, returned_to_child.size());
+
+ // Transfer resources back from the parent to the child. Set no resources as
+ // being in use.
+ ResourceProvider::ResourceIdArray no_resources;
+ resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
+
+ ASSERT_EQ(3u, returned_to_child.size());
+ EXPECT_EQ(0u, returned_to_child[0].sync_point);
+ EXPECT_EQ(0u, returned_to_child[1].sync_point);
+ EXPECT_EQ(0u, returned_to_child[2].sync_point);
+ EXPECT_EQ(id1, returned_to_child[0].id);
+ EXPECT_EQ(id2, returned_to_child[1].id);
+ EXPECT_EQ(id3, returned_to_child[2].id);
+ EXPECT_FALSE(returned_to_child[0].lost);
+ EXPECT_FALSE(returned_to_child[1].lost);
+ EXPECT_FALSE(returned_to_child[2].lost);
+ child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
+ returned_to_child.clear();
+ }
+ EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1));
+ EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2));
+ EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3));
+
+ {
+ ResourceProvider::ScopedReadLockSoftware lock(
+ child_resource_provider_.get(), id1);
+ const SkBitmap* sk_bitmap = lock.sk_bitmap();
+ EXPECT_EQ(sk_bitmap->width(), size.width());
+ EXPECT_EQ(sk_bitmap->height(), size.height());
+ EXPECT_EQ(0, memcmp(data1, sk_bitmap->getPixels(), pixel_size));
+ }
+ {
+ ResourceProvider::ScopedReadLockSoftware lock(
+ child_resource_provider_.get(), id2);
+ const SkBitmap* sk_bitmap = lock.sk_bitmap();
+ EXPECT_EQ(sk_bitmap->width(), size.width());
+ EXPECT_EQ(sk_bitmap->height(), size.height());
+ EXPECT_EQ(0, memcmp(data2, sk_bitmap->getPixels(), pixel_size));
+ }
+ {
+ // Transfer resources to the parent again.
+ ResourceProvider::ResourceIdArray resource_ids_to_transfer;
+ resource_ids_to_transfer.push_back(id1);
+ resource_ids_to_transfer.push_back(id2);
+ resource_ids_to_transfer.push_back(id3);
+ TransferableResourceArray list;
+ child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
+ &list);
+ ASSERT_EQ(3u, list.size());
+ EXPECT_EQ(id1, list[0].id);
+ EXPECT_EQ(id2, list[1].id);
+ EXPECT_EQ(id3, list[2].id);
+ EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
+ EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
+ EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
+ resource_provider_->ReceiveFromChild(child_id, list);
+ resource_provider_->DeclareUsedResourcesFromChild(child_id,
+ resource_ids_to_transfer);
+ }
+
+ EXPECT_EQ(0u, returned_to_child.size());
+
+ EXPECT_EQ(3u, resource_provider_->num_resources());
+ resource_provider_->DestroyChild(child_id);
+ EXPECT_EQ(0u, resource_provider_->num_resources());
+
+ ASSERT_EQ(3u, returned_to_child.size());
+ EXPECT_EQ(0u, returned_to_child[0].sync_point);
+ EXPECT_EQ(0u, returned_to_child[1].sync_point);
+ EXPECT_EQ(0u, returned_to_child[2].sync_point);
+ EXPECT_EQ(id1, returned_to_child[0].id);
+ EXPECT_EQ(id2, returned_to_child[1].id);
+ EXPECT_EQ(id3, returned_to_child[2].id);
+ EXPECT_FALSE(returned_to_child[0].lost);
+ EXPECT_FALSE(returned_to_child[1].lost);
+ EXPECT_FALSE(returned_to_child[2].lost);
+}
+
+TEST_P(ResourceProviderTest, TransferSoftwareToNonUber) {
+ // TODO(jbauman): Remove test when shared bitmap manager available
+ // everywhere.
+ if (GetParam() != ResourceProvider::Bitmap)
+ return;
+
+ scoped_ptr<FakeOutputSurface> parent_output_surface =
+ FakeOutputSurface::CreateSoftware(
+ make_scoped_ptr(new SoftwareOutputDevice));
+ FakeOutputSurfaceClient parent_output_surface_client;
+ CHECK(parent_output_surface->BindToClient(&parent_output_surface_client));
+
+ scoped_ptr<ResourceProvider> parent_resource_provider(
+ ResourceProvider::Create(parent_output_surface.get(),
+ NULL,
+ 0,
+ false,
+ 1));
+
+ gfx::Size size(1, 1);
+ ResourceFormat format = RGBA_8888;
+ size_t pixel_size = TextureSizeBytes(size, format);
+ ASSERT_EQ(4U, pixel_size);
+
+ ResourceProvider::ResourceId id1 = resource_provider_->CreateResource(
+ size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+ uint8_t data1[4] = { 1, 2, 3, 4 };
+ gfx::Rect rect(size);
+ resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
+
+ ReturnedResourceArray returned_to_child;
+ int child_id = parent_resource_provider->CreateChild(
+ GetReturnCallback(&returned_to_child));
+ {
+ ResourceProvider::ResourceIdArray resource_ids_to_transfer;
+ resource_ids_to_transfer.push_back(id1);
+ TransferableResourceArray list;
+ resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
+ ASSERT_EQ(1u, list.size());
+ EXPECT_TRUE(resource_provider_->InUseByConsumer(id1));
+ parent_resource_provider->ReceiveFromChild(child_id, list);
+ }
+
+ EXPECT_EQ(0u, parent_resource_provider->num_resources());
+ ASSERT_EQ(1u, returned_to_child.size());
+ EXPECT_EQ(returned_to_child[0].id, id1);
+ ResourceProvider::ResourceIdMap resource_map =
+ parent_resource_provider->GetChildToParentMap(child_id);
+ ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
+ EXPECT_EQ(0u, mapped_id1);
+
+ parent_resource_provider->DestroyChild(child_id);
+ EXPECT_EQ(0u, parent_resource_provider->num_resources());
+
+ ASSERT_EQ(1u, returned_to_child.size());
+ EXPECT_FALSE(returned_to_child[0].lost);
+}
+
+TEST_P(ResourceProviderTest, TransferGLToSoftware) {
+ if (GetParam() != ResourceProvider::Bitmap)
return;
scoped_ptr<ResourceProviderContext> child_context_owned(
@@ -721,23 +1051,116 @@ TEST_P(ResourceProviderTest, DeleteExportedResources) {
CHECK(child_output_surface->BindToClient(&child_output_surface_client));
scoped_ptr<ResourceProvider> child_resource_provider(
- ResourceProvider::Create(child_output_surface.get(), 0, false));
+ ResourceProvider::Create(child_output_surface.get(),
+ NULL,
+ 0,
+ false,
+ 1));
gfx::Size size(1, 1);
ResourceFormat format = RGBA_8888;
- size_t pixel_size = TextureSize(size, format);
+ size_t pixel_size = TextureSizeBytes(size, format);
ASSERT_EQ(4U, pixel_size);
ResourceProvider::ResourceId id1 = child_resource_provider->CreateResource(
size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
- uint8_t data1[4] = {1, 2, 3, 4};
+ uint8_t data1[4] = { 1, 2, 3, 4 };
gfx::Rect rect(size);
child_resource_provider->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
- ResourceProvider::ResourceId id2 = child_resource_provider->CreateResource(
+ ReturnedResourceArray returned_to_child;
+ int child_id =
+ resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
+ {
+ ResourceProvider::ResourceIdArray resource_ids_to_transfer;
+ resource_ids_to_transfer.push_back(id1);
+ TransferableResourceArray list;
+ child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
+ &list);
+ ASSERT_EQ(1u, list.size());
+ EXPECT_NE(0u, list[0].sync_point);
+ EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[0].target);
+ EXPECT_TRUE(child_resource_provider->InUseByConsumer(id1));
+ resource_provider_->ReceiveFromChild(child_id, list);
+ }
+
+ EXPECT_EQ(0u, resource_provider_->num_resources());
+ ASSERT_EQ(1u, returned_to_child.size());
+ EXPECT_EQ(returned_to_child[0].id, id1);
+ ResourceProvider::ResourceIdMap resource_map =
+ resource_provider_->GetChildToParentMap(child_id);
+ ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
+ EXPECT_EQ(0u, mapped_id1);
+
+ resource_provider_->DestroyChild(child_id);
+ EXPECT_EQ(0u, resource_provider_->num_resources());
+
+ ASSERT_EQ(1u, returned_to_child.size());
+ EXPECT_FALSE(returned_to_child[0].lost);
+}
+
+TEST_P(ResourceProviderTest, TransferInvalidSoftware) {
+ if (GetParam() != ResourceProvider::Bitmap)
+ return;
+
+ gfx::Size size(1, 1);
+ ResourceFormat format = RGBA_8888;
+ size_t pixel_size = TextureSizeBytes(size, format);
+ ASSERT_EQ(4U, pixel_size);
+
+ ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
+ size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+ uint8_t data1[4] = { 1, 2, 3, 4 };
+ gfx::Rect rect(size);
+ child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
+
+ ReturnedResourceArray returned_to_child;
+ int child_id =
+ resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
+ {
+ ResourceProvider::ResourceIdArray resource_ids_to_transfer;
+ resource_ids_to_transfer.push_back(id1);
+ TransferableResourceArray list;
+ child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
+ &list);
+ ASSERT_EQ(1u, list.size());
+ // Make invalid.
+ list[0].mailbox.name[1] = 5;
+ EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
+ resource_provider_->ReceiveFromChild(child_id, list);
+ }
+
+ EXPECT_EQ(0u, resource_provider_->num_resources());
+ ASSERT_EQ(1u, returned_to_child.size());
+ EXPECT_EQ(returned_to_child[0].id, id1);
+ ResourceProvider::ResourceIdMap resource_map =
+ resource_provider_->GetChildToParentMap(child_id);
+ ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
+ EXPECT_EQ(0u, mapped_id1);
+
+ resource_provider_->DestroyChild(child_id);
+ EXPECT_EQ(0u, resource_provider_->num_resources());
+
+ ASSERT_EQ(1u, returned_to_child.size());
+ EXPECT_FALSE(returned_to_child[0].lost);
+}
+
+TEST_P(ResourceProviderTest, DeleteExportedResources) {
+ gfx::Size size(1, 1);
+ ResourceFormat format = RGBA_8888;
+ size_t pixel_size = TextureSizeBytes(size, format);
+ ASSERT_EQ(4U, pixel_size);
+
+ ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
+ size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+ uint8_t data1[4] = { 1, 2, 3, 4 };
+ gfx::Rect rect(size);
+ child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
+
+ ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
uint8_t data2[4] = {5, 5, 5, 5};
- child_resource_provider->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
+ child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
ReturnedResourceArray returned_to_child;
int child_id =
@@ -748,13 +1171,15 @@ TEST_P(ResourceProviderTest, DeleteExportedResources) {
resource_ids_to_transfer.push_back(id1);
resource_ids_to_transfer.push_back(id2);
TransferableResourceArray list;
- child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
- &list);
+ child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
+ &list);
ASSERT_EQ(2u, list.size());
- EXPECT_NE(0u, list[0].sync_point);
- EXPECT_NE(0u, list[1].sync_point);
- EXPECT_TRUE(child_resource_provider->InUseByConsumer(id1));
- EXPECT_TRUE(child_resource_provider->InUseByConsumer(id2));
+ if (GetParam() == ResourceProvider::GLTexture) {
+ EXPECT_NE(0u, list[0].sync_point);
+ EXPECT_NE(0u, list[1].sync_point);
+ }
+ EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
+ EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
resource_provider_->ReceiveFromChild(child_id, list);
resource_provider_->DeclareUsedResourcesFromChild(child_id,
resource_ids_to_transfer);
@@ -779,8 +1204,10 @@ TEST_P(ResourceProviderTest, DeleteExportedResources) {
resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
ASSERT_EQ(2u, list.size());
- EXPECT_NE(0u, list[0].sync_point);
- EXPECT_NE(0u, list[1].sync_point);
+ if (GetParam() == ResourceProvider::GLTexture) {
+ EXPECT_NE(0u, list[0].sync_point);
+ EXPECT_NE(0u, list[1].sync_point);
+ }
EXPECT_TRUE(resource_provider_->InUseByConsumer(id1));
EXPECT_TRUE(resource_provider_->InUseByConsumer(id2));
@@ -803,44 +1230,31 @@ TEST_P(ResourceProviderTest, DeleteExportedResources) {
EXPECT_EQ(0u, resource_provider_->num_resources());
ASSERT_EQ(2u, returned_to_child.size());
- EXPECT_NE(0u, returned_to_child[0].sync_point);
- EXPECT_NE(0u, returned_to_child[1].sync_point);
+ if (GetParam() == ResourceProvider::GLTexture) {
+ EXPECT_NE(0u, returned_to_child[0].sync_point);
+ EXPECT_NE(0u, returned_to_child[1].sync_point);
+ }
EXPECT_FALSE(returned_to_child[0].lost);
EXPECT_FALSE(returned_to_child[1].lost);
}
}
TEST_P(ResourceProviderTest, DestroyChildWithExportedResources) {
- // Resource transfer is only supported with GL textures for now.
- if (GetParam() != ResourceProvider::GLTexture)
- return;
-
- scoped_ptr<ResourceProviderContext> child_context_owned(
- ResourceProviderContext::Create(shared_data_.get()));
-
- FakeOutputSurfaceClient child_output_surface_client;
- scoped_ptr<OutputSurface> child_output_surface(FakeOutputSurface::Create3d(
- child_context_owned.PassAs<TestWebGraphicsContext3D>()));
- CHECK(child_output_surface->BindToClient(&child_output_surface_client));
-
- scoped_ptr<ResourceProvider> child_resource_provider(
- ResourceProvider::Create(child_output_surface.get(), 0, false));
-
gfx::Size size(1, 1);
ResourceFormat format = RGBA_8888;
- size_t pixel_size = TextureSize(size, format);
+ size_t pixel_size = TextureSizeBytes(size, format);
ASSERT_EQ(4U, pixel_size);
- ResourceProvider::ResourceId id1 = child_resource_provider->CreateResource(
+ ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
uint8_t data1[4] = {1, 2, 3, 4};
gfx::Rect rect(size);
- child_resource_provider->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
+ child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
- ResourceProvider::ResourceId id2 = child_resource_provider->CreateResource(
+ ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
uint8_t data2[4] = {5, 5, 5, 5};
- child_resource_provider->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
+ child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
ReturnedResourceArray returned_to_child;
int child_id =
@@ -851,13 +1265,15 @@ TEST_P(ResourceProviderTest, DestroyChildWithExportedResources) {
resource_ids_to_transfer.push_back(id1);
resource_ids_to_transfer.push_back(id2);
TransferableResourceArray list;
- child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
- &list);
+ child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
+ &list);
ASSERT_EQ(2u, list.size());
- EXPECT_NE(0u, list[0].sync_point);
- EXPECT_NE(0u, list[1].sync_point);
- EXPECT_TRUE(child_resource_provider->InUseByConsumer(id1));
- EXPECT_TRUE(child_resource_provider->InUseByConsumer(id2));
+ if (GetParam() == ResourceProvider::GLTexture) {
+ EXPECT_NE(0u, list[0].sync_point);
+ EXPECT_NE(0u, list[1].sync_point);
+ }
+ EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
+ EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
resource_provider_->ReceiveFromChild(child_id, list);
resource_provider_->DeclareUsedResourcesFromChild(child_id,
resource_ids_to_transfer);
@@ -882,8 +1298,10 @@ TEST_P(ResourceProviderTest, DestroyChildWithExportedResources) {
resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
ASSERT_EQ(2u, list.size());
- EXPECT_NE(0u, list[0].sync_point);
- EXPECT_NE(0u, list[1].sync_point);
+ if (GetParam() == ResourceProvider::GLTexture) {
+ EXPECT_NE(0u, list[0].sync_point);
+ EXPECT_NE(0u, list[1].sync_point);
+ }
EXPECT_TRUE(resource_provider_->InUseByConsumer(id1));
EXPECT_TRUE(resource_provider_->InUseByConsumer(id2));
@@ -892,61 +1310,57 @@ TEST_P(ResourceProviderTest, DestroyChildWithExportedResources) {
ResourceProvider::ResourceIdArray no_resources;
resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
- // Destroy the child, the resources should be returned immediately from the
- // parent and marked as lost.
+ // Destroy the child, the resources should not be returned yet.
EXPECT_EQ(0u, returned_to_child.size());
EXPECT_EQ(2u, resource_provider_->num_resources());
resource_provider_->DestroyChild(child_id);
- EXPECT_EQ(0u, resource_provider_->num_resources());
- ASSERT_EQ(2u, returned_to_child.size());
- EXPECT_NE(0u, returned_to_child[0].sync_point);
- EXPECT_NE(0u, returned_to_child[1].sync_point);
- EXPECT_TRUE(returned_to_child[0].lost);
- EXPECT_TRUE(returned_to_child[1].lost);
- returned_to_child.clear();
+ EXPECT_EQ(2u, resource_provider_->num_resources());
+ ASSERT_EQ(0u, returned_to_child.size());
- // Return the resources from the grandparent to the parent. They should be
- // dropped on the floor since they were already returned to the child.
+ // Return a resource from the grandparent, it should be returned at this
+ // point.
EXPECT_EQ(2u, list.size());
EXPECT_EQ(mapped_id1, list[0].id);
EXPECT_EQ(mapped_id2, list[1].id);
+ TransferableResourceArray return_list;
+ return_list.push_back(list[1]);
+ list.pop_back();
ReturnedResourceArray returned;
- TransferableResource::ReturnResources(list, &returned);
+ TransferableResource::ReturnResources(return_list, &returned);
resource_provider_->ReceiveReturnsFromParent(returned);
- EXPECT_EQ(0u, returned_to_child.size());
+ EXPECT_EQ(1u, resource_provider_->num_resources());
+ ASSERT_EQ(1u, returned_to_child.size());
+ if (GetParam() == ResourceProvider::GLTexture) {
+ EXPECT_NE(0u, returned_to_child[0].sync_point);
+ }
+ EXPECT_FALSE(returned_to_child[0].lost);
+ returned_to_child.clear();
+
+ // Destroy the parent resource provider. The resource that's left should be
+ // lost at this point, and returned.
+ resource_provider_.reset();
+ ASSERT_EQ(1u, returned_to_child.size());
+ if (GetParam() == ResourceProvider::GLTexture) {
+ EXPECT_NE(0u, returned_to_child[0].sync_point);
+ }
+ EXPECT_TRUE(returned_to_child[0].lost);
}
}
TEST_P(ResourceProviderTest, DeleteTransferredResources) {
- // Resource transfer is only supported with GL textures for now.
- if (GetParam() != ResourceProvider::GLTexture)
- return;
-
- scoped_ptr<ResourceProviderContext> child_context_owned(
- ResourceProviderContext::Create(shared_data_.get()));
-
- FakeOutputSurfaceClient child_output_surface_client;
- scoped_ptr<OutputSurface> child_output_surface(
- FakeOutputSurface::Create3d(
- child_context_owned.PassAs<TestWebGraphicsContext3D>()));
- CHECK(child_output_surface->BindToClient(&child_output_surface_client));
-
- scoped_ptr<ResourceProvider> child_resource_provider(
- ResourceProvider::Create(child_output_surface.get(), 0, false));
-
gfx::Size size(1, 1);
ResourceFormat format = RGBA_8888;
- size_t pixel_size = TextureSize(size, format);
+ size_t pixel_size = TextureSizeBytes(size, format);
ASSERT_EQ(4U, pixel_size);
- ResourceProvider::ResourceId id = child_resource_provider->CreateResource(
+ ResourceProvider::ResourceId id = child_resource_provider_->CreateResource(
size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
uint8_t data[4] = { 1, 2, 3, 4 };
gfx::Rect rect(size);
- child_resource_provider->SetPixels(id, data, rect, rect, gfx::Vector2d());
+ child_resource_provider_->SetPixels(id, data, rect, rect, gfx::Vector2d());
ReturnedResourceArray returned_to_child;
int child_id =
@@ -956,19 +1370,20 @@ TEST_P(ResourceProviderTest, DeleteTransferredResources) {
ResourceProvider::ResourceIdArray resource_ids_to_transfer;
resource_ids_to_transfer.push_back(id);
TransferableResourceArray list;
- child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
- &list);
+ child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
+ &list);
ASSERT_EQ(1u, list.size());
- EXPECT_NE(0u, list[0].sync_point);
- EXPECT_TRUE(child_resource_provider->InUseByConsumer(id));
+ if (GetParam() == ResourceProvider::GLTexture)
+ EXPECT_NE(0u, list[0].sync_point);
+ EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
resource_provider_->ReceiveFromChild(child_id, list);
resource_provider_->DeclareUsedResourcesFromChild(child_id,
resource_ids_to_transfer);
}
// Delete textures in the child, while they are transfered.
- child_resource_provider->DeleteResource(id);
- EXPECT_EQ(1u, child_resource_provider->num_resources());
+ child_resource_provider_->DeleteResource(id);
+ EXPECT_EQ(1u, child_resource_provider_->num_resources());
{
EXPECT_EQ(0u, returned_to_child.size());
@@ -978,10 +1393,11 @@ TEST_P(ResourceProviderTest, DeleteTransferredResources) {
resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
ASSERT_EQ(1u, returned_to_child.size());
- EXPECT_NE(0u, returned_to_child[0].sync_point);
- child_resource_provider->ReceiveReturnsFromParent(returned_to_child);
+ if (GetParam() == ResourceProvider::GLTexture)
+ EXPECT_NE(0u, returned_to_child[0].sync_point);
+ child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
}
- EXPECT_EQ(0u, child_resource_provider->num_resources());
+ EXPECT_EQ(0u, child_resource_provider_->num_resources());
}
class ResourceProviderTestTextureFilters : public ResourceProviderTest {
@@ -997,7 +1413,11 @@ class ResourceProviderTestTextureFilters : public ResourceProviderTest {
CHECK(child_output_surface->BindToClient(&child_output_surface_client));
scoped_ptr<ResourceProvider> child_resource_provider(
- ResourceProvider::Create(child_output_surface.get(), 0, false));
+ ResourceProvider::Create(child_output_surface.get(),
+ NULL,
+ 0,
+ false,
+ 1));
scoped_ptr<TextureStateTrackingContext> parent_context_owned(
new TextureStateTrackingContext);
@@ -1009,20 +1429,25 @@ class ResourceProviderTestTextureFilters : public ResourceProviderTest {
CHECK(parent_output_surface->BindToClient(&parent_output_surface_client));
scoped_ptr<ResourceProvider> parent_resource_provider(
- ResourceProvider::Create(parent_output_surface.get(), 0, false));
+ ResourceProvider::Create(parent_output_surface.get(),
+ NULL,
+ 0,
+ false,
+ 1));
gfx::Size size(1, 1);
ResourceFormat format = RGBA_8888;
- int texture_id = 1;
+ int child_texture_id = 1;
+ int parent_texture_id = 2;
- size_t pixel_size = TextureSize(size, format);
+ size_t pixel_size = TextureSizeBytes(size, format);
ASSERT_EQ(4U, pixel_size);
ResourceProvider::ResourceId id = child_resource_provider->CreateResource(
size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
// The new texture is created with GL_LINEAR.
- EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, texture_id))
+ EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id))
.Times(2); // Once to create and once to allocate.
EXPECT_CALL(*child_context,
texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
@@ -1044,12 +1469,12 @@ class ResourceProviderTestTextureFilters : public ResourceProviderTest {
uint8_t data[4] = { 1, 2, 3, 4 };
gfx::Rect rect(size);
- EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, texture_id));
+ EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
child_resource_provider->SetPixels(id, data, rect, rect, gfx::Vector2d());
Mock::VerifyAndClearExpectations(child_context);
// The texture is set to |child_filter| in the child.
- EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, texture_id));
+ EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
if (child_filter != GL_LINEAR) {
EXPECT_CALL(
*child_context,
@@ -1070,7 +1495,7 @@ class ResourceProviderTestTextureFilters : public ResourceProviderTest {
resource_ids_to_transfer.push_back(id);
TransferableResourceArray list;
- EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, texture_id));
+ EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
EXPECT_CALL(*child_context,
produceTextureCHROMIUM(GL_TEXTURE_2D, _));
EXPECT_CALL(*child_context, insertSyncPoint());
@@ -1081,9 +1506,9 @@ class ResourceProviderTestTextureFilters : public ResourceProviderTest {
ASSERT_EQ(1u, list.size());
EXPECT_EQ(static_cast<unsigned>(child_filter), list[0].filter);
- EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, texture_id));
EXPECT_CALL(*parent_context,
- consumeTextureCHROMIUM(GL_TEXTURE_2D, _));
+ bindTexture(GL_TEXTURE_2D, parent_texture_id));
+ EXPECT_CALL(*parent_context, consumeTextureCHROMIUM(GL_TEXTURE_2D, _));
parent_resource_provider->ReceiveFromChild(child_id, list);
Mock::VerifyAndClearExpectations(parent_context);
@@ -1097,7 +1522,7 @@ class ResourceProviderTestTextureFilters : public ResourceProviderTest {
EXPECT_NE(0u, mapped_id);
// The texture is set to |parent_filter| in the parent.
- EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, texture_id));
+ EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, parent_texture_id));
EXPECT_CALL(
*parent_context,
texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, parent_filter));
@@ -1109,7 +1534,7 @@ class ResourceProviderTestTextureFilters : public ResourceProviderTest {
// The texture should be reset to |child_filter| in the parent when it is
// returned, since that is how it was received.
- EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, texture_id));
+ EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, parent_texture_id));
EXPECT_CALL(
*parent_context,
texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, child_filter));
@@ -1133,7 +1558,7 @@ class ResourceProviderTestTextureFilters : public ResourceProviderTest {
}
// The child remembers the texture filter is set to |child_filter|.
- EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, texture_id));
+ EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
SetResourceFilter(child_resource_provider.get(), id, child_filter);
Mock::VerifyAndClearExpectations(child_context);
}
@@ -1151,16 +1576,8 @@ TEST_P(ResourceProviderTest, TextureFilters_ChildLinearParentNearest) {
ResourceProviderTestTextureFilters::RunTest(GL_LINEAR, GL_NEAREST);
}
-void ReleaseTextureMailbox(unsigned* release_sync_point,
- bool* release_lost_resource,
- unsigned sync_point,
- bool lost_resource) {
- *release_sync_point = sync_point;
- *release_lost_resource = lost_resource;
-}
-
TEST_P(ResourceProviderTest, TransferMailboxResources) {
- // Resource transfer is only supported with GL textures for now.
+ // Other mailbox transfers tested elsewhere.
if (GetParam() != ResourceProvider::GLTexture)
return;
unsigned texture = context()->createTexture();
@@ -1184,7 +1601,7 @@ TEST_P(ResourceProviderTest, TransferMailboxResources) {
resource_provider_->CreateResourceFromTextureMailbox(
TextureMailbox(mailbox, sync_point),
SingleReleaseCallback::Create(callback));
- EXPECT_EQ(1, context()->texture_count());
+ EXPECT_EQ(1u, context()->NumTextures());
EXPECT_EQ(0u, release_sync_point);
{
// Transfer the resource, expect the sync points to be consistent.
@@ -1216,7 +1633,7 @@ TEST_P(ResourceProviderTest, TransferMailboxResources) {
ReturnedResourceArray returned;
TransferableResource::ReturnResources(list, &returned);
resource_provider_->ReceiveReturnsFromParent(returned);
- EXPECT_EQ(1, context()->texture_count());
+ EXPECT_EQ(1u, context()->NumTextures());
EXPECT_EQ(0u, release_sync_point);
resource_provider_->DeleteResource(resource);
@@ -1232,7 +1649,7 @@ TEST_P(ResourceProviderTest, TransferMailboxResources) {
resource = resource_provider_->CreateResourceFromTextureMailbox(
TextureMailbox(mailbox, sync_point),
SingleReleaseCallback::Create(callback));
- EXPECT_EQ(1, context()->texture_count());
+ EXPECT_EQ(1u, context()->NumTextures());
EXPECT_EQ(0u, release_sync_point);
{
// Transfer the resource, expect the sync points to be consistent.
@@ -1261,7 +1678,7 @@ TEST_P(ResourceProviderTest, TransferMailboxResources) {
// Delete the resource, which shouldn't do anything.
resource_provider_->DeleteResource(resource);
- EXPECT_EQ(1, context()->texture_count());
+ EXPECT_EQ(1u, context()->NumTextures());
EXPECT_EQ(0u, release_sync_point);
// Then receive the resource which should release the mailbox, expect the
@@ -1280,27 +1697,14 @@ TEST_P(ResourceProviderTest, TransferMailboxResources) {
}
TEST_P(ResourceProviderTest, LostResourceInParent) {
- // Resource transfer is only supported with GL textures for now.
- if (GetParam() != ResourceProvider::GLTexture)
- return;
-
- scoped_ptr<ResourceProviderContext> child_context_owned(
- ResourceProviderContext::Create(shared_data_.get()));
-
- FakeOutputSurfaceClient child_output_surface_client;
- scoped_ptr<OutputSurface> child_output_surface(FakeOutputSurface::Create3d(
- child_context_owned.PassAs<TestWebGraphicsContext3D>()));
- CHECK(child_output_surface->BindToClient(&child_output_surface_client));
-
- scoped_ptr<ResourceProvider> child_resource_provider(
- ResourceProvider::Create(child_output_surface.get(), 0, false));
-
gfx::Size size(1, 1);
ResourceFormat format = RGBA_8888;
ResourceProvider::ResourceId resource =
- child_resource_provider->CreateResource(
+ child_resource_provider_->CreateResource(
size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
- child_resource_provider->AllocateForTesting(resource);
+ child_resource_provider_->AllocateForTesting(resource);
+ // Expect a GL resource to be lost.
+ bool should_lose_resource = GetParam() == ResourceProvider::GLTexture;
ReturnedResourceArray returned_to_child;
int child_id =
@@ -1310,8 +1714,8 @@ TEST_P(ResourceProviderTest, LostResourceInParent) {
ResourceProvider::ResourceIdArray resource_ids_to_transfer;
resource_ids_to_transfer.push_back(resource);
TransferableResourceArray list;
- child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
- &list);
+ child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
+ &list);
EXPECT_EQ(1u, list.size());
resource_provider_->ReceiveFromChild(child_id, list);
@@ -1330,42 +1734,28 @@ TEST_P(ResourceProviderTest, LostResourceInParent) {
ResourceProvider::ResourceIdArray no_resources;
resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
- // Expect the resource to be lost.
+ // Expect a GL resource to be lost.
ASSERT_EQ(1u, returned_to_child.size());
- EXPECT_TRUE(returned_to_child[0].lost);
- child_resource_provider->ReceiveReturnsFromParent(returned_to_child);
+ EXPECT_EQ(should_lose_resource, returned_to_child[0].lost);
+ child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
returned_to_child.clear();
}
- // The resource should be lost.
- EXPECT_TRUE(child_resource_provider->IsLost(resource));
+ // A GL resource should be lost.
+ EXPECT_EQ(should_lose_resource, child_resource_provider_->IsLost(resource));
// Lost resources stay in use in the parent forever.
- EXPECT_TRUE(child_resource_provider->InUseByConsumer(resource));
+ EXPECT_EQ(should_lose_resource,
+ child_resource_provider_->InUseByConsumer(resource));
}
TEST_P(ResourceProviderTest, LostResourceInGrandParent) {
- // Resource transfer is only supported with GL textures for now.
- if (GetParam() != ResourceProvider::GLTexture)
- return;
-
- scoped_ptr<ResourceProviderContext> child_context_owned(
- ResourceProviderContext::Create(shared_data_.get()));
-
- FakeOutputSurfaceClient child_output_surface_client;
- scoped_ptr<OutputSurface> child_output_surface(FakeOutputSurface::Create3d(
- child_context_owned.PassAs<TestWebGraphicsContext3D>()));
- CHECK(child_output_surface->BindToClient(&child_output_surface_client));
-
- scoped_ptr<ResourceProvider> child_resource_provider(
- ResourceProvider::Create(child_output_surface.get(), 0, false));
-
gfx::Size size(1, 1);
ResourceFormat format = RGBA_8888;
ResourceProvider::ResourceId resource =
- child_resource_provider->CreateResource(
+ child_resource_provider_->CreateResource(
size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
- child_resource_provider->AllocateForTesting(resource);
+ child_resource_provider_->AllocateForTesting(resource);
ReturnedResourceArray returned_to_child;
int child_id =
@@ -1375,8 +1765,8 @@ TEST_P(ResourceProviderTest, LostResourceInGrandParent) {
ResourceProvider::ResourceIdArray resource_ids_to_transfer;
resource_ids_to_transfer.push_back(resource);
TransferableResourceArray list;
- child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
- &list);
+ child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
+ &list);
EXPECT_EQ(1u, list.size());
resource_provider_->ReceiveFromChild(child_id, list);
@@ -1424,47 +1814,24 @@ TEST_P(ResourceProviderTest, LostResourceInGrandParent) {
// Expect the resource to be lost.
ASSERT_EQ(1u, returned_to_child.size());
EXPECT_TRUE(returned_to_child[0].lost);
- child_resource_provider->ReceiveReturnsFromParent(returned_to_child);
+ child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
returned_to_child.clear();
}
// The resource should be lost.
- EXPECT_TRUE(child_resource_provider->IsLost(resource));
+ EXPECT_TRUE(child_resource_provider_->IsLost(resource));
// Lost resources stay in use in the parent forever.
- EXPECT_TRUE(child_resource_provider->InUseByConsumer(resource));
+ EXPECT_TRUE(child_resource_provider_->InUseByConsumer(resource));
}
TEST_P(ResourceProviderTest, LostMailboxInParent) {
- // Resource transfer is only supported with GL textures for now.
- if (GetParam() != ResourceProvider::GLTexture)
- return;
-
- scoped_ptr<ResourceProviderContext> child_context_owned(
- ResourceProviderContext::Create(shared_data_.get()));
- ResourceProviderContext* child_context = child_context_owned.get();
-
- FakeOutputSurfaceClient child_output_surface_client;
- scoped_ptr<OutputSurface> child_output_surface(FakeOutputSurface::Create3d(
- child_context_owned.PassAs<TestWebGraphicsContext3D>()));
- CHECK(child_output_surface->BindToClient(&child_output_surface_client));
-
- scoped_ptr<ResourceProvider> child_resource_provider(
- ResourceProvider::Create(child_output_surface.get(), 0, false));
-
- unsigned texture = child_context->createTexture();
- gpu::Mailbox gpu_mailbox;
- child_context->bindTexture(GL_TEXTURE_2D, texture);
- child_context->genMailboxCHROMIUM(gpu_mailbox.name);
- child_context->produceTextureCHROMIUM(GL_TEXTURE_2D, gpu_mailbox.name);
-
unsigned release_sync_point = 0;
bool lost_resource = false;
- ReleaseCallback callback =
- base::Bind(ReleaseTextureMailbox, &release_sync_point, &lost_resource);
- ResourceProvider::ResourceId resource =
- child_resource_provider->CreateResourceFromTextureMailbox(
- TextureMailbox(gpu_mailbox), SingleReleaseCallback::Create(callback));
+ bool release_called = false;
+ unsigned sync_point = 0;
+ ResourceProvider::ResourceId resource = CreateChildMailbox(
+ &release_sync_point, &lost_resource, &release_called, &sync_point);
ReturnedResourceArray returned_to_child;
int child_id =
@@ -1474,8 +1841,8 @@ TEST_P(ResourceProviderTest, LostMailboxInParent) {
ResourceProvider::ResourceIdArray resource_ids_to_transfer;
resource_ids_to_transfer.push_back(resource);
TransferableResourceArray list;
- child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
- &list);
+ child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
+ &list);
EXPECT_EQ(1u, list.size());
resource_provider_->ReceiveFromChild(child_id, list);
@@ -1494,51 +1861,27 @@ TEST_P(ResourceProviderTest, LostMailboxInParent) {
ResourceProvider::ResourceIdArray no_resources;
resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
- // Expect the resource to be lost.
ASSERT_EQ(1u, returned_to_child.size());
- EXPECT_TRUE(returned_to_child[0].lost);
- child_resource_provider->ReceiveReturnsFromParent(returned_to_child);
+ // Losing an output surface only loses hardware resources.
+ EXPECT_EQ(returned_to_child[0].lost,
+ GetParam() == ResourceProvider::GLTexture);
+ child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
returned_to_child.clear();
}
- // Delete the resource in the child. Expect the resource to be lost.
- child_resource_provider->DeleteResource(resource);
- EXPECT_TRUE(lost_resource);
-
- child_context->waitSyncPoint(release_sync_point);
- child_context->deleteTexture(texture);
+ // Delete the resource in the child. Expect the resource to be lost if it's
+ // a GL texture.
+ child_resource_provider_->DeleteResource(resource);
+ EXPECT_EQ(lost_resource, GetParam() == ResourceProvider::GLTexture);
}
TEST_P(ResourceProviderTest, LostMailboxInGrandParent) {
- // Resource transfer is only supported with GL textures for now.
- if (GetParam() != ResourceProvider::GLTexture)
- return;
-
- scoped_ptr<ResourceProviderContext> child_context_owned(
- ResourceProviderContext::Create(shared_data_.get()));
- ResourceProviderContext* child_context = child_context_owned.get();
-
- FakeOutputSurfaceClient child_output_surface_client;
- scoped_ptr<OutputSurface> child_output_surface(FakeOutputSurface::Create3d(
- child_context_owned.PassAs<TestWebGraphicsContext3D>()));
- CHECK(child_output_surface->BindToClient(&child_output_surface_client));
-
- scoped_ptr<ResourceProvider> child_resource_provider(
- ResourceProvider::Create(child_output_surface.get(), 0, false));
-
- unsigned texture = child_context->createTexture();
- gpu::Mailbox gpu_mailbox;
- child_context->bindTexture(GL_TEXTURE_2D, texture);
- child_context->genMailboxCHROMIUM(gpu_mailbox.name);
- child_context->produceTextureCHROMIUM(GL_TEXTURE_2D, gpu_mailbox.name);
-
unsigned release_sync_point = 0;
bool lost_resource = false;
- ReleaseCallback callback =
- base::Bind(ReleaseTextureMailbox, &release_sync_point, &lost_resource);
- ResourceProvider::ResourceId resource =
- child_resource_provider->CreateResourceFromTextureMailbox(
- TextureMailbox(gpu_mailbox), SingleReleaseCallback::Create(callback));
+ bool release_called = false;
+ unsigned sync_point = 0;
+ ResourceProvider::ResourceId resource = CreateChildMailbox(
+ &release_sync_point, &lost_resource, &release_called, &sync_point);
ReturnedResourceArray returned_to_child;
int child_id =
@@ -1548,8 +1891,8 @@ TEST_P(ResourceProviderTest, LostMailboxInGrandParent) {
ResourceProvider::ResourceIdArray resource_ids_to_transfer;
resource_ids_to_transfer.push_back(resource);
TransferableResourceArray list;
- child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
- &list);
+ child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
+ &list);
EXPECT_EQ(1u, list.size());
resource_provider_->ReceiveFromChild(child_id, list);
@@ -1591,116 +1934,54 @@ TEST_P(ResourceProviderTest, LostMailboxInGrandParent) {
// Expect the resource to be lost.
ASSERT_EQ(1u, returned_to_child.size());
EXPECT_TRUE(returned_to_child[0].lost);
- child_resource_provider->ReceiveReturnsFromParent(returned_to_child);
+ child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
returned_to_child.clear();
}
// Delete the resource in the child. Expect the resource to be lost.
- child_resource_provider->DeleteResource(resource);
+ child_resource_provider_->DeleteResource(resource);
EXPECT_TRUE(lost_resource);
-
- child_context->waitSyncPoint(release_sync_point);
- child_context->deleteTexture(texture);
}
TEST_P(ResourceProviderTest, Shutdown) {
- // TextureMailbox callbacks only exist for GL textures for now.
- if (GetParam() != ResourceProvider::GLTexture)
- return;
- unsigned texture = context()->createTexture();
- context()->bindTexture(GL_TEXTURE_2D, texture);
- gpu::Mailbox mailbox;
- context()->genMailboxCHROMIUM(mailbox.name);
- context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
- unsigned sync_point = context()->insertSyncPoint();
-
- EXPECT_LT(0u, sync_point);
-
unsigned release_sync_point = 0;
bool lost_resource = false;
- scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
- base::Bind(ReleaseTextureMailbox, &release_sync_point, &lost_resource));
- resource_provider_->CreateResourceFromTextureMailbox(
- TextureMailbox(mailbox, sync_point),
- callback.Pass());
+ bool release_called = false;
+ unsigned sync_point = 0;
+ CreateChildMailbox(
+ &release_sync_point, &lost_resource, &release_called, &sync_point);
EXPECT_EQ(0u, release_sync_point);
EXPECT_FALSE(lost_resource);
- resource_provider_.reset();
-
- EXPECT_LE(sync_point, release_sync_point);
- EXPECT_FALSE(lost_resource);
-}
-
-static scoped_ptr<base::SharedMemory> CreateAndFillSharedMemory(
- gfx::Size size, uint32_t value) {
- scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory);
- CHECK(shared_memory->CreateAndMapAnonymous(4 * size.GetArea()));
- uint32_t* pixels = reinterpret_cast<uint32_t*>(shared_memory->memory());
- CHECK(pixels);
- std::fill_n(pixels, size.GetArea(), value);
- return shared_memory.Pass();
-}
-
-static void ReleaseSharedMemoryCallback(
- bool* release_called,
- unsigned sync_point, bool lost_resource) {
- *release_called = true;
-}
-
-TEST_P(ResourceProviderTest, ShutdownSharedMemory) {
- if (GetParam() != ResourceProvider::Bitmap)
- return;
-
- gfx::Size size(64, 64);
- scoped_ptr<base::SharedMemory> shared_memory(
- CreateAndFillSharedMemory(size, 0));
-
- bool release_called = false;
- scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
- base::Bind(ReleaseSharedMemoryCallback, &release_called));
- resource_provider_->CreateResourceFromTextureMailbox(
- TextureMailbox(shared_memory.get(), size),
- callback.Pass());
-
- resource_provider_.reset();
+ child_resource_provider_.reset();
+ if (GetParam() == ResourceProvider::GLTexture) {
+ EXPECT_LE(sync_point, release_sync_point);
+ }
EXPECT_TRUE(release_called);
+ EXPECT_FALSE(lost_resource);
}
TEST_P(ResourceProviderTest, ShutdownWithExportedResource) {
- // TextureMailbox callbacks only exist for GL textures for now.
- if (GetParam() != ResourceProvider::GLTexture)
- return;
- unsigned texture = context()->createTexture();
- context()->bindTexture(GL_TEXTURE_2D, texture);
- gpu::Mailbox mailbox;
- context()->genMailboxCHROMIUM(mailbox.name);
- context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
- unsigned sync_point = context()->insertSyncPoint();
-
- EXPECT_LT(0u, sync_point);
-
unsigned release_sync_point = 0;
bool lost_resource = false;
- scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
- base::Bind(ReleaseTextureMailbox, &release_sync_point, &lost_resource));
- ResourceProvider::ResourceId resource =
- resource_provider_->CreateResourceFromTextureMailbox(
- TextureMailbox(mailbox, sync_point),
- callback.Pass());
+ bool release_called = false;
+ unsigned sync_point = 0;
+ ResourceProvider::ResourceId resource = CreateChildMailbox(
+ &release_sync_point, &lost_resource, &release_called, &sync_point);
// Transfer the resource, so we can't release it properly on shutdown.
ResourceProvider::ResourceIdArray resource_ids_to_transfer;
resource_ids_to_transfer.push_back(resource);
TransferableResourceArray list;
- resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
+ child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
+ &list);
EXPECT_EQ(0u, release_sync_point);
EXPECT_FALSE(lost_resource);
- resource_provider_.reset();
+ child_resource_provider_.reset();
// Since the resource is in the parent, the child considers it lost.
EXPECT_EQ(0u, release_sync_point);
@@ -1753,7 +2034,7 @@ TEST_P(ResourceProviderTest, ScopedSampler) {
CHECK(output_surface->BindToClient(&output_surface_client));
scoped_ptr<ResourceProvider> resource_provider(
- ResourceProvider::Create(output_surface.get(), 0, false));
+ ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
gfx::Size size(1, 1);
ResourceFormat format = RGBA_8888;
@@ -1834,7 +2115,7 @@ TEST_P(ResourceProviderTest, ManagedResource) {
CHECK(output_surface->BindToClient(&output_surface_client));
scoped_ptr<ResourceProvider> resource_provider(
- ResourceProvider::Create(output_surface.get(), 0, false));
+ ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
gfx::Size size(1, 1);
ResourceFormat format = RGBA_8888;
@@ -1842,7 +2123,11 @@ TEST_P(ResourceProviderTest, ManagedResource) {
// Check that the texture gets created with the right sampler settings.
ResourceProvider::ResourceId id = resource_provider->CreateManagedResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+ size,
+ GL_TEXTURE_2D,
+ GL_CLAMP_TO_EDGE,
+ ResourceProvider::TextureUsageAny,
+ format);
EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
EXPECT_CALL(*context,
texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
@@ -1879,18 +2164,18 @@ TEST_P(ResourceProviderTest, TextureWrapMode) {
CHECK(output_surface->BindToClient(&output_surface_client));
scoped_ptr<ResourceProvider> resource_provider(
- ResourceProvider::Create(output_surface.get(), 0, false));
+ ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
gfx::Size size(1, 1);
ResourceFormat format = RGBA_8888;
- int texture_id = 1;
GLenum texture_pool = GL_TEXTURE_POOL_UNMANAGED_CHROMIUM;
- for (int i = 0; i < 2; ++i) {
- GLint wrap_mode = i ? GL_CLAMP_TO_EDGE : GL_REPEAT;
+ for (int texture_id = 1; texture_id <= 2; ++texture_id) {
+ GLint wrap_mode = texture_id == 1 ? GL_CLAMP_TO_EDGE : GL_REPEAT;
// Check that the texture gets created with the right sampler settings.
ResourceProvider::ResourceId id =
resource_provider->CreateGLTexture(size,
+ GL_TEXTURE_2D,
texture_pool,
wrap_mode,
ResourceProvider::TextureUsageAny,
@@ -1917,8 +2202,6 @@ TEST_P(ResourceProviderTest, TextureWrapMode) {
}
}
-static void EmptyReleaseCallback(unsigned sync_point, bool lost_resource) {}
-
TEST_P(ResourceProviderTest, TextureMailbox_SharedMemory) {
if (GetParam() != ResourceProvider::Bitmap)
return;
@@ -1935,7 +2218,7 @@ TEST_P(ResourceProviderTest, TextureMailbox_SharedMemory) {
CHECK(output_surface->BindToClient(&output_surface_client));
scoped_ptr<ResourceProvider> resource_provider(
- ResourceProvider::Create(output_surface.get(), 0, false));
+ ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
base::Bind(&EmptyReleaseCallback));
@@ -1970,7 +2253,7 @@ TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D) {
CHECK(output_surface->BindToClient(&output_surface_client));
scoped_ptr<ResourceProvider> resource_provider(
- ResourceProvider::Create(output_surface.get(), 0, false));
+ ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
unsigned texture_id = 1;
unsigned sync_point = 30;
@@ -2034,7 +2317,7 @@ TEST_P(ResourceProviderTest, TextureMailbox_GLTextureExternalOES) {
CHECK(output_surface->BindToClient(&output_surface_client));
scoped_ptr<ResourceProvider> resource_provider(
- ResourceProvider::Create(output_surface.get(), 0, false));
+ ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
unsigned texture_id = 1;
unsigned sync_point = 30;
@@ -2085,59 +2368,77 @@ TEST_P(ResourceProviderTest, TextureMailbox_GLTextureExternalOES) {
class AllocationTrackingContext3D : public TestWebGraphicsContext3D {
public:
- MOCK_METHOD0(createTexture, WebGLId());
- MOCK_METHOD1(deleteTexture, void(WebGLId texture_id));
- MOCK_METHOD2(bindTexture, void(WGC3Denum target, WebGLId texture));
+ MOCK_METHOD0(NextTextureId, GLuint());
+ MOCK_METHOD1(RetireTextureId, void(GLuint id));
+ MOCK_METHOD2(bindTexture, void(GLenum target, GLuint texture));
+ MOCK_METHOD5(texStorage2DEXT,
+ void(GLenum target,
+ GLint levels,
+ GLuint internalformat,
+ GLint width,
+ GLint height));
MOCK_METHOD9(texImage2D,
- void(WGC3Denum target,
- WGC3Dint level,
- WGC3Denum internalformat,
- WGC3Dsizei width,
- WGC3Dsizei height,
- WGC3Dint border,
- WGC3Denum format,
- WGC3Denum type,
+ void(GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type,
const void* pixels));
MOCK_METHOD9(texSubImage2D,
- void(WGC3Denum target,
- WGC3Dint level,
- WGC3Dint xoffset,
- WGC3Dint yoffset,
- WGC3Dsizei width,
- WGC3Dsizei height,
- WGC3Denum format,
- WGC3Denum type,
+ void(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
const void* pixels));
MOCK_METHOD9(asyncTexImage2DCHROMIUM,
- void(WGC3Denum target,
- WGC3Dint level,
- WGC3Denum internalformat,
- WGC3Dsizei width,
- WGC3Dsizei height,
- WGC3Dint border,
- WGC3Denum format,
- WGC3Denum type,
+ void(GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type,
const void* pixels));
MOCK_METHOD9(asyncTexSubImage2DCHROMIUM,
- void(WGC3Denum target,
- WGC3Dint level,
- WGC3Dint xoffset,
- WGC3Dint yoffset,
- WGC3Dsizei width,
- WGC3Dsizei height,
- WGC3Denum format,
- WGC3Denum type,
+ void(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
const void* pixels));
- MOCK_METHOD1(waitAsyncTexImage2DCHROMIUM, void(WGC3Denum));
- MOCK_METHOD3(createImageCHROMIUM, WGC3Duint(WGC3Dsizei, WGC3Dsizei,
- WGC3Denum));
- MOCK_METHOD1(destroyImageCHROMIUM, void(WGC3Duint));
- MOCK_METHOD2(mapImageCHROMIUM, void*(WGC3Duint, WGC3Denum));
- MOCK_METHOD3(getImageParameterivCHROMIUM, void(WGC3Duint, WGC3Denum,
- GLint*));
- MOCK_METHOD1(unmapImageCHROMIUM, void(WGC3Duint));
- MOCK_METHOD2(bindTexImage2DCHROMIUM, void(WGC3Denum, WGC3Dint));
- MOCK_METHOD2(releaseTexImage2DCHROMIUM, void(WGC3Denum, WGC3Dint));
+ MOCK_METHOD8(compressedTexImage2D,
+ void(GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLsizei image_size,
+ const void* data));
+ MOCK_METHOD1(waitAsyncTexImage2DCHROMIUM, void(GLenum));
+ MOCK_METHOD3(createImageCHROMIUM, GLuint(GLsizei, GLsizei, GLenum));
+ MOCK_METHOD1(destroyImageCHROMIUM, void(GLuint));
+ MOCK_METHOD2(mapImageCHROMIUM, void*(GLuint, GLenum));
+ MOCK_METHOD3(getImageParameterivCHROMIUM, void(GLuint, GLenum, GLint*));
+ MOCK_METHOD1(unmapImageCHROMIUM, void(GLuint));
+ MOCK_METHOD2(bindTexImage2DCHROMIUM, void(GLenum, GLint));
+ MOCK_METHOD2(releaseTexImage2DCHROMIUM, void(GLenum, GLint));
+
+ // We're mocking bindTexture, so we override
+ // TestWebGraphicsContext3D::texParameteri to avoid assertions related to the
+ // currently bound texture.
+ virtual void texParameteri(GLenum target, GLenum pname, GLint param) {}
};
TEST_P(ResourceProviderTest, TextureAllocation) {
@@ -2154,7 +2455,7 @@ TEST_P(ResourceProviderTest, TextureAllocation) {
CHECK(output_surface->BindToClient(&output_surface_client));
scoped_ptr<ResourceProvider> resource_provider(
- ResourceProvider::Create(output_surface.get(), 0, false));
+ ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
gfx::Size size(2, 2);
gfx::Vector2d offset(0, 0);
@@ -2168,11 +2469,11 @@ TEST_P(ResourceProviderTest, TextureAllocation) {
id = resource_provider->CreateResource(
size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
- EXPECT_CALL(*context, createTexture()).WillOnce(Return(texture_id));
+ EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1);
resource_provider->CreateForTesting(id);
- EXPECT_CALL(*context, deleteTexture(texture_id)).Times(1);
+ EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
resource_provider->DeleteResource(id);
Mock::VerifyAndClearExpectations(context);
@@ -2181,13 +2482,13 @@ TEST_P(ResourceProviderTest, TextureAllocation) {
id = resource_provider->CreateResource(
size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
- EXPECT_CALL(*context, createTexture()).WillOnce(Return(texture_id));
+ EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3);
EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _)).Times(1);
EXPECT_CALL(*context, texSubImage2D(_, _, _, _, 2, 2, _, _, _)).Times(1);
resource_provider->SetPixels(id, pixels, rect, rect, offset);
- EXPECT_CALL(*context, deleteTexture(texture_id)).Times(1);
+ EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
resource_provider->DeleteResource(id);
Mock::VerifyAndClearExpectations(context);
@@ -2197,7 +2498,7 @@ TEST_P(ResourceProviderTest, TextureAllocation) {
size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
resource_provider->AcquirePixelBuffer(id);
- EXPECT_CALL(*context, createTexture()).WillOnce(Return(texture_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);
@@ -2206,7 +2507,84 @@ TEST_P(ResourceProviderTest, TextureAllocation) {
resource_provider->ReleasePixelBuffer(id);
- EXPECT_CALL(*context, deleteTexture(texture_id)).Times(1);
+ EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
+ resource_provider->DeleteResource(id);
+
+ Mock::VerifyAndClearExpectations(context);
+}
+
+TEST_P(ResourceProviderTest, TextureAllocationStorageUsageAny) {
+ // Only for GL textures.
+ if (GetParam() != ResourceProvider::GLTexture)
+ return;
+ scoped_ptr<AllocationTrackingContext3D> context_owned(
+ new StrictMock<AllocationTrackingContext3D>);
+ AllocationTrackingContext3D* context = context_owned.get();
+ context->set_support_texture_storage(true);
+
+ FakeOutputSurfaceClient output_surface_client;
+ scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
+ context_owned.PassAs<TestWebGraphicsContext3D>()));
+ CHECK(output_surface->BindToClient(&output_surface_client));
+
+ scoped_ptr<ResourceProvider> resource_provider(
+ ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
+
+ gfx::Size size(2, 2);
+ ResourceFormat format = RGBA_8888;
+ ResourceProvider::ResourceId id = 0;
+ int texture_id = 123;
+
+ // Lazy allocation. Don't allocate when creating the resource.
+ id = resource_provider->CreateResource(
+ size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+
+ EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
+ EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
+ EXPECT_CALL(*context, texStorage2DEXT(_, _, _, 2, 2)).Times(1);
+ resource_provider->AllocateForTesting(id);
+
+ EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
+ resource_provider->DeleteResource(id);
+
+ Mock::VerifyAndClearExpectations(context);
+}
+
+TEST_P(ResourceProviderTest, TextureAllocationStorageUsageFramebuffer) {
+ // Only for GL textures.
+ if (GetParam() != ResourceProvider::GLTexture)
+ return;
+ scoped_ptr<AllocationTrackingContext3D> context_owned(
+ new StrictMock<AllocationTrackingContext3D>);
+ AllocationTrackingContext3D* context = context_owned.get();
+ context->set_support_texture_storage(true);
+
+ FakeOutputSurfaceClient output_surface_client;
+ scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
+ context_owned.PassAs<TestWebGraphicsContext3D>()));
+ CHECK(output_surface->BindToClient(&output_surface_client));
+
+ scoped_ptr<ResourceProvider> resource_provider(
+ ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
+
+ gfx::Size size(2, 2);
+ ResourceFormat format = RGBA_8888;
+ ResourceProvider::ResourceId id = 0;
+ int texture_id = 123;
+
+ // Lazy allocation. Don't allocate when creating the resource.
+ id = resource_provider->CreateResource(
+ size,
+ GL_CLAMP_TO_EDGE,
+ ResourceProvider::TextureUsageFramebuffer,
+ format);
+
+ EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
+ EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
+ EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _)).Times(1);
+ resource_provider->AllocateForTesting(id);
+
+ EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
resource_provider->DeleteResource(id);
Mock::VerifyAndClearExpectations(context);
@@ -2230,13 +2608,13 @@ TEST_P(ResourceProviderTest, PixelBuffer_GLTexture) {
int texture_id = 123;
scoped_ptr<ResourceProvider> resource_provider(
- ResourceProvider::Create(output_surface.get(), 0, false));
+ ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
id = resource_provider->CreateResource(
size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
resource_provider->AcquirePixelBuffer(id);
- EXPECT_CALL(*context, createTexture()).WillOnce(Return(texture_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);
@@ -2246,7 +2624,7 @@ TEST_P(ResourceProviderTest, PixelBuffer_GLTexture) {
resource_provider->ReleasePixelBuffer(id);
- EXPECT_CALL(*context, deleteTexture(texture_id)).Times(1);
+ EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
resource_provider->DeleteResource(id);
Mock::VerifyAndClearExpectations(context);
@@ -2267,7 +2645,7 @@ TEST_P(ResourceProviderTest, PixelBuffer_Bitmap) {
const uint32_t kBadBeef = 0xbadbeef;
scoped_ptr<ResourceProvider> resource_provider(
- ResourceProvider::Create(output_surface.get(), 0, false));
+ ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
id = resource_provider->CreateResource(
size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
@@ -2313,13 +2691,13 @@ TEST_P(ResourceProviderTest, ForcingAsyncUploadToComplete) {
int texture_id = 123;
scoped_ptr<ResourceProvider> resource_provider(
- ResourceProvider::Create(output_surface.get(), 0, false));
+ ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
id = resource_provider->CreateResource(
size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
resource_provider->AcquirePixelBuffer(id);
- EXPECT_CALL(*context, createTexture()).WillOnce(Return(texture_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);
@@ -2332,7 +2710,7 @@ TEST_P(ResourceProviderTest, ForcingAsyncUploadToComplete) {
resource_provider->ReleasePixelBuffer(id);
- EXPECT_CALL(*context, deleteTexture(texture_id)).Times(1);
+ EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
resource_provider->DeleteResource(id);
Mock::VerifyAndClearExpectations(context);
@@ -2354,9 +2732,9 @@ TEST_P(ResourceProviderTest, PixelBufferLostContext) {
int texture_id = 123;
scoped_ptr<ResourceProvider> resource_provider(
- ResourceProvider::Create(output_surface.get(), 0, false));
+ ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
- EXPECT_CALL(*context, createTexture()).WillRepeatedly(Return(texture_id));
+ EXPECT_CALL(*context, NextTextureId()).WillRepeatedly(Return(texture_id));
id = resource_provider->CreateResource(
size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
@@ -2392,7 +2770,7 @@ TEST_P(ResourceProviderTest, Image_GLTexture) {
const unsigned kImageId = 234u;
scoped_ptr<ResourceProvider> resource_provider(
- ResourceProvider::Create(output_surface.get(), 0, false));
+ ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
id = resource_provider->CreateResource(
size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
@@ -2421,7 +2799,7 @@ TEST_P(ResourceProviderTest, Image_GLTexture) {
.RetiresOnSaturation();
resource_provider->UnmapImage(id);
- EXPECT_CALL(*context, createTexture())
+ EXPECT_CALL(*context, NextTextureId())
.WillOnce(Return(kTextureId))
.RetiresOnSaturation();
// Once in CreateTextureId and once in BindForSampling
@@ -2430,10 +2808,31 @@ TEST_P(ResourceProviderTest, Image_GLTexture) {
EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
.Times(1)
.RetiresOnSaturation();
+ {
+ ResourceProvider::ScopedSamplerGL lock_gl(
+ resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
+ EXPECT_EQ(kTextureId, lock_gl.texture_id());
+ }
+
+ EXPECT_CALL(*context, mapImageCHROMIUM(kImageId, GL_READ_WRITE))
+ .WillOnce(Return(dummy_mapped_buffer_address))
+ .RetiresOnSaturation();
+ resource_provider->MapImage(id);
+
+ EXPECT_CALL(*context, unmapImageCHROMIUM(kImageId))
+ .Times(1)
+ .RetiresOnSaturation();
+ resource_provider->UnmapImage(id);
+
+ EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(1)
+ .RetiresOnSaturation();
EXPECT_CALL(*context, releaseTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
.Times(1)
.RetiresOnSaturation();
- EXPECT_CALL(*context, deleteTexture(kTextureId))
+ EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*context, RetireTextureId(kTextureId))
.Times(1)
.RetiresOnSaturation();
{
@@ -2463,7 +2862,7 @@ TEST_P(ResourceProviderTest, Image_Bitmap) {
const uint32_t kBadBeef = 0xbadbeef;
scoped_ptr<ResourceProvider> resource_provider(
- ResourceProvider::Create(output_surface.get(), 0, false));
+ ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
id = resource_provider->CreateResource(
size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
@@ -2514,7 +2913,7 @@ TEST(ResourceProviderTest, BasicInitializeGLSoftware) {
scoped_ptr<SoftwareOutputDevice>(new SoftwareOutputDevice)));
EXPECT_TRUE(output_surface->BindToClient(&client));
scoped_ptr<ResourceProvider> resource_provider(
- ResourceProvider::Create(output_surface.get(), 0, false));
+ ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
CheckCreateResource(ResourceProvider::Bitmap, resource_provider.get(), NULL);
@@ -2531,10 +2930,146 @@ TEST(ResourceProviderTest, BasicInitializeGLSoftware) {
output_surface.get());
}
+TEST_P(ResourceProviderTest, CompressedTextureETC1Allocate) {
+ if (GetParam() != ResourceProvider::GLTexture)
+ return;
+
+ scoped_ptr<AllocationTrackingContext3D> context_owned(
+ new AllocationTrackingContext3D);
+ AllocationTrackingContext3D* context = context_owned.get();
+ context_owned->set_support_compressed_texture_etc1(true);
+
+ FakeOutputSurfaceClient output_surface_client;
+ scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
+ context_owned.PassAs<TestWebGraphicsContext3D>()));
+ CHECK(output_surface->BindToClient(&output_surface_client));
+
+ gfx::Size size(4, 4);
+ scoped_ptr<ResourceProvider> resource_provider(
+ ResourceProvider::Create(output_surface.get(),
+ shared_bitmap_manager_.get(),
+ 0,
+ false,
+ 1));
+ int texture_id = 123;
+
+ ResourceProvider::ResourceId id = resource_provider->CreateResource(
+ size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, ETC1);
+ EXPECT_NE(0u, id);
+ EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
+ EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
+ resource_provider->AllocateForTesting(id);
+
+ EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
+ resource_provider->DeleteResource(id);
+}
+
+TEST_P(ResourceProviderTest, CompressedTextureETC1SetPixels) {
+ if (GetParam() != ResourceProvider::GLTexture)
+ return;
+
+ scoped_ptr<AllocationTrackingContext3D> context_owned(
+ new AllocationTrackingContext3D);
+ AllocationTrackingContext3D* context = context_owned.get();
+ context_owned->set_support_compressed_texture_etc1(true);
+
+ FakeOutputSurfaceClient output_surface_client;
+ scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
+ context_owned.PassAs<TestWebGraphicsContext3D>()));
+ CHECK(output_surface->BindToClient(&output_surface_client));
+
+ gfx::Size size(4, 4);
+ scoped_ptr<ResourceProvider> resource_provider(
+ ResourceProvider::Create(output_surface.get(),
+ shared_bitmap_manager_.get(),
+ 0,
+ false,
+ 1));
+ int texture_id = 123;
+ uint8_t pixels[8];
+
+ ResourceProvider::ResourceId id = resource_provider->CreateResource(
+ size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, ETC1);
+ EXPECT_NE(0u, id);
+ EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
+ EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3);
+ EXPECT_CALL(*context,
+ compressedTexImage2D(
+ _, 0, _, size.width(), size.height(), _, _, _)).Times(1);
+ resource_provider->SetPixels(
+ id, pixels, gfx::Rect(size), gfx::Rect(size), gfx::Vector2d(0, 0));
+
+ EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
+ resource_provider->DeleteResource(id);
+}
+
INSTANTIATE_TEST_CASE_P(
ResourceProviderTests,
ResourceProviderTest,
::testing::Values(ResourceProvider::GLTexture, ResourceProvider::Bitmap));
+class TextureIdAllocationTrackingContext : public TestWebGraphicsContext3D {
+ public:
+ virtual GLuint NextTextureId() OVERRIDE {
+ base::AutoLock lock(namespace_->lock);
+ return namespace_->next_texture_id++;
+ }
+ virtual void RetireTextureId(GLuint) OVERRIDE {}
+ GLuint PeekTextureId() {
+ base::AutoLock lock(namespace_->lock);
+ return namespace_->next_texture_id;
+ }
+};
+
+TEST(ResourceProviderTest, TextureAllocationChunkSize) {
+ scoped_ptr<TextureIdAllocationTrackingContext> context_owned(
+ new TextureIdAllocationTrackingContext);
+ TextureIdAllocationTrackingContext* context = context_owned.get();
+
+ FakeOutputSurfaceClient output_surface_client;
+ scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
+ context_owned.PassAs<TestWebGraphicsContext3D>()));
+ CHECK(output_surface->BindToClient(&output_surface_client));
+
+ gfx::Size size(1, 1);
+ ResourceFormat format = RGBA_8888;
+
+ {
+ size_t kTextureAllocationChunkSize = 1;
+ scoped_ptr<ResourceProvider> resource_provider(
+ ResourceProvider::Create(output_surface.get(),
+ NULL,
+ 0,
+ false,
+ kTextureAllocationChunkSize));
+
+ ResourceProvider::ResourceId id = resource_provider->CreateResource(
+ size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+ resource_provider->AllocateForTesting(id);
+ Mock::VerifyAndClearExpectations(context);
+
+ DCHECK_EQ(2u, context->PeekTextureId());
+ resource_provider->DeleteResource(id);
+ }
+
+ {
+ size_t kTextureAllocationChunkSize = 8;
+ scoped_ptr<ResourceProvider> resource_provider(
+ ResourceProvider::Create(output_surface.get(),
+ NULL,
+ 0,
+ false,
+ kTextureAllocationChunkSize));
+
+ ResourceProvider::ResourceId id = resource_provider->CreateResource(
+ size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+ resource_provider->AllocateForTesting(id);
+ Mock::VerifyAndClearExpectations(context);
+
+ DCHECK_EQ(10u, context->PeekTextureId());
+ resource_provider->DeleteResource(id);
+ }
+}
+
} // namespace
} // namespace cc
diff --git a/chromium/cc/resources/resource_update_controller.cc b/chromium/cc/resources/resource_update_controller.cc
index 3c8b1e709ff..868133596be 100644
--- a/chromium/cc/resources/resource_update_controller.cc
+++ b/chromium/cc/resources/resource_update_controller.cc
@@ -9,6 +9,7 @@
#include "base/single_thread_task_runner.h"
#include "cc/resources/prioritized_resource.h"
#include "cc/resources/resource_provider.h"
+#include "ui/gfx/frame_time.h"
namespace {
@@ -31,11 +32,7 @@ size_t ResourceUpdateController::MaxPartialTextureUpdates() {
size_t ResourceUpdateController::MaxFullUpdatesPerTick(
ResourceProvider* resource_provider) {
- double textures_per_second = resource_provider->EstimatedUploadsPerSecond();
- size_t textures_per_tick =
- floor(resource_provider->TextureUpdateTickRate().InSecondsF() *
- textures_per_second);
- return textures_per_tick ? textures_per_tick : 1;
+ return resource_provider->EstimatedUploadsPerTick();
}
ResourceUpdateController::ResourceUpdateController(
@@ -49,8 +46,8 @@ ResourceUpdateController::ResourceUpdateController(
texture_updates_per_tick_(MaxFullUpdatesPerTick(resource_provider)),
first_update_attempt_(true),
task_runner_(task_runner),
- weak_factory_(this),
- task_posted_(false) {}
+ task_posted_(false),
+ weak_factory_(this) {}
ResourceUpdateController::~ResourceUpdateController() {}
@@ -112,12 +109,9 @@ void ResourceUpdateController::OnTimerFired() {
client_->ReadyToFinalizeTextureUpdates();
}
-base::TimeTicks ResourceUpdateController::Now() const {
- return base::TimeTicks::Now();
-}
-
-base::TimeDelta ResourceUpdateController::UpdateMoreTexturesTime() const {
- return resource_provider_->TextureUpdateTickRate();
+base::TimeTicks ResourceUpdateController::UpdateMoreTexturesCompletionTime() {
+ return resource_provider_->EstimatedUploadCompletionTime(
+ texture_updates_per_tick_);
}
size_t ResourceUpdateController::UpdateMoreTexturesSize() const {
@@ -128,25 +122,14 @@ size_t ResourceUpdateController::MaxBlockingUpdates() const {
return UpdateMoreTexturesSize() * kMaxBlockingUpdateIntervals;
}
-base::TimeDelta ResourceUpdateController::PendingUpdateTime() const {
- base::TimeDelta update_one_resource_time =
- UpdateMoreTexturesTime() / UpdateMoreTexturesSize();
- return update_one_resource_time * resource_provider_->NumBlockingUploads();
-}
-
bool ResourceUpdateController::UpdateMoreTexturesIfEnoughTimeRemaining() {
while (resource_provider_->NumBlockingUploads() < MaxBlockingUpdates()) {
if (!queue_->FullUploadSize())
return false;
if (!time_limit_.is_null()) {
- // Estimated completion time of all pending updates.
- base::TimeTicks completion_time = Now() + PendingUpdateTime();
-
- // Time remaining based on current completion estimate.
- base::TimeDelta time_remaining = time_limit_ - completion_time;
-
- if (time_remaining < UpdateMoreTexturesTime())
+ base::TimeTicks completion_time = UpdateMoreTexturesCompletionTime();
+ if (completion_time > time_limit_)
return true;
}
diff --git a/chromium/cc/resources/resource_update_controller.h b/chromium/cc/resources/resource_update_controller.h
index 97138bcf5d5..4425f377f71 100644
--- a/chromium/cc/resources/resource_update_controller.h
+++ b/chromium/cc/resources/resource_update_controller.h
@@ -48,9 +48,8 @@ class CC_EXPORT ResourceUpdateController {
// Virtual for testing.
- virtual base::TimeTicks Now() const;
- virtual base::TimeDelta UpdateMoreTexturesTime() const;
virtual size_t UpdateMoreTexturesSize() const;
+ virtual base::TimeTicks UpdateMoreTexturesCompletionTime();
protected:
ResourceUpdateController(ResourceUpdateControllerClient* client,
@@ -62,7 +61,6 @@ class CC_EXPORT ResourceUpdateController {
static size_t MaxFullUpdatesPerTick(ResourceProvider* resource_provider);
size_t MaxBlockingUpdates() const;
- base::TimeDelta PendingUpdateTime() const;
void UpdateTexture(ResourceUpdate update);
@@ -79,8 +77,8 @@ class CC_EXPORT ResourceUpdateController {
size_t texture_updates_per_tick_;
bool first_update_attempt_;
base::SingleThreadTaskRunner* task_runner_;
- base::WeakPtrFactory<ResourceUpdateController> weak_factory_;
bool task_posted_;
+ base::WeakPtrFactory<ResourceUpdateController> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(ResourceUpdateController);
};
diff --git a/chromium/cc/resources/resource_update_controller_unittest.cc b/chromium/cc/resources/resource_update_controller_unittest.cc
index 31b5d71662a..8979925caea 100644
--- a/chromium/cc/resources/resource_update_controller_unittest.cc
+++ b/chromium/cc/resources/resource_update_controller_unittest.cc
@@ -5,24 +5,18 @@
#include "cc/resources/resource_update_controller.h"
#include "base/test/test_simple_task_runner.h"
-#include "cc/debug/test_web_graphics_context_3d.h"
#include "cc/resources/prioritized_resource_manager.h"
#include "cc/test/fake_output_surface.h"
#include "cc/test/fake_output_surface_client.h"
#include "cc/test/fake_proxy.h"
#include "cc/test/scheduler_test_common.h"
+#include "cc/test/test_web_graphics_context_3d.h"
#include "cc/test/tiled_layer_test_common.h"
#include "cc/trees/single_thread_proxy.h" // For DebugScopedSetImplThread
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/khronos/GLES2/gl2ext.h"
using testing::Test;
-using WebKit::WGC3Denum;
-using WebKit::WGC3Dint;
-using WebKit::WGC3Duint;
-using WebKit::WGC3Dsizei;
-using WebKit::WebGLId;
-using WebKit::WebString;
namespace cc {
namespace {
@@ -35,28 +29,22 @@ class ResourceUpdateControllerTest;
class WebGraphicsContext3DForUploadTest : public TestWebGraphicsContext3D {
public:
explicit WebGraphicsContext3DForUploadTest(ResourceUpdateControllerTest* test)
- : test_(test) {
- test_capabilities_.shallow_flush = true;
- }
-
- virtual void flush(void) OVERRIDE;
- virtual void shallowFlushCHROMIUM(void) OVERRIDE;
- virtual void texSubImage2D(
- WGC3Denum target,
- WGC3Dint level,
- WGC3Dint xoffset,
- WGC3Dint yoffset,
- WGC3Dsizei width,
- WGC3Dsizei height,
- WGC3Denum format,
- WGC3Denum type,
- const void* pixels) OVERRIDE;
- virtual GrGLInterface* onCreateGrGLInterface() OVERRIDE { return NULL; }
-
- virtual void getQueryObjectuivEXT(
- WebGLId id,
- WGC3Denum pname,
- WGC3Duint* value);
+ : test_(test) {}
+
+ virtual void flush() OVERRIDE;
+ virtual void shallowFlushCHROMIUM() OVERRIDE;
+ virtual void texSubImage2D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ const void* pixels) OVERRIDE;
+ virtual GrGLInterface* createGrGLInterface() OVERRIDE { return NULL; }
+
+ virtual void getQueryObjectuivEXT(GLuint id, GLenum pname, GLuint* value);
private:
ResourceUpdateControllerTest* test_;
@@ -137,7 +125,7 @@ class ResourceUpdateControllerTest : public Test {
CHECK(output_surface_->BindToClient(&output_surface_client_));
resource_provider_ =
- ResourceProvider::Create(output_surface_.get(), 0, false);
+ ResourceProvider::Create(output_surface_.get(), NULL, 0, false, 1);
}
void AppendFullUploadsOfIndexedTextureToUpdateQueue(int count,
@@ -214,29 +202,27 @@ class ResourceUpdateControllerTest : public Test {
int num_total_flushes_;
};
-void WebGraphicsContext3DForUploadTest::flush(void) { test_->OnFlush(); }
+void WebGraphicsContext3DForUploadTest::flush() { test_->OnFlush(); }
-void WebGraphicsContext3DForUploadTest::shallowFlushCHROMIUM(void) {
+void WebGraphicsContext3DForUploadTest::shallowFlushCHROMIUM() {
test_->OnFlush();
}
-void WebGraphicsContext3DForUploadTest::texSubImage2D(
- WGC3Denum target,
- WGC3Dint level,
- WGC3Dint xoffset,
- WGC3Dint yoffset,
- WGC3Dsizei width,
- WGC3Dsizei height,
- WGC3Denum format,
- WGC3Denum type,
- const void* pixels) {
+void WebGraphicsContext3DForUploadTest::texSubImage2D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ const void* pixels) {
test_->OnUpload();
}
-void WebGraphicsContext3DForUploadTest::getQueryObjectuivEXT(
- WebGLId id,
- WGC3Denum pname,
- WGC3Duint* params) {
+void WebGraphicsContext3DForUploadTest::getQueryObjectuivEXT(GLuint id,
+ GLenum pname,
+ GLuint* params) {
if (pname == GL_QUERY_RESULT_AVAILABLE_EXT)
*params = test_->IsQueryResultAvailable();
}
@@ -355,12 +341,14 @@ class FakeResourceUpdateController : public ResourceUpdateController {
}
void SetNow(base::TimeTicks time) { now_ = time; }
- virtual base::TimeTicks Now() const OVERRIDE { return now_; }
- void SetUpdateMoreTexturesTime(base::TimeDelta time) {
- update_more_textures_time_ = time;
+ base::TimeTicks Now() const { return now_; }
+ void SetUpdateTextureTime(base::TimeDelta time) {
+ update_textures_time_ = time;
}
- virtual base::TimeDelta UpdateMoreTexturesTime() const OVERRIDE {
- return update_more_textures_time_;
+ virtual base::TimeTicks UpdateMoreTexturesCompletionTime() OVERRIDE {
+ size_t total_updates =
+ resource_provider_->NumBlockingUploads() + update_more_textures_size_;
+ return now_ + total_updates * update_textures_time_;
}
void SetUpdateMoreTexturesSize(size_t size) {
update_more_textures_size_ = size;
@@ -376,10 +364,12 @@ class FakeResourceUpdateController : public ResourceUpdateController {
ResourceProvider* resource_provider)
: ResourceUpdateController(
client, task_runner, queue.Pass(), resource_provider),
+ resource_provider_(resource_provider),
update_more_textures_size_(0) {}
+ ResourceProvider* resource_provider_;
base::TimeTicks now_;
- base::TimeDelta update_more_textures_time_;
+ base::TimeDelta update_textures_time_;
size_t update_more_textures_size_;
};
@@ -408,14 +398,14 @@ TEST_F(ResourceUpdateControllerTest, UpdateMoreTextures) {
resource_provider_.get()));
controller->SetNow(controller->Now() + base::TimeDelta::FromMilliseconds(1));
- controller->SetUpdateMoreTexturesTime(base::TimeDelta::FromMilliseconds(100));
+ controller->SetUpdateTextureTime(base::TimeDelta::FromMilliseconds(100));
controller->SetUpdateMoreTexturesSize(1);
// Not enough time for any updates.
controller->PerformMoreUpdates(controller->Now() +
base::TimeDelta::FromMilliseconds(90));
EXPECT_FALSE(task_runner->HasPendingTask());
- controller->SetUpdateMoreTexturesTime(base::TimeDelta::FromMilliseconds(100));
+ controller->SetUpdateTextureTime(base::TimeDelta::FromMilliseconds(100));
controller->SetUpdateMoreTexturesSize(1);
// Only enough time for 1 update.
controller->PerformMoreUpdates(controller->Now() +
@@ -426,7 +416,7 @@ TEST_F(ResourceUpdateControllerTest, UpdateMoreTextures) {
// Complete one upload.
MakeQueryResultAvailable();
- controller->SetUpdateMoreTexturesTime(base::TimeDelta::FromMilliseconds(100));
+ controller->SetUpdateTextureTime(base::TimeDelta::FromMilliseconds(100));
controller->SetUpdateMoreTexturesSize(1);
// Enough time for 2 updates.
controller->PerformMoreUpdates(controller->Now() +
@@ -455,7 +445,7 @@ TEST_F(ResourceUpdateControllerTest, NoMoreUpdates) {
resource_provider_.get()));
controller->SetNow(controller->Now() + base::TimeDelta::FromMilliseconds(1));
- controller->SetUpdateMoreTexturesTime(base::TimeDelta::FromMilliseconds(100));
+ controller->SetUpdateTextureTime(base::TimeDelta::FromMilliseconds(100));
controller->SetUpdateMoreTexturesSize(1);
// Enough time for 3 updates but only 2 necessary.
controller->PerformMoreUpdates(controller->Now() +
@@ -465,7 +455,7 @@ TEST_F(ResourceUpdateControllerTest, NoMoreUpdates) {
EXPECT_TRUE(client.ReadyToFinalizeCalled());
EXPECT_EQ(2, num_total_uploads_);
- controller->SetUpdateMoreTexturesTime(base::TimeDelta::FromMilliseconds(100));
+ controller->SetUpdateTextureTime(base::TimeDelta::FromMilliseconds(100));
controller->SetUpdateMoreTexturesSize(1);
// Enough time for updates but no more updates left.
controller->PerformMoreUpdates(controller->Now() +
@@ -495,7 +485,7 @@ TEST_F(ResourceUpdateControllerTest, UpdatesCompleteInFiniteTime) {
resource_provider_.get()));
controller->SetNow(controller->Now() + base::TimeDelta::FromMilliseconds(1));
- controller->SetUpdateMoreTexturesTime(base::TimeDelta::FromMilliseconds(500));
+ controller->SetUpdateTextureTime(base::TimeDelta::FromMilliseconds(500));
controller->SetUpdateMoreTexturesSize(1);
for (int i = 0; i < 100; i++) {
diff --git a/chromium/cc/resources/scoped_resource.cc b/chromium/cc/resources/scoped_resource.cc
index 5fcaaca7acc..99f93c9bc85 100644
--- a/chromium/cc/resources/scoped_resource.cc
+++ b/chromium/cc/resources/scoped_resource.cc
@@ -15,7 +15,7 @@ ScopedResource::~ScopedResource() {
Free();
}
-bool ScopedResource::Allocate(gfx::Size size,
+void ScopedResource::Allocate(gfx::Size size,
ResourceProvider::TextureUsageHint hint,
ResourceFormat format) {
DCHECK(!id());
@@ -28,8 +28,25 @@ bool ScopedResource::Allocate(gfx::Size size,
#ifndef NDEBUG
allocate_thread_id_ = base::PlatformThread::CurrentId();
#endif
+}
- return id() != 0;
+void ScopedResource::AllocateManaged(gfx::Size size,
+ GLenum target,
+ ResourceFormat format) {
+ DCHECK(!id());
+ DCHECK(!size.IsEmpty());
+
+ set_dimensions(size, format);
+ set_id(resource_provider_->CreateManagedResource(
+ size,
+ target,
+ GL_CLAMP_TO_EDGE,
+ ResourceProvider::TextureUsageAny,
+ format));
+
+#ifndef NDEBUG
+ allocate_thread_id_ = base::PlatformThread::CurrentId();
+#endif
}
void ScopedResource::Free() {
diff --git a/chromium/cc/resources/scoped_resource.h b/chromium/cc/resources/scoped_resource.h
index 8e316eb76db..63f2cd48c47 100644
--- a/chromium/cc/resources/scoped_resource.h
+++ b/chromium/cc/resources/scoped_resource.h
@@ -19,15 +19,16 @@ namespace cc {
class CC_EXPORT ScopedResource : public Resource {
public:
- static scoped_ptr<ScopedResource> create(
+ static scoped_ptr<ScopedResource> Create(
ResourceProvider* resource_provider) {
return make_scoped_ptr(new ScopedResource(resource_provider));
}
virtual ~ScopedResource();
- bool Allocate(gfx::Size size,
+ void Allocate(gfx::Size size,
ResourceProvider::TextureUsageHint hint,
- ResourceFormat texture_format);
+ ResourceFormat format);
+ void AllocateManaged(gfx::Size size, GLenum target, ResourceFormat format);
void Free();
void Leak();
diff --git a/chromium/cc/resources/scoped_resource_unittest.cc b/chromium/cc/resources/scoped_resource_unittest.cc
index 8b59995f289..93ad3208b83 100644
--- a/chromium/cc/resources/scoped_resource_unittest.cc
+++ b/chromium/cc/resources/scoped_resource_unittest.cc
@@ -19,9 +19,9 @@ TEST(ScopedResourceTest, NewScopedResource) {
CHECK(output_surface->BindToClient(&output_surface_client));
scoped_ptr<ResourceProvider> resource_provider(
- ResourceProvider::Create(output_surface.get(), 0, false));
+ ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
scoped_ptr<ScopedResource> texture =
- ScopedResource::create(resource_provider.get());
+ ScopedResource::Create(resource_provider.get());
// New scoped textures do not hold a texture yet.
EXPECT_EQ(0u, texture->id());
@@ -37,9 +37,9 @@ TEST(ScopedResourceTest, CreateScopedResource) {
CHECK(output_surface->BindToClient(&output_surface_client));
scoped_ptr<ResourceProvider> resource_provider(
- ResourceProvider::Create(output_surface.get(), 0, false));
+ ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
scoped_ptr<ScopedResource> texture =
- ScopedResource::create(resource_provider.get());
+ ScopedResource::Create(resource_provider.get());
texture->Allocate(gfx::Size(30, 30),
ResourceProvider::TextureUsageAny,
RGBA_8888);
@@ -59,10 +59,10 @@ TEST(ScopedResourceTest, ScopedResourceIsDeleted) {
CHECK(output_surface->BindToClient(&output_surface_client));
scoped_ptr<ResourceProvider> resource_provider(
- ResourceProvider::Create(output_surface.get(), 0, false));
+ ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
{
scoped_ptr<ScopedResource> texture =
- ScopedResource::create(resource_provider.get());
+ ScopedResource::Create(resource_provider.get());
EXPECT_EQ(0u, resource_provider->num_resources());
texture->Allocate(gfx::Size(30, 30),
@@ -75,7 +75,7 @@ TEST(ScopedResourceTest, ScopedResourceIsDeleted) {
EXPECT_EQ(0u, resource_provider->num_resources());
{
scoped_ptr<ScopedResource> texture =
- ScopedResource::create(resource_provider.get());
+ ScopedResource::Create(resource_provider.get());
EXPECT_EQ(0u, resource_provider->num_resources());
texture->Allocate(gfx::Size(30, 30),
ResourceProvider::TextureUsageAny,
@@ -93,10 +93,10 @@ TEST(ScopedResourceTest, LeakScopedResource) {
CHECK(output_surface->BindToClient(&output_surface_client));
scoped_ptr<ResourceProvider> resource_provider(
- ResourceProvider::Create(output_surface.get(), 0, false));
+ ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
{
scoped_ptr<ScopedResource> texture =
- ScopedResource::create(resource_provider.get());
+ ScopedResource::Create(resource_provider.get());
EXPECT_EQ(0u, resource_provider->num_resources());
texture->Allocate(gfx::Size(30, 30),
diff --git a/chromium/cc/resources/shared_bitmap.cc b/chromium/cc/resources/shared_bitmap.cc
new file mode 100644
index 00000000000..3a6fc3589e3
--- /dev/null
+++ b/chromium/cc/resources/shared_bitmap.cc
@@ -0,0 +1,17 @@
+// 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/resources/shared_bitmap.h"
+
+namespace cc {
+
+SharedBitmap::SharedBitmap(
+ base::SharedMemory* memory,
+ const SharedBitmapId& id,
+ const base::Callback<void(SharedBitmap*)>& free_callback)
+ : memory_(memory), id_(id), free_callback_(free_callback) {}
+
+SharedBitmap::~SharedBitmap() { free_callback_.Run(this); }
+
+} // namespace cc
diff --git a/chromium/cc/resources/shared_bitmap.h b/chromium/cc/resources/shared_bitmap.h
new file mode 100644
index 00000000000..9575068411a
--- /dev/null
+++ b/chromium/cc/resources/shared_bitmap.h
@@ -0,0 +1,51 @@
+// 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_RESOURCES_SHARED_BITMAP_H_
+#define CC_RESOURCES_SHARED_BITMAP_H_
+
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/memory/shared_memory.h"
+#include "cc/base/cc_export.h"
+#include "gpu/command_buffer/common/mailbox.h"
+
+namespace base { class SharedMemory; }
+
+namespace cc {
+typedef gpu::Mailbox SharedBitmapId;
+
+class CC_EXPORT SharedBitmap {
+ public:
+ SharedBitmap(base::SharedMemory* memory,
+ const SharedBitmapId& id,
+ const base::Callback<void(SharedBitmap*)>& free_callback);
+
+ ~SharedBitmap();
+
+ bool operator<(const SharedBitmap& right) const {
+ if (memory_ < right.memory_)
+ return true;
+ if (memory_ > right.memory_)
+ return false;
+ return id_ < right.id_;
+ }
+
+ uint8* pixels() { return static_cast<uint8*>(memory_->memory()); }
+
+ base::SharedMemory* memory() { return memory_; }
+
+ SharedBitmapId id() { return id_; }
+
+ private:
+ base::SharedMemory* memory_;
+ SharedBitmapId id_;
+ base::Callback<void(SharedBitmap*)> free_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(SharedBitmap);
+};
+
+} // namespace cc
+
+#endif // CC_RESOURCES_SHARED_BITMAP_H_
diff --git a/chromium/cc/resources/shared_bitmap_manager.h b/chromium/cc/resources/shared_bitmap_manager.h
new file mode 100644
index 00000000000..53dd156470c
--- /dev/null
+++ b/chromium/cc/resources/shared_bitmap_manager.h
@@ -0,0 +1,32 @@
+// 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_RESOURCES_SHARED_BITMAP_MANAGER_H_
+#define CC_RESOURCES_SHARED_BITMAP_MANAGER_H_
+
+#include "base/basictypes.h"
+#include "cc/base/cc_export.h"
+#include "cc/resources/shared_bitmap.h"
+#include "ui/gfx/size.h"
+
+namespace cc {
+
+class CC_EXPORT SharedBitmapManager {
+ public:
+ SharedBitmapManager() {}
+
+ virtual scoped_ptr<SharedBitmap> AllocateSharedBitmap(gfx::Size) = 0;
+ virtual scoped_ptr<SharedBitmap> GetSharedBitmapFromId(
+ gfx::Size,
+ const SharedBitmapId&) = 0;
+ virtual scoped_ptr<SharedBitmap> GetBitmapForSharedMemory(
+ base::SharedMemory*) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SharedBitmapManager);
+};
+
+} // namespace cc
+
+#endif // CC_RESOURCES_SHARED_BITMAP_MANAGER_H_
diff --git a/chromium/cc/resources/sync_point_helper.cc b/chromium/cc/resources/sync_point_helper.cc
deleted file mode 100644
index f5822a41ae9..00000000000
--- a/chromium/cc/resources/sync_point_helper.cc
+++ /dev/null
@@ -1,48 +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/resources/sync_point_helper.h"
-
-#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
-
-namespace cc {
-
-class SignalSyncPointCallbackClass
- : public WebKit::WebGraphicsContext3D::WebGraphicsSyncPointCallback {
- public:
- explicit SignalSyncPointCallbackClass(const base::Closure& closure)
- : closure_(closure) {}
-
- virtual void onSyncPointReached() {
- if (!closure_.is_null())
- closure_.Run();
- }
-
- private:
- base::Closure closure_;
-};
-
-void SyncPointHelper::SignalSyncPoint(
- WebKit::WebGraphicsContext3D* context3d,
- unsigned sync_point,
- const base::Closure& closure) {
- SignalSyncPointCallbackClass* callback_class =
- new SignalSyncPointCallbackClass(closure);
-
- // Pass ownership of the CallbackClass to WebGraphicsContext3D.
- context3d->signalSyncPoint(sync_point, callback_class);
-}
-
-void SyncPointHelper::SignalQuery(
- WebKit::WebGraphicsContext3D* context3d,
- WebKit::WebGLId query,
- const base::Closure& closure) {
- SignalSyncPointCallbackClass* callback_class =
- new SignalSyncPointCallbackClass(closure);
-
- // Pass ownership of the CallbackClass to WebGraphicsContext3D.
- context3d->signalQuery(query, callback_class);
-}
-
-} // namespace cc
diff --git a/chromium/cc/resources/sync_point_helper.h b/chromium/cc/resources/sync_point_helper.h
deleted file mode 100644
index e33a7f25364..00000000000
--- a/chromium/cc/resources/sync_point_helper.h
+++ /dev/null
@@ -1,44 +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_RESOURCES_SYNC_POINT_HELPER_H_
-#define CC_RESOURCES_SYNC_POINT_HELPER_H_
-
-#include "base/callback.h"
-#include "cc/base/cc_export.h"
-
-namespace WebKit { class WebGraphicsContext3D; }
-
-namespace cc {
-
-class CC_EXPORT SyncPointHelper {
- public:
- // Requests a callback to |closure| when the |sync_point| is reached by the
- // |context3d|.
- //
- // If the |context3d| is destroyed or lost before the callback fires, then
- // AbortBecauseDidLoseOrDestroyContext() must be called to clean up the
- // callback's resources.
- static void SignalSyncPoint(WebKit::WebGraphicsContext3D* context3d,
- unsigned sync_point,
- const base::Closure& closure);
-
- // Requests a callback to |closure| when the results for |query| is available.
- //
- // If the |context3d| is destroyed or lost before the callback fires, then
- // AbortBecauseDidLoseOrDestroyContext() must be called to clean up the
- // callback's resources.
- static void SignalQuery(WebKit::WebGraphicsContext3D* context3d,
- unsigned int query,
- const base::Closure& closure);
-
- private:
- SyncPointHelper();
-
- DISALLOW_COPY_AND_ASSIGN(SyncPointHelper);
-};
-
-} // namespace cc
-
-#endif // CC_RESOURCES_SYNC_POINT_HELPER_H_
diff --git a/chromium/cc/resources/texture_mailbox_deleter.cc b/chromium/cc/resources/texture_mailbox_deleter.cc
index ae6df17691d..cf7b3b6107f 100644
--- a/chromium/cc/resources/texture_mailbox_deleter.cc
+++ b/chromium/cc/resources/texture_mailbox_deleter.cc
@@ -10,7 +10,7 @@
#include "base/message_loop/message_loop_proxy.h"
#include "cc/output/context_provider.h"
#include "cc/resources/single_release_callback.h"
-#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
namespace cc {
@@ -20,8 +20,8 @@ static void DeleteTextureOnImplThread(
unsigned sync_point,
bool is_lost) {
if (sync_point)
- context_provider->Context3d()->waitSyncPoint(sync_point);
- context_provider->Context3d()->deleteTexture(texture_id);
+ context_provider->ContextGL()->WaitSyncPointCHROMIUM(sync_point);
+ context_provider->ContextGL()->DeleteTextures(1, &texture_id);
}
static void PostTaskFromMainToImplThread(
diff --git a/chromium/cc/resources/texture_mailbox_deleter.h b/chromium/cc/resources/texture_mailbox_deleter.h
index 072dcab375b..9b6d771c0f5 100644
--- a/chromium/cc/resources/texture_mailbox_deleter.h
+++ b/chromium/cc/resources/texture_mailbox_deleter.h
@@ -37,8 +37,8 @@ class CC_EXPORT TextureMailboxDeleter {
unsigned sync_point,
bool is_lost);
- base::WeakPtrFactory<TextureMailboxDeleter> weak_ptr_factory_;
ScopedPtrVector<SingleReleaseCallback> impl_callbacks_;
+ base::WeakPtrFactory<TextureMailboxDeleter> weak_ptr_factory_;
};
} // namespace cc
diff --git a/chromium/cc/resources/texture_mailbox_deleter_unittest.cc b/chromium/cc/resources/texture_mailbox_deleter_unittest.cc
index a6ec48ed2ed..d08da84af90 100644
--- a/chromium/cc/resources/texture_mailbox_deleter_unittest.cc
+++ b/chromium/cc/resources/texture_mailbox_deleter_unittest.cc
@@ -4,9 +4,9 @@
#include "cc/resources/texture_mailbox_deleter.h"
-#include "cc/debug/test_context_provider.h"
-#include "cc/debug/test_web_graphics_context_3d.h"
#include "cc/resources/single_release_callback.h"
+#include "cc/test/test_context_provider.h"
+#include "cc/test/test_web_graphics_context_3d.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace cc {
diff --git a/chromium/cc/resources/tile.cc b/chromium/cc/resources/tile.cc
index d7e1d2c2da2..209780679cb 100644
--- a/chromium/cc/resources/tile.cc
+++ b/chromium/cc/resources/tile.cc
@@ -21,26 +21,24 @@ Tile::Tile(TileManager* tile_manager,
float contents_scale,
int layer_id,
int source_frame_number,
- bool can_use_lcd_text)
- : tile_manager_(tile_manager),
+ int flags)
+ : RefCountedManaged<Tile>(tile_manager),
+ tile_manager_(tile_manager),
tile_size_(tile_size),
content_rect_(content_rect),
contents_scale_(contents_scale),
opaque_rect_(opaque_rect),
layer_id_(layer_id),
source_frame_number_(source_frame_number),
- can_use_lcd_text_(can_use_lcd_text),
+ flags_(flags),
id_(s_next_id_++) {
set_picture_pile(picture_pile);
- tile_manager_->RegisterTile(this);
}
Tile::~Tile() {
TRACE_EVENT_OBJECT_DELETED_WITH_ID(
- TRACE_DISABLED_BY_DEFAULT("cc.debug") ","
- TRACE_DISABLED_BY_DEFAULT("cc.debug.quads"),
+ TRACE_DISABLED_BY_DEFAULT("cc.debug"),
"cc::Tile", this);
- tile_manager_->UnregisterTile(this);
}
void Tile::SetPriority(WhichTree tree, const TilePriority& priority) {
@@ -61,7 +59,8 @@ void Tile::MarkRequiredForActivation() {
scoped_ptr<base::Value> Tile::AsValue() const {
scoped_ptr<base::DictionaryValue> res(new base::DictionaryValue());
- TracedValue::MakeDictIntoImplicitSnapshot(res.get(), "cc::Tile", this);
+ TracedValue::MakeDictIntoImplicitSnapshotWithCategory(
+ TRACE_DISABLED_BY_DEFAULT("cc.debug"), res.get(), "cc::Tile", this);
res->Set("picture_pile",
TracedValue::CreateIDRef(picture_pile_.get()).release());
res->SetDouble("contents_scale", contents_scale_);
@@ -70,6 +69,8 @@ scoped_ptr<base::Value> Tile::AsValue() const {
res->Set("active_priority", priority_[ACTIVE_TREE].AsValue().release());
res->Set("pending_priority", priority_[PENDING_TREE].AsValue().release());
res->Set("managed_state", managed_state_.AsValue().release());
+ res->SetBoolean("can_use_lcd_text", can_use_lcd_text());
+ res->SetBoolean("use_gpu_rasterization", use_gpu_rasterization());
return res.PassAs<base::Value>();
}
diff --git a/chromium/cc/resources/tile.h b/chromium/cc/resources/tile.h
index 3caa407ae9c..e7c96360fe5 100644
--- a/chromium/cc/resources/tile.h
+++ b/chromium/cc/resources/tile.h
@@ -8,6 +8,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
+#include "cc/base/ref_counted_managed.h"
#include "cc/resources/managed_tile_state.h"
#include "cc/resources/raster_mode.h"
#include "cc/resources/tile_priority.h"
@@ -18,19 +19,14 @@ namespace cc {
class PicturePileImpl;
-class CC_EXPORT Tile : public base::RefCounted<Tile> {
+class CC_EXPORT Tile : public RefCountedManaged<Tile> {
public:
- typedef uint64 Id;
+ enum TileRasterFlags {
+ USE_LCD_TEXT = 1 << 0,
+ USE_GPU_RASTERIZATION = 1 << 1
+ };
- Tile(TileManager* tile_manager,
- PicturePileImpl* picture_pile,
- gfx::Size tile_size,
- gfx::Rect content_rect,
- gfx::Rect opaque_rect,
- float contents_scale,
- int layer_id,
- int source_frame_number,
- bool can_use_lcd_text);
+ typedef uint64 Id;
Id id() const {
return id_;
@@ -62,11 +58,25 @@ class CC_EXPORT Tile : public base::RefCounted<Tile> {
}
void set_can_use_lcd_text(bool can_use_lcd_text) {
- can_use_lcd_text_ = can_use_lcd_text;
+ if (can_use_lcd_text)
+ flags_ |= USE_LCD_TEXT;
+ else
+ flags_ &= ~USE_LCD_TEXT;
}
bool can_use_lcd_text() const {
- return can_use_lcd_text_;
+ return !!(flags_ & USE_LCD_TEXT);
+ }
+
+ void set_use_gpu_rasterization(bool use_gpu_rasterization) {
+ if (use_gpu_rasterization)
+ flags_ |= USE_GPU_RASTERIZATION;
+ else
+ flags_ &= ~USE_GPU_RASTERIZATION;
+ }
+
+ bool use_gpu_rasterization() const {
+ return !!(flags_ & USE_GPU_RASTERIZATION);
}
scoped_ptr<base::Value> AsValue() const;
@@ -116,18 +126,27 @@ class CC_EXPORT Tile : public base::RefCounted<Tile> {
gfx::Size size() const { return tile_size_.size(); }
private:
- // Methods called by by tile manager.
friend class TileManager;
friend class PrioritizedTileSet;
friend class FakeTileManager;
friend class BinComparator;
- ManagedTileState& managed_state() { return managed_state_; }
- const ManagedTileState& managed_state() const { return managed_state_; }
+ friend class FakePictureLayerImpl;
- // Normal private methods.
- friend class base::RefCounted<Tile>;
+ // Methods called by by tile manager.
+ Tile(TileManager* tile_manager,
+ PicturePileImpl* picture_pile,
+ gfx::Size tile_size,
+ gfx::Rect content_rect,
+ gfx::Rect opaque_rect,
+ float contents_scale,
+ int layer_id,
+ int source_frame_number,
+ int flags);
~Tile();
+ ManagedTileState& managed_state() { return managed_state_; }
+ const ManagedTileState& managed_state() const { return managed_state_; }
+
TileManager* tile_manager_;
scoped_refptr<PicturePileImpl> picture_pile_;
gfx::Rect tile_size_;
@@ -139,7 +158,7 @@ class CC_EXPORT Tile : public base::RefCounted<Tile> {
ManagedTileState managed_state_;
int layer_id_;
int source_frame_number_;
- bool can_use_lcd_text_;
+ int flags_;
Id id_;
static Id s_next_id_;
diff --git a/chromium/cc/resources/tile_manager.cc b/chromium/cc/resources/tile_manager.cc
index b8cbdca1fa7..2fbb6d18913 100644
--- a/chromium/cc/resources/tile_manager.cc
+++ b/chromium/cc/resources/tile_manager.cc
@@ -12,7 +12,6 @@
#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
-#include "cc/debug/devtools_instrumentation.h"
#include "cc/debug/traced_value.h"
#include "cc/resources/image_raster_worker_pool.h"
#include "cc/resources/pixel_buffer_raster_worker_pool.h"
@@ -34,75 +33,121 @@ const ManagedTileBin kBinPolicyMap[NUM_TILE_MEMORY_LIMIT_POLICIES][NUM_BINS] = {
NEVER_BIN, // [EVENTUALLY_BIN]
NEVER_BIN, // [AT_LAST_AND_ACTIVE_BIN]
NEVER_BIN, // [AT_LAST_BIN]
- NEVER_BIN // [NEVER_BIN]
+ NEVER_BIN
}, { // [ALLOW_ABSOLUTE_MINIMUM]
- NOW_AND_READY_TO_DRAW_BIN, // [NOW_AND_READY_TO_DRAW_BIN]
- NOW_BIN, // [NOW_BIN]
+ NOW_AND_READY_TO_DRAW_BIN,
+ NOW_BIN,
NEVER_BIN, // [SOON_BIN]
NEVER_BIN, // [EVENTUALLY_AND_ACTIVE_BIN]
NEVER_BIN, // [EVENTUALLY_BIN]
NEVER_BIN, // [AT_LAST_AND_ACTIVE_BIN]
NEVER_BIN, // [AT_LAST_BIN]
- NEVER_BIN // [NEVER_BIN]
+ NEVER_BIN
}, { // [ALLOW_PREPAINT_ONLY]
- NOW_AND_READY_TO_DRAW_BIN, // [NOW_AND_READY_TO_DRAW_BIN]
- NOW_BIN, // [NOW_BIN]
- SOON_BIN, // [SOON_BIN]
+ NOW_AND_READY_TO_DRAW_BIN,
+ NOW_BIN,
+ SOON_BIN,
NEVER_BIN, // [EVENTUALLY_AND_ACTIVE_BIN]
NEVER_BIN, // [EVENTUALLY_BIN]
NEVER_BIN, // [AT_LAST_AND_ACTIVE_BIN]
NEVER_BIN, // [AT_LAST_BIN]
- NEVER_BIN // [NEVER_BIN]
+ NEVER_BIN
}, { // [ALLOW_ANYTHING]
- NOW_AND_READY_TO_DRAW_BIN, // [NOW_AND_READY_TO_DRAW_BIN]
- NOW_BIN, // [NOW_BIN]
- SOON_BIN, // [SOON_BIN]
- EVENTUALLY_AND_ACTIVE_BIN, // [EVENTUALLY_AND_ACTIVE_BIN]
- EVENTUALLY_BIN, // [EVENTUALLY_BIN]
- AT_LAST_AND_ACTIVE_BIN, // [AT_LAST_AND_ACTIVE_BIN]
- AT_LAST_BIN, // [AT_LAST_BIN]
- NEVER_BIN // [NEVER_BIN]
+ NOW_AND_READY_TO_DRAW_BIN,
+ NOW_BIN,
+ SOON_BIN,
+ EVENTUALLY_AND_ACTIVE_BIN,
+ EVENTUALLY_BIN,
+ AT_LAST_AND_ACTIVE_BIN,
+ AT_LAST_BIN,
+ NEVER_BIN
+ }
+};
+
+// Ready to draw works by mapping NOW_BIN to NOW_AND_READY_TO_DRAW_BIN.
+const ManagedTileBin kBinReadyToDrawMap[2][NUM_BINS] = {
+ { // Not ready
+ NOW_AND_READY_TO_DRAW_BIN,
+ NOW_BIN,
+ SOON_BIN,
+ EVENTUALLY_AND_ACTIVE_BIN,
+ EVENTUALLY_BIN,
+ AT_LAST_AND_ACTIVE_BIN,
+ AT_LAST_BIN,
+ NEVER_BIN
+ }, { // Ready
+ NOW_AND_READY_TO_DRAW_BIN,
+ NOW_AND_READY_TO_DRAW_BIN, // [NOW_BIN]
+ SOON_BIN,
+ EVENTUALLY_AND_ACTIVE_BIN,
+ EVENTUALLY_BIN,
+ AT_LAST_AND_ACTIVE_BIN,
+ AT_LAST_BIN,
+ NEVER_BIN
+ }
+};
+
+// Active works by mapping some bin stats to equivalent _ACTIVE_BIN state.
+const ManagedTileBin kBinIsActiveMap[2][NUM_BINS] = {
+ { // Inactive
+ NOW_AND_READY_TO_DRAW_BIN,
+ NOW_BIN,
+ SOON_BIN,
+ EVENTUALLY_AND_ACTIVE_BIN,
+ EVENTUALLY_BIN,
+ AT_LAST_AND_ACTIVE_BIN,
+ AT_LAST_BIN,
+ NEVER_BIN
+ }, { // Active
+ NOW_AND_READY_TO_DRAW_BIN,
+ NOW_BIN,
+ SOON_BIN,
+ EVENTUALLY_AND_ACTIVE_BIN,
+ EVENTUALLY_AND_ACTIVE_BIN, // [EVENTUALLY_BIN]
+ AT_LAST_AND_ACTIVE_BIN,
+ AT_LAST_AND_ACTIVE_BIN, // [AT_LAST_BIN]
+ NEVER_BIN
}
};
// Determine bin based on three categories of tiles: things we need now,
// things we need soon, and eventually.
-inline ManagedTileBin BinFromTilePriority(const TilePriority& prio,
- TreePriority tree_priority,
- bool is_ready_to_draw,
- bool is_active) {
- // The amount of time for which we want to have prepainting coverage.
+inline ManagedTileBin BinFromTilePriority(const TilePriority& prio) {
+ // The amount of time/pixels for which we want to have prepainting coverage.
+ // Note: All very arbitrary constants: metric-based tuning is welcome!
const float kPrepaintingWindowTimeSeconds = 1.0f;
const float kBackflingGuardDistancePixels = 314.0f;
-
- // Don't let low res tiles be in the now bin unless we're in a mode where
- // we're prioritizing checkerboard prevention.
- bool can_be_in_now_bin = tree_priority == SMOOTHNESS_TAKES_PRIORITY ||
- prio.resolution != LOW_RESOLUTION;
+ // Note: The max distances here assume that SOON_BIN will never help overcome
+ // raster being too slow (only caching in advance will do that), so we just
+ // need enough padding to handle some latency and per-tile variability.
+ const float kMaxPrepaintingDistancePixelsHighRes = 2000.0f;
+ const float kMaxPrepaintingDistancePixelsLowRes = 4000.0f;
if (prio.distance_to_visible_in_pixels ==
std::numeric_limits<float>::infinity())
return NEVER_BIN;
- if (can_be_in_now_bin && prio.time_to_visible_in_seconds == 0)
- return is_ready_to_draw ? NOW_AND_READY_TO_DRAW_BIN : NOW_BIN;
+ if (prio.time_to_visible_in_seconds == 0)
+ return NOW_BIN;
if (prio.resolution == NON_IDEAL_RESOLUTION)
- return is_active ? EVENTUALLY_AND_ACTIVE_BIN : EVENTUALLY_BIN;
+ return EVENTUALLY_BIN;
+
+ float max_prepainting_distance_pixels =
+ (prio.resolution == HIGH_RESOLUTION)
+ ? kMaxPrepaintingDistancePixelsHighRes
+ : kMaxPrepaintingDistancePixelsLowRes;
+ // Soon bin if we are within backfling-guard, or under both the time window
+ // and the max distance window.
if (prio.distance_to_visible_in_pixels < kBackflingGuardDistancePixels ||
- prio.time_to_visible_in_seconds < kPrepaintingWindowTimeSeconds)
+ (prio.time_to_visible_in_seconds < kPrepaintingWindowTimeSeconds &&
+ prio.distance_to_visible_in_pixels <= max_prepainting_distance_pixels))
return SOON_BIN;
- return is_active ? EVENTUALLY_AND_ACTIVE_BIN : EVENTUALLY_BIN;
+ return EVENTUALLY_BIN;
}
-// Limit to the number of raster tasks that can be scheduled.
-// This is high enough to not cause unnecessary scheduling but
-// gives us an insurance that we're not spending a huge amount
-// of time scheduling one enormous set of tasks.
-const size_t kMaxRasterTasks = 256u;
-
} // namespace
RasterTaskCompletionStats::RasterTaskCompletionStats()
@@ -125,18 +170,23 @@ scoped_ptr<TileManager> TileManager::Create(
size_t num_raster_threads,
RenderingStatsInstrumentation* rendering_stats_instrumentation,
bool use_map_image,
- size_t max_transfer_buffer_usage_bytes) {
+ size_t max_transfer_buffer_usage_bytes,
+ size_t max_raster_usage_bytes,
+ GLenum map_image_texture_target) {
return make_scoped_ptr(
new TileManager(client,
resource_provider,
use_map_image ?
ImageRasterWorkerPool::Create(
- resource_provider, num_raster_threads) :
+ resource_provider,
+ num_raster_threads,
+ map_image_texture_target) :
PixelBufferRasterWorkerPool::Create(
resource_provider,
num_raster_threads,
max_transfer_buffer_usage_bytes),
num_raster_threads,
+ max_raster_usage_bytes,
rendering_stats_instrumentation));
}
@@ -145,9 +195,13 @@ TileManager::TileManager(
ResourceProvider* resource_provider,
scoped_ptr<RasterWorkerPool> raster_worker_pool,
size_t num_raster_threads,
+ size_t max_raster_usage_bytes,
RenderingStatsInstrumentation* rendering_stats_instrumentation)
: client_(client),
- resource_pool_(ResourcePool::Create(resource_provider)),
+ resource_pool_(ResourcePool::Create(
+ resource_provider,
+ raster_worker_pool->GetResourceTarget(),
+ raster_worker_pool->GetResourceFormat())),
raster_worker_pool_(raster_worker_pool.Pass()),
prioritized_tiles_dirty_(false),
all_tiles_that_need_to_be_rasterized_have_memory_(true),
@@ -156,6 +210,7 @@ TileManager::TileManager(
memory_nice_to_have_bytes_(0),
bytes_releasable_(0),
resources_releasable_(0),
+ max_raster_usage_bytes_(max_raster_usage_bytes),
ever_exceeded_memory_budget_(false),
rendering_stats_instrumentation_(rendering_stats_instrumentation),
did_initialize_visible_tile_(false),
@@ -168,6 +223,7 @@ TileManager::~TileManager() {
// our memory usage to drop to zero.
global_state_ = GlobalStateThatImpactsTilePriority();
+ CleanUpReleasedTiles();
DCHECK_EQ(0u, tiles_.size());
RasterWorkerPool::RasterTask::Queue empty;
@@ -182,56 +238,53 @@ TileManager::~TileManager() {
DCHECK_EQ(0u, resources_releasable_);
}
-void TileManager::SetGlobalState(
- const GlobalStateThatImpactsTilePriority& global_state) {
- global_state_ = global_state;
- resource_pool_->SetResourceUsageLimits(
- global_state_.memory_limit_in_bytes,
- global_state_.unused_memory_limit_in_bytes,
- global_state_.num_resources_limit);
+void TileManager::Release(Tile* tile) {
+ prioritized_tiles_dirty_ = true;
+ released_tiles_.push_back(tile);
}
-void TileManager::RegisterTile(Tile* tile) {
- DCHECK(!tile->required_for_activation());
- DCHECK(tiles_.find(tile->id()) == tiles_.end());
-
- tiles_[tile->id()] = tile;
- used_layer_counts_[tile->layer_id()]++;
+void TileManager::DidChangeTilePriority(Tile* tile) {
prioritized_tiles_dirty_ = true;
}
-void TileManager::UnregisterTile(Tile* tile) {
- FreeResourcesForTile(tile);
+bool TileManager::ShouldForceTasksRequiredForActivationToComplete() const {
+ return global_state_.tree_priority != SMOOTHNESS_TAKES_PRIORITY;
+}
- DCHECK(tiles_.find(tile->id()) != tiles_.end());
- tiles_.erase(tile->id());
+void TileManager::CleanUpReleasedTiles() {
+ for (std::vector<Tile*>::iterator it = released_tiles_.begin();
+ it != released_tiles_.end();
+ ++it) {
+ Tile* tile = *it;
- 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());
- }
+ FreeResourcesForTile(tile);
- prioritized_tiles_dirty_ = true;
-}
+ DCHECK(tiles_.find(tile->id()) != tiles_.end());
+ tiles_.erase(tile->id());
-void TileManager::DidChangeTilePriority(Tile* tile) {
- prioritized_tiles_dirty_ = true;
-}
+ 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());
+ }
-bool TileManager::ShouldForceTasksRequiredForActivationToComplete() const {
- return GlobalState().tree_priority != SMOOTHNESS_TAKES_PRIORITY;
+ delete tile;
+ }
+
+ released_tiles_.clear();
}
-PrioritizedTileSet* TileManager::GetPrioritizedTileSet() {
+void TileManager::UpdatePrioritizedTileSetIfNeeded() {
if (!prioritized_tiles_dirty_)
- return &prioritized_tiles_;
+ return;
+
+ CleanUpReleasedTiles();
prioritized_tiles_.Clear();
GetTilesWithAssignedBins(&prioritized_tiles_);
prioritized_tiles_dirty_ = false;
- return &prioritized_tiles_;
}
void TileManager::DidFinishRunningTasks() {
@@ -246,7 +299,7 @@ void TileManager::DidFinishRunningTasks() {
did_check_for_completed_tasks_since_last_schedule_tasks_ = true;
TileVector tiles_that_need_to_be_rasterized;
- AssignGpuMemoryToTiles(GetPrioritizedTileSet(),
+ AssignGpuMemoryToTiles(&prioritized_tiles_,
&tiles_that_need_to_be_rasterized);
// |tiles_that_need_to_be_rasterized| will be empty when we reach a
@@ -318,44 +371,68 @@ void TileManager::GetTilesWithAssignedBins(PrioritizedTileSet* tiles) {
// Get the active priority and bin.
TilePriority active_priority = tile->priority(ACTIVE_TREE);
- ManagedTileBin active_bin = BinFromTilePriority(
- active_priority, tree_priority, tile_is_ready_to_draw, tile_is_active);
- mts.tree_bin[ACTIVE_TREE] = kBinPolicyMap[memory_policy][active_bin];
+ ManagedTileBin active_bin = BinFromTilePriority(active_priority);
// Get the pending priority and bin.
TilePriority pending_priority = tile->priority(PENDING_TREE);
- ManagedTileBin pending_bin = BinFromTilePriority(
- pending_priority, tree_priority, tile_is_ready_to_draw, tile_is_active);
- mts.tree_bin[PENDING_TREE] = kBinPolicyMap[memory_policy][pending_bin];
-
- // Get the combined priority and bin.
- TilePriority combined_priority = tile->combined_priority();
- ManagedTileBin combined_bin = BinFromTilePriority(combined_priority,
- tree_priority,
- tile_is_ready_to_draw,
- tile_is_active);
+ ManagedTileBin pending_bin = BinFromTilePriority(pending_priority);
+
+ bool pending_is_low_res =
+ pending_priority.resolution == LOW_RESOLUTION;
+ bool pending_is_non_ideal =
+ pending_priority.resolution == NON_IDEAL_RESOLUTION;
+ bool active_is_non_ideal =
+ active_priority.resolution == NON_IDEAL_RESOLUTION;
+
+ // Adjust pending bin state for low res tiles. This prevents
+ // pending tree low-res tiles from being initialized before
+ // high-res tiles.
+ if (pending_is_low_res)
+ pending_bin = std::max(pending_bin, EVENTUALLY_BIN);
+
+ // Adjust bin state based on if ready to draw.
+ active_bin = kBinReadyToDrawMap[tile_is_ready_to_draw][active_bin];
+ pending_bin = kBinReadyToDrawMap[tile_is_ready_to_draw][pending_bin];
+
+ // Adjust bin state based on if active.
+ active_bin = kBinIsActiveMap[tile_is_active][active_bin];
+ pending_bin = kBinIsActiveMap[tile_is_active][pending_bin];
+
+ // We never want to paint new non-ideal tiles, as we always have
+ // a high-res tile covering that content (paint that instead).
+ if (!tile_is_ready_to_draw && active_is_non_ideal)
+ active_bin = NEVER_BIN;
+ if (!tile_is_ready_to_draw && pending_is_non_ideal)
+ pending_bin = NEVER_BIN;
+
+ // Compute combined bin.
+ ManagedTileBin combined_bin = std::min(active_bin, pending_bin);
+
+ ManagedTileBin tree_bin[NUM_TREES];
+ tree_bin[ACTIVE_TREE] = kBinPolicyMap[memory_policy][active_bin];
+ tree_bin[PENDING_TREE] = kBinPolicyMap[memory_policy][pending_bin];
// The bin that the tile would have if the GPU memory manager had
// a maximally permissive policy, send to the GPU memory manager
// to determine policy.
ManagedTileBin gpu_memmgr_stats_bin = NEVER_BIN;
+ TilePriority tile_priority;
- TilePriority* high_priority = NULL;
switch (tree_priority) {
case SAME_PRIORITY_FOR_BOTH_TREES:
mts.bin = kBinPolicyMap[memory_policy][combined_bin];
gpu_memmgr_stats_bin = combined_bin;
- high_priority = &combined_priority;
+ tile_priority = tile->combined_priority();
break;
case SMOOTHNESS_TAKES_PRIORITY:
- mts.bin = mts.tree_bin[ACTIVE_TREE];
+ mts.bin = tree_bin[ACTIVE_TREE];
gpu_memmgr_stats_bin = active_bin;
- high_priority = &active_priority;
+ tile_priority = active_priority;
break;
case NEW_CONTENT_TAKES_PRIORITY:
- mts.bin = mts.tree_bin[PENDING_TREE];
+ mts.bin = tree_bin[PENDING_TREE];
gpu_memmgr_stats_bin = pending_bin;
- high_priority = &pending_priority;
+ tile_priority = pending_priority;
break;
}
@@ -370,22 +447,20 @@ void TileManager::GetTilesWithAssignedBins(PrioritizedTileSet* tiles) {
// Bump up the priority if we determined it's NEVER_BIN on one tree,
// but is still required on the other tree.
bool is_in_never_bin_on_both_trees =
- mts.tree_bin[ACTIVE_TREE] == NEVER_BIN &&
- mts.tree_bin[PENDING_TREE] == NEVER_BIN;
+ tree_bin[ACTIVE_TREE] == NEVER_BIN &&
+ tree_bin[PENDING_TREE] == NEVER_BIN;
if (mts.bin == NEVER_BIN && !is_in_never_bin_on_both_trees)
mts.bin = tile_is_active ? AT_LAST_AND_ACTIVE_BIN : AT_LAST_BIN;
- DCHECK(high_priority != NULL);
-
- mts.resolution = high_priority->resolution;
- mts.time_to_needed_in_seconds = high_priority->time_to_visible_in_seconds;
+ mts.resolution = tile_priority.resolution;
+ mts.time_to_needed_in_seconds = tile_priority.time_to_visible_in_seconds;
mts.distance_to_visible_in_pixels =
- high_priority->distance_to_visible_in_pixels;
- mts.required_for_activation = high_priority->required_for_activation;
+ tile_priority.distance_to_visible_in_pixels;
+ mts.required_for_activation = tile_priority.required_for_activation;
mts.visible_and_ready_to_draw =
- mts.tree_bin[ACTIVE_TREE] == NOW_AND_READY_TO_DRAW_BIN;
+ tree_bin[ACTIVE_TREE] == NOW_AND_READY_TO_DRAW_BIN;
if (mts.bin == NEVER_BIN) {
FreeResourcesForTile(tile);
@@ -406,9 +481,19 @@ void TileManager::GetTilesWithAssignedBins(PrioritizedTileSet* tiles) {
}
}
-void TileManager::ManageTiles() {
+void TileManager::ManageTiles(const GlobalStateThatImpactsTilePriority& state) {
TRACE_EVENT0("cc", "TileManager::ManageTiles");
+ // Update internal state.
+ if (state != global_state_) {
+ global_state_ = state;
+ prioritized_tiles_dirty_ = true;
+ resource_pool_->SetResourceUsageLimits(
+ global_state_.memory_limit_in_bytes,
+ global_state_.unused_memory_limit_in_bytes,
+ global_state_.num_resources_limit);
+ }
+
// We need to call CheckForCompletedTasks() once in-between each call
// to ScheduleTasks() to prevent canceled tasks from being scheduled.
if (!did_check_for_completed_tasks_since_last_schedule_tasks_) {
@@ -416,8 +501,10 @@ void TileManager::ManageTiles() {
did_check_for_completed_tasks_since_last_schedule_tasks_ = true;
}
+ UpdatePrioritizedTileSetIfNeeded();
+
TileVector tiles_that_need_to_be_rasterized;
- AssignGpuMemoryToTiles(GetPrioritizedTileSet(),
+ AssignGpuMemoryToTiles(&prioritized_tiles_,
&tiles_that_need_to_be_rasterized);
// Finally, schedule rasterizer tasks.
@@ -523,6 +610,13 @@ void TileManager::AssignGpuMemoryToTiles(
TileVector* tiles_that_need_to_be_rasterized) {
TRACE_EVENT0("cc", "TileManager::AssignGpuMemoryToTiles");
+ // Maintain the list of released resources that can potentially be re-used
+ // 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();
+
// Now give memory out to the tiles until we're out, and build
// the needs-to-be-rasterized queue.
all_tiles_that_need_to_be_rasterized_have_memory_ = true;
@@ -547,6 +641,14 @@ void TileManager::AssignGpuMemoryToTiles(
size_t resources_left = resources_allocatable;
bool oomed = false;
+ // Memory we assign to raster tasks now will be deducted from our memory
+ // in future iterations if priorities change. By assigning at most half
+ // the raster limit, we will always have another 50% left even if priorities
+ // change completely (assuming we check for completed/cancelled rasters
+ // between each call to this function).
+ size_t max_raster_bytes = max_raster_usage_bytes_ / 2;
+ size_t raster_bytes = 0;
+
unsigned schedule_priority = 1u;
for (PrioritizedTileSet::Iterator it(tiles, true);
it;
@@ -571,13 +673,16 @@ void TileManager::AssignGpuMemoryToTiles(
continue;
}
+ size_t bytes_if_allocated = BytesConsumedIfAllocated(tile);
+ size_t raster_bytes_if_rastered = raster_bytes + bytes_if_allocated;
+
size_t tile_bytes = 0;
size_t tile_resources = 0;
// It costs to maintain a resource.
for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) {
if (mts.tile_versions[mode].resource_) {
- tile_bytes += BytesConsumedIfAllocated(tile);
+ tile_bytes += bytes_if_allocated;
tile_resources++;
}
}
@@ -585,11 +690,11 @@ void TileManager::AssignGpuMemoryToTiles(
// Allow lower priority tiles with initialized resources to keep
// their memory by only assigning memory to new raster tasks if
// they can be scheduled.
- if (tiles_that_need_to_be_rasterized->size() < kMaxRasterTasks) {
+ if (raster_bytes_if_rastered <= max_raster_bytes) {
// If we don't have the required version, and it's not in flight
// then we'll have to pay to create a new task.
if (!tile_version.resource_ && tile_version.raster_task_.is_null()) {
- tile_bytes += BytesConsumedIfAllocated(tile);
+ tile_bytes += bytes_if_allocated;
tile_resources++;
}
}
@@ -624,7 +729,7 @@ void TileManager::AssignGpuMemoryToTiles(
// 1. Tile size should not impact raster priority.
// 2. Tiles with existing raster task could otherwise incorrectly
// be added as they are not affected by |bytes_allocatable|.
- if (oomed || tiles_that_need_to_be_rasterized->size() >= kMaxRasterTasks) {
+ if (oomed || raster_bytes_if_rastered > max_raster_bytes) {
all_tiles_that_need_to_be_rasterized_have_memory_ = false;
if (tile->required_for_activation())
all_tiles_required_for_activation_have_memory_ = false;
@@ -632,6 +737,7 @@ void TileManager::AssignGpuMemoryToTiles(
continue;
}
+ raster_bytes = raster_bytes_if_rastered;
tiles_that_need_to_be_rasterized->push_back(tile);
}
@@ -742,11 +848,9 @@ RasterWorkerPool::Task TileManager::CreateImageDecodeTask(
RasterWorkerPool::RasterTask TileManager::CreateRasterTask(Tile* tile) {
ManagedTileState& mts = tile->managed_state();
- scoped_ptr<ResourcePool::Resource> resource =
- resource_pool_->AcquireResource(
- tile->tile_size_.size(),
- raster_worker_pool_->GetResourceFormat());
- const Resource* const_resource = resource.get();
+ scoped_ptr<ScopedResource> resource =
+ resource_pool_->AcquireResource(tile->tile_size_.size());
+ const ScopedResource* const_resource = resource.get();
// Create and queue all image decode tasks that this tile depends on.
RasterWorkerPool::Task::Set decode_tasks;
@@ -778,7 +882,6 @@ RasterWorkerPool::RasterTask TileManager::CreateRasterTask(Tile* tile) {
tile->content_rect(),
tile->contents_scale(),
mts.raster_mode,
- mts.tree_bin[PENDING_TREE] == NOW_BIN,
mts.resolution,
tile->layer_id(),
static_cast<const void *>(tile),
@@ -817,7 +920,7 @@ void TileManager::OnImageDecodeTaskCompleted(
void TileManager::OnRasterTaskCompleted(
Tile::Id tile_id,
- scoped_ptr<ResourcePool::Resource> resource,
+ scoped_ptr<ScopedResource> resource,
RasterMode raster_mode,
const PicturePileImpl::Analysis& analysis,
bool was_canceled) {
@@ -860,4 +963,29 @@ void TileManager::OnRasterTaskCompleted(
did_initialize_visible_tile_ = true;
}
+scoped_refptr<Tile> TileManager::CreateTile(PicturePileImpl* picture_pile,
+ gfx::Size tile_size,
+ gfx::Rect content_rect,
+ gfx::Rect opaque_rect,
+ float contents_scale,
+ int layer_id,
+ int source_frame_number,
+ int flags) {
+ scoped_refptr<Tile> tile = make_scoped_refptr(new Tile(this,
+ picture_pile,
+ tile_size,
+ content_rect,
+ opaque_rect,
+ contents_scale,
+ layer_id,
+ source_frame_number,
+ flags));
+ DCHECK(tiles_.find(tile->id()) == tiles_.end());
+
+ tiles_[tile->id()] = tile;
+ used_layer_counts_[tile->layer_id()]++;
+ prioritized_tiles_dirty_ = true;
+ return tile;
+}
+
} // namespace cc
diff --git a/chromium/cc/resources/tile_manager.h b/chromium/cc/resources/tile_manager.h
index 3f262bcf28d..78beb1b15fb 100644
--- a/chromium/cc/resources/tile_manager.h
+++ b/chromium/cc/resources/tile_manager.h
@@ -12,6 +12,7 @@
#include "base/containers/hash_tables.h"
#include "base/memory/scoped_ptr.h"
#include "base/values.h"
+#include "cc/base/ref_counted_managed.h"
#include "cc/debug/rendering_stats_instrumentation.h"
#include "cc/resources/managed_tile_state.h"
#include "cc/resources/memory_history.h"
@@ -45,7 +46,8 @@ scoped_ptr<base::Value> RasterTaskCompletionStatsAsValue(
// should no longer have any memory assigned to them. Tile objects are "owned"
// by layers; they automatically register with the manager when they are
// created, and unregister from the manager when they are deleted.
-class CC_EXPORT TileManager : public RasterWorkerPoolClient {
+class CC_EXPORT TileManager : public RasterWorkerPoolClient,
+ public RefCountedManager<Tile> {
public:
static scoped_ptr<TileManager> Create(
TileManagerClient* client,
@@ -53,19 +55,25 @@ class CC_EXPORT TileManager : public RasterWorkerPoolClient {
size_t num_raster_threads,
RenderingStatsInstrumentation* rendering_stats_instrumentation,
bool use_map_image,
- size_t max_transfer_buffer_usage_bytes);
+ size_t max_transfer_buffer_usage_bytes,
+ size_t max_raster_usage_bytes,
+ GLenum map_image_texture_target);
virtual ~TileManager();
- const GlobalStateThatImpactsTilePriority& GlobalState() const {
- return global_state_;
- }
- void SetGlobalState(const GlobalStateThatImpactsTilePriority& state);
-
- void ManageTiles();
+ void ManageTiles(const GlobalStateThatImpactsTilePriority& state);
// Returns true when visible tiles have been initialized.
bool UpdateVisibleTiles();
+ scoped_refptr<Tile> CreateTile(PicturePileImpl* picture_pile,
+ gfx::Size tile_size,
+ gfx::Rect content_rect,
+ gfx::Rect opaque_rect,
+ float contents_scale,
+ int layer_id,
+ int source_frame_number,
+ int flags);
+
scoped_ptr<base::Value> BasicStateAsValue() const;
scoped_ptr<base::Value> AllTilesAsValue() const;
void GetMemoryStats(size_t* memory_required_bytes,
@@ -85,10 +93,8 @@ class CC_EXPORT TileManager : public RasterWorkerPoolClient {
ManagedTileState::TileVersion& tile_version =
mts.tile_versions[HIGH_QUALITY_NO_LCD_RASTER_MODE];
- tile_version.resource_ = make_scoped_ptr(
- new ResourcePool::Resource(resource_provider,
- gfx::Size(1, 1),
- resource_provider->best_texture_format()));
+ tile_version.resource_ = resource_pool_->AcquireResource(
+ gfx::Size(1, 1));
bytes_releasable_ += BytesConsumedIfAllocated(tiles[i]);
++resources_releasable_;
@@ -98,19 +104,35 @@ class CC_EXPORT TileManager : public RasterWorkerPoolClient {
return raster_worker_pool_.get();
}
+ void SetGlobalStateForTesting(
+ const GlobalStateThatImpactsTilePriority& state) {
+ if (state != global_state_) {
+ global_state_ = state;
+ prioritized_tiles_dirty_ = true;
+ resource_pool_->SetResourceUsageLimits(
+ global_state_.memory_limit_in_bytes,
+ global_state_.unused_memory_limit_in_bytes,
+ global_state_.num_resources_limit);
+ }
+ }
+
protected:
TileManager(TileManagerClient* client,
ResourceProvider* resource_provider,
scoped_ptr<RasterWorkerPool> raster_worker_pool,
size_t num_raster_threads,
+ size_t max_raster_usage_bytes,
RenderingStatsInstrumentation* rendering_stats_instrumentation);
// Methods called by Tile
friend class Tile;
- void RegisterTile(Tile* tile);
- void UnregisterTile(Tile* tile);
void DidChangeTilePriority(Tile* tile);
+ void CleanUpReleasedTiles();
+
+ // Overriden from RefCountedManager<Tile>:
+ virtual void Release(Tile* tile) OVERRIDE;
+
// Overriden from RasterWorkerPoolClient:
virtual bool ShouldForceTasksRequiredForActivationToComplete() const
OVERRIDE;
@@ -134,12 +156,11 @@ class CC_EXPORT TileManager : public RasterWorkerPoolClient {
int layer_id,
skia::LazyPixelRef* pixel_ref,
bool was_canceled);
- void OnRasterTaskCompleted(
- Tile::Id tile,
- scoped_ptr<ResourcePool::Resource> resource,
- RasterMode raster_mode,
- const PicturePileImpl::Analysis& analysis,
- bool was_canceled);
+ void OnRasterTaskCompleted(Tile::Id tile,
+ scoped_ptr<ScopedResource> resource,
+ RasterMode raster_mode,
+ const PicturePileImpl::Analysis& analysis,
+ bool was_canceled);
inline size_t BytesConsumedIfAllocated(const Tile* tile) const {
return Resource::MemorySizeBytes(tile->size(),
@@ -154,7 +175,7 @@ class CC_EXPORT TileManager : public RasterWorkerPoolClient {
Tile* tile, skia::LazyPixelRef* pixel_ref);
RasterWorkerPool::RasterTask CreateRasterTask(Tile* tile);
scoped_ptr<base::Value> GetMemoryRequirementsAsValue() const;
- PrioritizedTileSet* GetPrioritizedTileSet();
+ void UpdatePrioritizedTileSetIfNeeded();
TileManagerClient* client_;
scoped_ptr<ResourcePool> resource_pool_;
@@ -175,6 +196,7 @@ class CC_EXPORT TileManager : public RasterWorkerPoolClient {
size_t bytes_releasable_;
size_t resources_releasable_;
+ size_t max_raster_usage_bytes_;
bool ever_exceeded_memory_budget_;
MemoryHistory::Entry memory_stats_from_last_assign_;
@@ -193,6 +215,8 @@ class CC_EXPORT TileManager : public RasterWorkerPoolClient {
RasterTaskCompletionStats update_visible_tiles_stats_;
+ std::vector<Tile*> released_tiles_;
+
DISALLOW_COPY_AND_ASSIGN(TileManager);
};
diff --git a/chromium/cc/resources/tile_manager_perftest.cc b/chromium/cc/resources/tile_manager_perftest.cc
index 99d16a187e7..9a651a2afa4 100644
--- a/chromium/cc/resources/tile_manager_perftest.cc
+++ b/chromium/cc/resources/tile_manager_perftest.cc
@@ -40,10 +40,16 @@ class TileManagerPerfTest : public testing::Test {
CHECK(output_surface_->BindToClient(&output_surface_client_));
resource_provider_ =
- ResourceProvider::Create(output_surface_.get(), 0, false);
+ ResourceProvider::Create(output_surface_.get(), NULL, 0, false, 1);
+ size_t raster_task_limit_bytes = 32 * 1024 * 1024; // 16-64MB in practice.
tile_manager_ = make_scoped_ptr(
- new FakeTileManager(&tile_manager_client_, resource_provider_.get()));
+ new FakeTileManager(&tile_manager_client_,
+ resource_provider_.get(),
+ raster_task_limit_bytes));
+ picture_pile_ = FakePicturePileImpl::CreatePile();
+ }
+ GlobalStateThatImpactsTilePriority GlobalStateForTest() {
GlobalStateThatImpactsTilePriority state;
gfx::Size tile_size = settings_.default_tile_size;
state.memory_limit_in_bytes =
@@ -52,9 +58,7 @@ class TileManagerPerfTest : public testing::Test {
state.num_resources_limit = 10000;
state.memory_limit_policy = ALLOW_ANYTHING;
state.tree_priority = SMOOTHNESS_TAKES_PRIORITY;
-
- tile_manager_->SetGlobalState(state);
- picture_pile_ = FakePicturePileImpl::CreatePile();
+ return state;
}
virtual void TearDown() OVERRIDE {
@@ -105,15 +109,14 @@ class TileManagerPerfTest : public testing::Test {
void CreateBinTiles(int count, ManagedTileBin bin, TileBinVector* tiles) {
for (int i = 0; i < count; ++i) {
scoped_refptr<Tile> tile =
- make_scoped_refptr(new Tile(tile_manager_.get(),
- picture_pile_.get(),
- settings_.default_tile_size,
- gfx::Rect(),
- gfx::Rect(),
- 1.0,
- 0,
- 0,
- true));
+ tile_manager_->CreateTile(picture_pile_.get(),
+ settings_.default_tile_size,
+ gfx::Rect(),
+ gfx::Rect(),
+ 1.0,
+ 0,
+ 0,
+ Tile::USE_LCD_TEXT);
tile->SetPriority(ACTIVE_TREE, GetTilePriorityFromBin(bin));
tile->SetPriority(PENDING_TREE, GetTilePriorityFromBin(bin));
tiles->push_back(std::make_pair(tile, bin));
@@ -151,7 +154,7 @@ class TileManagerPerfTest : public testing::Test {
}
}
- tile_manager_->ManageTiles();
+ tile_manager_->ManageTiles(GlobalStateForTest());
tile_manager_->CheckForCompletedTasks();
timer_.NextLap();
} while (!timer_.HasTimeLimitExpired());
diff --git a/chromium/cc/resources/tile_manager_unittest.cc b/chromium/cc/resources/tile_manager_unittest.cc
index 0274914a324..8339bd07b0a 100644
--- a/chromium/cc/resources/tile_manager_unittest.cc
+++ b/chromium/cc/resources/tile_manager_unittest.cc
@@ -26,7 +26,7 @@ class TileManagerTest : public testing::TestWithParam<bool> {
CHECK(output_surface_->BindToClient(&output_surface_client_));
resource_provider_ =
- ResourceProvider::Create(output_surface_.get(), 0, false);
+ ResourceProvider::Create(output_surface_.get(), NULL, 0, false, 1);
tile_manager_ = make_scoped_ptr(
new FakeTileManager(&tile_manager_client_, resource_provider_.get()));
@@ -49,7 +49,8 @@ class TileManagerTest : public testing::TestWithParam<bool> {
state.memory_limit_policy = memory_limit_policy;
state.tree_priority = tree_priority;
- tile_manager_->SetGlobalState(state);
+ global_state_ = state;
+ tile_manager_->SetGlobalStateForTesting(state);
picture_pile_ = FakePicturePileImpl::CreatePile();
}
@@ -62,7 +63,7 @@ class TileManagerTest : public testing::TestWithParam<bool> {
state.memory_limit_policy = memory_limit_policy_;
state.num_resources_limit = 100;
state.tree_priority = tree_priority;
- tile_manager_->SetGlobalState(state);
+ global_state_ = state;
}
virtual void TearDown() OVERRIDE {
@@ -78,16 +79,14 @@ class TileManagerTest : public testing::TestWithParam<bool> {
gfx::Size tile_size) {
TileVector tiles;
for (int i = 0; i < count; ++i) {
- scoped_refptr<Tile> tile =
- make_scoped_refptr(new Tile(tile_manager_.get(),
- picture_pile_.get(),
- tile_size,
- gfx::Rect(),
- gfx::Rect(),
- 1.0,
- 0,
- 0,
- true));
+ scoped_refptr<Tile> tile = tile_manager_->CreateTile(picture_pile_.get(),
+ tile_size,
+ gfx::Rect(),
+ gfx::Rect(),
+ 1.0,
+ 0,
+ 0,
+ Tile::USE_LCD_TEXT);
tile->SetPriority(ACTIVE_TREE, active_priority);
tile->SetPriority(PENDING_TREE, pending_priority);
tiles.push_back(tile);
@@ -130,6 +129,9 @@ class TileManagerTest : public testing::TestWithParam<bool> {
return has_lcd_count;
}
+ protected:
+ GlobalStateThatImpactsTilePriority global_state_;
+
private:
FakeTileManagerClient tile_manager_client_;
LayerTreeSettings settings_;
@@ -154,7 +156,7 @@ TEST_P(TileManagerTest, EnoughMemoryAllowAnything) {
3, TilePriorityForSoonBin(), TilePriorityForSoonBin());
TileVector never_bin = CreateTiles(1, TilePriority(), TilePriority());
- tile_manager()->AssignMemoryToTiles();
+ tile_manager()->AssignMemoryToTiles(global_state_);
EXPECT_EQ(3, AssignedMemoryCount(active_now));
EXPECT_EQ(3, AssignedMemoryCount(pending_now));
@@ -175,7 +177,7 @@ TEST_P(TileManagerTest, EnoughMemoryAllowPrepaintOnly) {
3, TilePriorityForSoonBin(), TilePriorityForSoonBin());
TileVector never_bin = CreateTiles(1, TilePriority(), TilePriority());
- tile_manager()->AssignMemoryToTiles();
+ tile_manager()->AssignMemoryToTiles(global_state_);
EXPECT_EQ(3, AssignedMemoryCount(active_now));
EXPECT_EQ(3, AssignedMemoryCount(pending_now));
@@ -196,7 +198,7 @@ TEST_P(TileManagerTest, EnoughMemoryAllowAbsoluteMinimum) {
3, TilePriorityForSoonBin(), TilePriorityForSoonBin());
TileVector never_bin = CreateTiles(1, TilePriority(), TilePriority());
- tile_manager()->AssignMemoryToTiles();
+ tile_manager()->AssignMemoryToTiles(global_state_);
EXPECT_EQ(3, AssignedMemoryCount(active_now));
EXPECT_EQ(3, AssignedMemoryCount(pending_now));
@@ -217,7 +219,7 @@ TEST_P(TileManagerTest, EnoughMemoryAllowNothing) {
3, TilePriorityForSoonBin(), TilePriorityForSoonBin());
TileVector never_bin = CreateTiles(1, TilePriority(), TilePriority());
- tile_manager()->AssignMemoryToTiles();
+ tile_manager()->AssignMemoryToTiles(global_state_);
EXPECT_EQ(0, AssignedMemoryCount(active_now));
EXPECT_EQ(0, AssignedMemoryCount(pending_now));
@@ -237,13 +239,13 @@ TEST_P(TileManagerTest, PartialOOMMemoryToPending) {
TileVector pending_tree_tiles =
CreateTiles(5, TilePriority(), TilePriorityRequiredForActivation());
- tile_manager()->AssignMemoryToTiles();
+ tile_manager()->AssignMemoryToTiles(global_state_);
EXPECT_EQ(5, AssignedMemoryCount(active_tree_tiles));
EXPECT_EQ(3, AssignedMemoryCount(pending_tree_tiles));
SetTreePriority(SAME_PRIORITY_FOR_BOTH_TREES);
- tile_manager()->AssignMemoryToTiles();
+ tile_manager()->AssignMemoryToTiles(global_state_);
EXPECT_EQ(3, AssignedMemoryCount(active_tree_tiles));
EXPECT_EQ(5, AssignedMemoryCount(pending_tree_tiles));
@@ -260,7 +262,7 @@ TEST_P(TileManagerTest, PartialOOMMemoryToActive) {
TileVector pending_tree_tiles =
CreateTiles(5, TilePriority(), TilePriorityForNowBin());
- tile_manager()->AssignMemoryToTiles();
+ tile_manager()->AssignMemoryToTiles(global_state_);
EXPECT_EQ(5, AssignedMemoryCount(active_tree_tiles));
EXPECT_EQ(3, AssignedMemoryCount(pending_tree_tiles));
@@ -278,13 +280,13 @@ TEST_P(TileManagerTest, TotalOOMMemoryToPending) {
TileVector pending_tree_tiles =
CreateTiles(5, TilePriority(), TilePriorityRequiredForActivation());
- tile_manager()->AssignMemoryToTiles();
+ tile_manager()->AssignMemoryToTiles(global_state_);
EXPECT_EQ(4, AssignedMemoryCount(active_tree_tiles));
EXPECT_EQ(0, AssignedMemoryCount(pending_tree_tiles));
SetTreePriority(SAME_PRIORITY_FOR_BOTH_TREES);
- tile_manager()->AssignMemoryToTiles();
+ tile_manager()->AssignMemoryToTiles(global_state_);
EXPECT_EQ(0, AssignedMemoryCount(active_tree_tiles));
EXPECT_EQ(4, AssignedMemoryCount(pending_tree_tiles));
@@ -302,13 +304,13 @@ TEST_P(TileManagerTest, TotalOOMActiveSoonMemoryToPending) {
TileVector pending_tree_tiles =
CreateTiles(5, TilePriority(), TilePriorityRequiredForActivation());
- tile_manager()->AssignMemoryToTiles();
+ tile_manager()->AssignMemoryToTiles(global_state_);
EXPECT_EQ(4, AssignedMemoryCount(active_tree_tiles));
EXPECT_EQ(0, AssignedMemoryCount(pending_tree_tiles));
SetTreePriority(SAME_PRIORITY_FOR_BOTH_TREES);
- tile_manager()->AssignMemoryToTiles();
+ tile_manager()->AssignMemoryToTiles(global_state_);
EXPECT_EQ(0, AssignedMemoryCount(active_tree_tiles));
EXPECT_EQ(4, AssignedMemoryCount(pending_tree_tiles));
@@ -325,7 +327,7 @@ TEST_P(TileManagerTest, TotalOOMMemoryToActive) {
TileVector pending_tree_tiles =
CreateTiles(5, TilePriority(), TilePriorityForNowBin());
- tile_manager()->AssignMemoryToTiles();
+ tile_manager()->AssignMemoryToTiles(global_state_);
EXPECT_EQ(4, AssignedMemoryCount(active_tree_tiles));
EXPECT_EQ(0, AssignedMemoryCount(pending_tree_tiles));
@@ -340,7 +342,7 @@ TEST_P(TileManagerTest, RasterAsLCD) {
TileVector pending_tree_tiles =
CreateTiles(5, TilePriority(), TilePriorityForNowBin());
- tile_manager()->ManageTiles();
+ tile_manager()->AssignMemoryToTiles(global_state_);
EXPECT_EQ(5, TilesWithLCDCount(active_tree_tiles));
EXPECT_EQ(5, TilesWithLCDCount(pending_tree_tiles));
@@ -364,7 +366,7 @@ TEST_P(TileManagerTest, RasterAsNoLCD) {
(*it)->set_can_use_lcd_text(false);
}
- tile_manager()->ManageTiles();
+ tile_manager()->AssignMemoryToTiles(global_state_);
EXPECT_EQ(0, TilesWithLCDCount(active_tree_tiles));
EXPECT_EQ(0, TilesWithLCDCount(pending_tree_tiles));
@@ -377,7 +379,7 @@ TEST_P(TileManagerTest, ReRasterAsNoLCD) {
TileVector pending_tree_tiles =
CreateTiles(5, TilePriority(), TilePriorityForNowBin());
- tile_manager()->ManageTiles();
+ tile_manager()->AssignMemoryToTiles(global_state_);
EXPECT_EQ(5, TilesWithLCDCount(active_tree_tiles));
EXPECT_EQ(5, TilesWithLCDCount(pending_tree_tiles));
@@ -393,7 +395,7 @@ TEST_P(TileManagerTest, ReRasterAsNoLCD) {
(*it)->set_can_use_lcd_text(false);
}
- tile_manager()->ManageTiles();
+ tile_manager()->AssignMemoryToTiles(global_state_);
EXPECT_EQ(0, TilesWithLCDCount(active_tree_tiles));
EXPECT_EQ(0, TilesWithLCDCount(pending_tree_tiles));
@@ -406,7 +408,7 @@ TEST_P(TileManagerTest, NoTextDontReRasterAsNoLCD) {
TileVector pending_tree_tiles =
CreateTiles(5, TilePriority(), TilePriorityForNowBin());
- tile_manager()->ManageTiles();
+ tile_manager()->AssignMemoryToTiles(global_state_);
EXPECT_EQ(5, TilesWithLCDCount(active_tree_tiles));
EXPECT_EQ(5, TilesWithLCDCount(pending_tree_tiles));
@@ -430,7 +432,7 @@ TEST_P(TileManagerTest, NoTextDontReRasterAsNoLCD) {
EXPECT_TRUE((*it)->IsReadyToDraw());
}
- tile_manager()->ManageTiles();
+ tile_manager()->AssignMemoryToTiles(global_state_);
EXPECT_EQ(5, TilesWithLCDCount(active_tree_tiles));
EXPECT_EQ(5, TilesWithLCDCount(pending_tree_tiles));
@@ -443,7 +445,7 @@ TEST_P(TileManagerTest, TextReRasterAsNoLCD) {
TileVector pending_tree_tiles =
CreateTiles(5, TilePriority(), TilePriorityForNowBin());
- tile_manager()->ManageTiles();
+ tile_manager()->AssignMemoryToTiles(global_state_);
EXPECT_EQ(5, TilesWithLCDCount(active_tree_tiles));
EXPECT_EQ(5, TilesWithLCDCount(pending_tree_tiles));
@@ -472,7 +474,7 @@ TEST_P(TileManagerTest, TextReRasterAsNoLCD) {
EXPECT_TRUE((*it)->IsReadyToDraw());
}
- tile_manager()->ManageTiles();
+ tile_manager()->AssignMemoryToTiles(global_state_);
EXPECT_EQ(0, TilesWithLCDCount(active_tree_tiles));
EXPECT_EQ(0, TilesWithLCDCount(pending_tree_tiles));
@@ -488,20 +490,19 @@ TEST_P(TileManagerTest, RespectMemoryLimit) {
size_t memory_allocated_bytes;
size_t memory_used_bytes;
- tile_manager()->ManageTiles();
+ tile_manager()->AssignMemoryToTiles(global_state_);
tile_manager()->GetMemoryStats(&memory_required_bytes,
&memory_nice_to_have_bytes,
&memory_allocated_bytes,
&memory_used_bytes);
// Allocated bytes should never be more than the memory limit.
- EXPECT_LE(memory_allocated_bytes,
- tile_manager()->GlobalState().memory_limit_in_bytes);
+ EXPECT_LE(memory_allocated_bytes, global_state_.memory_limit_in_bytes);
// Finish raster of large tiles.
tile_manager()->UpdateVisibleTiles();
// Remove all large tiles. This will leave the memory currently
- // used by these tiles as unused when ManageTiles() is called.
+ // used by these tiles as unused when AssignMemoryToTiles() is called.
large_tiles.clear();
// Create a new set of tiles using a different size. These tiles
@@ -510,14 +511,13 @@ TEST_P(TileManagerTest, RespectMemoryLimit) {
TileVector small_tiles = CreateTilesWithSize(
5, TilePriorityForNowBin(), TilePriority(), gfx::Size(128, 128));
- tile_manager()->ManageTiles();
+ tile_manager()->AssignMemoryToTiles(global_state_);
tile_manager()->GetMemoryStats(&memory_required_bytes,
&memory_nice_to_have_bytes,
&memory_allocated_bytes,
&memory_used_bytes);
// Allocated bytes should never be more than the memory limit.
- EXPECT_LE(memory_allocated_bytes,
- tile_manager()->GlobalState().memory_limit_in_bytes);
+ EXPECT_LE(memory_allocated_bytes, global_state_.memory_limit_in_bytes);
}
// If true, the max tile limit should be applied as bytes; if false,
diff --git a/chromium/cc/resources/tile_priority.cc b/chromium/cc/resources/tile_priority.cc
index eeb87cdcbbc..9cf4634f7d5 100644
--- a/chromium/cc/resources/tile_priority.cc
+++ b/chromium/cc/resources/tile_priority.cc
@@ -18,14 +18,6 @@ struct Range {
float end_;
};
-inline bool Intersects(const Range& a, const Range& b) {
- return a.start_ < b.end_ && b.start_ < a.end_;
-}
-
-inline Range Intersect(const Range& a, const Range& b) {
- return Range(std::max(a.start_, b.start_), std::min(a.end_, b.end_));
-}
-
bool Range::IsEmpty() {
return start_ >= end_;
}
diff --git a/chromium/cc/resources/tile_priority.h b/chromium/cc/resources/tile_priority.h
index e613dd77b04..0052e40ddce 100644
--- a/chromium/cc/resources/tile_priority.h
+++ b/chromium/cc/resources/tile_priority.h
@@ -75,26 +75,9 @@ struct CC_EXPORT TilePriority {
std::min(active.distance_to_visible_in_pixels,
pending.distance_to_visible_in_pixels);
}
- void set_current_screen_quad(const gfx::QuadF& q) { current_screen_quad = q; }
scoped_ptr<base::Value> AsValue() const;
- static inline float manhattanDistance(const gfx::RectF& a,
- const gfx::RectF& b) {
- // Compute the union explicitly.
- gfx::RectF c = gfx::RectF(
- std::min(a.x(), b.x()),
- std::min(a.y(), b.y()),
- std::max(a.right(), b.right()) - std::min(a.x(), b.x()),
- std::max(a.bottom(), b.bottom()) - std::min(a.y(), b.y()));
-
- // Rects touching the edge of the screen should not be considered visible.
- // So we add 1 pixel here to avoid that situation.
- float x = std::max(0.0f, c.width() - a.width() - b.width() + 1.0f);
- float y = std::max(0.0f, c.height() - a.height() - b.height() + 1.0f);
- return (x + y);
- }
-
// Calculate the time for the |current_bounds| to intersect with the
// |target_bounds| given its previous location and time delta.
// This function should work for both scaling and scrolling case.
@@ -108,8 +91,6 @@ struct CC_EXPORT TilePriority {
time_to_visible_in_seconds == other.time_to_visible_in_seconds &&
distance_to_visible_in_pixels == other.distance_to_visible_in_pixels &&
required_for_activation == other.required_for_activation;
- // No need to compare current_screen_quad which is for debug only and
- // never changes by itself.
}
bool operator !=(const TilePriority& other) const {
@@ -120,9 +101,6 @@ struct CC_EXPORT TilePriority {
bool required_for_activation;
float time_to_visible_in_seconds;
float distance_to_visible_in_pixels;
-
- private:
- gfx::QuadF current_screen_quad;
};
enum TileMemoryLimitPolicy {
@@ -172,6 +150,17 @@ class GlobalStateThatImpactsTilePriority {
TreePriority tree_priority;
+ bool operator==(const GlobalStateThatImpactsTilePriority& other) const {
+ return memory_limit_policy == other.memory_limit_policy
+ && memory_limit_in_bytes == other.memory_limit_in_bytes
+ && unused_memory_limit_in_bytes == other.unused_memory_limit_in_bytes
+ && num_resources_limit == other.num_resources_limit
+ && tree_priority == other.tree_priority;
+ }
+ bool operator!=(const GlobalStateThatImpactsTilePriority& other) const {
+ return !(*this == other);
+ }
+
scoped_ptr<base::Value> AsValue() const;
};
diff --git a/chromium/cc/resources/tile_priority_unittest.cc b/chromium/cc/resources/tile_priority_unittest.cc
index 97de199b094..0f4c6717aff 100644
--- a/chromium/cc/resources/tile_priority_unittest.cc
+++ b/chromium/cc/resources/tile_priority_unittest.cc
@@ -49,19 +49,5 @@ TEST(TilePriorityTest, TimeForBoundsToIntersectWithScale) {
gfx::Rect(-450, -450, 50, 50), current, 1, target));
}
-TEST(TilePriorityTest, ManhattanDistanceBetweenRects) {
- EXPECT_EQ(0, TilePriority::manhattanDistance(
- gfx::RectF(0, 0, 400, 400), gfx::RectF(0, 0, 100, 100)));
-
- EXPECT_EQ(2, TilePriority::manhattanDistance(
- gfx::Rect(0, 0, 400, 400), gfx::Rect(-100, -100, 100, 100)));
-
- EXPECT_EQ(1, TilePriority::manhattanDistance(
- gfx::Rect(0, 0, 400, 400), gfx::Rect(0, -100, 100, 100)));
-
- EXPECT_EQ(202, TilePriority::manhattanDistance(
- gfx::Rect(0, 0, 100, 100), gfx::Rect(200, 200, 100, 100)));
-}
-
} // namespace
} // namespace cc
diff --git a/chromium/cc/resources/transferable_resource.cc b/chromium/cc/resources/transferable_resource.cc
index 1b8930f34ad..62f1bdb1641 100644
--- a/chromium/cc/resources/transferable_resource.cc
+++ b/chromium/cc/resources/transferable_resource.cc
@@ -12,8 +12,9 @@ TransferableResource::TransferableResource()
: id(0),
sync_point(0),
format(RGBA_8888),
- filter(0) {
-}
+ target(0),
+ filter(0),
+ is_software(false) {}
TransferableResource::~TransferableResource() {
}
diff --git a/chromium/cc/resources/transferable_resource.h b/chromium/cc/resources/transferable_resource.h
index 0ea62436991..5c93d1c042f 100644
--- a/chromium/cc/resources/transferable_resource.h
+++ b/chromium/cc/resources/transferable_resource.h
@@ -31,9 +31,11 @@ struct CC_EXPORT TransferableResource {
unsigned id;
unsigned sync_point;
ResourceFormat format;
+ uint32 target;
uint32 filter;
gfx::Size size;
gpu::Mailbox mailbox;
+ bool is_software;
};
} // namespace cc
diff --git a/chromium/cc/resources/ui_resource_bitmap.cc b/chromium/cc/resources/ui_resource_bitmap.cc
index 86acfa5185c..b813d973537 100644
--- a/chromium/cc/resources/ui_resource_bitmap.cc
+++ b/chromium/cc/resources/ui_resource_bitmap.cc
@@ -6,26 +6,29 @@
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
+#include "cc/resources/etc1_pixel_ref.h"
#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkPixelRef.h"
namespace cc {
void UIResourceBitmap::Create(const skia::RefPtr<SkPixelRef>& pixel_ref,
UIResourceFormat format,
- UIResourceWrapMode wrap_mode,
gfx::Size size) {
DCHECK(size.width());
DCHECK(size.height());
DCHECK(pixel_ref);
DCHECK(pixel_ref->isImmutable());
format_ = format;
- wrap_mode_ = wrap_mode;
size_ = size;
pixel_ref_ = pixel_ref;
+
+ // Default values for secondary parameters.
+ wrap_mode_ = CLAMP_TO_EDGE;
+ opaque_ = (format == ETC1);
}
-UIResourceBitmap::UIResourceBitmap(const SkBitmap& skbitmap,
- UIResourceWrapMode wrap_mode) {
+UIResourceBitmap::UIResourceBitmap(const SkBitmap& skbitmap) {
DCHECK_EQ(skbitmap.config(), SkBitmap::kARGB_8888_Config);
DCHECK_EQ(skbitmap.width(), skbitmap.rowBytesAsPixels());
DCHECK(skbitmap.isImmutable());
@@ -33,8 +36,15 @@ UIResourceBitmap::UIResourceBitmap(const SkBitmap& skbitmap,
skia::RefPtr<SkPixelRef> pixel_ref = skia::SharePtr(skbitmap.pixelRef());
Create(pixel_ref,
UIResourceBitmap::RGBA8,
- wrap_mode,
gfx::Size(skbitmap.width(), skbitmap.height()));
+
+ SetOpaque(skbitmap.isOpaque());
+}
+
+UIResourceBitmap::UIResourceBitmap(
+ const skia::RefPtr<ETC1PixelRef>& etc1_pixel_ref,
+ gfx::Size size) {
+ Create(etc1_pixel_ref, ETC1, size);
}
UIResourceBitmap::~UIResourceBitmap() {}
diff --git a/chromium/cc/resources/ui_resource_bitmap.h b/chromium/cc/resources/ui_resource_bitmap.h
index 78cb4658125..ea54f613b10 100644
--- a/chromium/cc/resources/ui_resource_bitmap.h
+++ b/chromium/cc/resources/ui_resource_bitmap.h
@@ -17,14 +17,17 @@ class SkBitmap;
namespace cc {
-// A bitmap class that contains a ref-counted reference to a SkPixelRef* that
+class ETC1PixelRef;
+
+// A bitmap class that contains a ref-counted reference to a SkPixelRef that
// holds the content of the bitmap (cannot use SkBitmap because of ETC1).
// Thread-safety (by ways of SkPixelRef) ensures that both main and impl threads
// can hold references to the bitmap and that asynchronous uploads are allowed.
class CC_EXPORT UIResourceBitmap {
public:
enum UIResourceFormat {
- RGBA8
+ RGBA8,
+ ETC1
};
enum UIResourceWrapMode {
CLAMP_TO_EDGE,
@@ -34,12 +37,16 @@ class CC_EXPORT UIResourceBitmap {
gfx::Size GetSize() const { return size_; }
UIResourceFormat GetFormat() const { return format_; }
UIResourceWrapMode GetWrapMode() const { return wrap_mode_; }
+ void SetWrapMode(UIResourceWrapMode wrap_mode) { wrap_mode_ = wrap_mode; }
+ bool GetOpaque() const { return opaque_; }
+ void SetOpaque(bool opaque) { opaque_ = opaque; }
+
+ // User must ensure that |skbitmap| is immutable. The SkBitmap Format should
+ // be 32-bit RGBA.
+ explicit UIResourceBitmap(const SkBitmap& skbitmap);
- // The constructor for the UIResourceBitmap. User must ensure that |skbitmap|
- // is immutable. The SkBitmap format should be in 32-bit RGBA. Wrap mode is
- // unnecessary for most UI resources and is defaulted to CLAMP_TO_EDGE.
- UIResourceBitmap(const SkBitmap& skbitmap,
- UIResourceWrapMode wrap_mode = CLAMP_TO_EDGE);
+ UIResourceBitmap(const skia::RefPtr<ETC1PixelRef>& etc1_pixel_ref,
+ gfx::Size size);
~UIResourceBitmap();
@@ -47,13 +54,13 @@ class CC_EXPORT UIResourceBitmap {
friend class AutoLockUIResourceBitmap;
void Create(const skia::RefPtr<SkPixelRef>& pixel_ref,
UIResourceFormat format,
- UIResourceWrapMode wrap_mode,
gfx::Size size);
skia::RefPtr<SkPixelRef> pixel_ref_;
UIResourceFormat format_;
UIResourceWrapMode wrap_mode_;
gfx::Size size_;
+ bool opaque_;
};
class CC_EXPORT AutoLockUIResourceBitmap {
diff --git a/chromium/cc/resources/ui_resource_request.cc b/chromium/cc/resources/ui_resource_request.cc
new file mode 100644
index 00000000000..75680369c6d
--- /dev/null
+++ b/chromium/cc/resources/ui_resource_request.cc
@@ -0,0 +1,37 @@
+// 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/resources/ui_resource_request.h"
+
+namespace cc {
+
+UIResourceRequest::UIResourceRequest(UIResourceRequestType type,
+ UIResourceId id)
+ : type_(type), id_(id) {}
+
+UIResourceRequest::UIResourceRequest(UIResourceRequestType type,
+ UIResourceId id,
+ const UIResourceBitmap& bitmap)
+ : type_(type), id_(id), bitmap_(new UIResourceBitmap(bitmap)) {}
+
+UIResourceRequest::UIResourceRequest(const UIResourceRequest& request) {
+ (*this) = request;
+}
+
+UIResourceRequest& UIResourceRequest::operator=(
+ const UIResourceRequest& request) {
+ type_ = request.type_;
+ id_ = request.id_;
+ if (request.bitmap_) {
+ bitmap_ = make_scoped_ptr(new UIResourceBitmap(*request.bitmap_.get()));
+ } else {
+ bitmap_.reset();
+ }
+
+ return *this;
+}
+
+UIResourceRequest::~UIResourceRequest() {}
+
+} // namespace cc
diff --git a/chromium/cc/resources/ui_resource_request.h b/chromium/cc/resources/ui_resource_request.h
new file mode 100644
index 00000000000..6d89761d44b
--- /dev/null
+++ b/chromium/cc/resources/ui_resource_request.h
@@ -0,0 +1,49 @@
+// 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_RESOURCES_UI_RESOURCE_REQUEST_H_
+#define CC_RESOURCES_UI_RESOURCE_REQUEST_H_
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "cc/base/cc_export.h"
+#include "cc/resources/ui_resource_bitmap.h"
+#include "cc/resources/ui_resource_client.h"
+
+namespace cc {
+
+class CC_EXPORT UIResourceRequest {
+ public:
+ enum UIResourceRequestType {
+ UIResourceCreate,
+ UIResourceDelete,
+ UIResourceInvalidRequest
+ };
+
+ UIResourceRequest(UIResourceRequestType type, UIResourceId id);
+ UIResourceRequest(UIResourceRequestType type,
+ UIResourceId id,
+ const UIResourceBitmap& bitmap);
+ UIResourceRequest(const UIResourceRequest& request);
+
+ ~UIResourceRequest();
+
+ UIResourceRequestType GetType() const { return type_; }
+ UIResourceId GetId() const { return id_; }
+ UIResourceBitmap GetBitmap() const {
+ DCHECK(bitmap_);
+ return *bitmap_.get();
+ }
+
+ UIResourceRequest& operator=(const UIResourceRequest& request);
+
+ private:
+ UIResourceRequestType type_;
+ UIResourceId id_;
+ scoped_ptr<UIResourceBitmap> bitmap_;
+};
+
+} // namespace cc
+
+#endif // CC_RESOURCES_UI_RESOURCE_REQUEST_H_
diff --git a/chromium/cc/resources/video_resource_updater.cc b/chromium/cc/resources/video_resource_updater.cc
index 34c7ab65c35..4abeab149d3 100644
--- a/chromium/cc/resources/video_resource_updater.cc
+++ b/chromium/cc/resources/video_resource_updater.cc
@@ -8,9 +8,9 @@
#include "cc/output/gl_renderer.h"
#include "cc/resources/resource_provider.h"
#include "gpu/GLES2/gl2extchromium.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
#include "media/base/video_frame.h"
#include "media/filters/skcanvas_video_renderer.h"
-#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/khronos/GLES2/gl2ext.h"
#include "ui/gfx/size_conversions.h"
@@ -69,16 +69,16 @@ bool VideoResourceUpdater::VerifyFrame(
case media::VideoFrame::YV12:
case media::VideoFrame::YV12A:
case media::VideoFrame::YV16:
+ case media::VideoFrame::YV12J:
case media::VideoFrame::NATIVE_TEXTURE:
-#if defined(GOOGLE_TV)
+#if defined(VIDEO_HOLE)
case media::VideoFrame::HOLE:
-#endif
+#endif // defined(VIDEO_HOLE)
return true;
// Unacceptable inputs. ¯\(°_o)/¯
- case media::VideoFrame::INVALID:
- case media::VideoFrame::RGB32:
- case media::VideoFrame::EMPTY:
+ case media::VideoFrame::UNKNOWN:
+ case media::VideoFrame::HISTOGRAM_MAX:
case media::VideoFrame::I420:
break;
}
@@ -100,18 +100,18 @@ static gfx::Size SoftwarePlaneDimension(
switch (input_frame_format) {
case media::VideoFrame::YV12:
case media::VideoFrame::YV12A:
+ case media::VideoFrame::YV12J:
return gfx::ToFlooredSize(gfx::ScaleSize(coded_size, 0.5f, 0.5f));
case media::VideoFrame::YV16:
return gfx::ToFlooredSize(gfx::ScaleSize(coded_size, 0.5f, 1.f));
- case media::VideoFrame::INVALID:
- case media::VideoFrame::RGB32:
- case media::VideoFrame::EMPTY:
+ case media::VideoFrame::UNKNOWN:
case media::VideoFrame::I420:
case media::VideoFrame::NATIVE_TEXTURE:
-#if defined(GOOGLE_TV)
+ case media::VideoFrame::HISTOGRAM_MAX:
+#if defined(VIDEO_HOLE)
case media::VideoFrame::HOLE:
-#endif
+#endif // defined(VIDEO_HOLE)
NOTREACHED();
}
}
@@ -124,20 +124,22 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
const scoped_refptr<media::VideoFrame>& video_frame) {
media::VideoFrame::Format input_frame_format = video_frame->format();
-#if defined(GOOGLE_TV)
+#if defined(VIDEO_HOLE)
if (input_frame_format == media::VideoFrame::HOLE) {
VideoFrameExternalResources external_resources;
external_resources.type = VideoFrameExternalResources::HOLE;
return external_resources;
}
-#endif
+#endif // defined(VIDEO_HOLE)
// Only YUV software video frames are supported.
DCHECK(input_frame_format == media::VideoFrame::YV12 ||
input_frame_format == media::VideoFrame::YV12A ||
+ input_frame_format == media::VideoFrame::YV12J ||
input_frame_format == media::VideoFrame::YV16);
if (input_frame_format != media::VideoFrame::YV12 &&
input_frame_format != media::VideoFrame::YV12A &&
+ input_frame_format != media::VideoFrame::YV12J &&
input_frame_format != media::VideoFrame::YV16)
return VideoFrameExternalResources();
@@ -203,20 +205,18 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
if (!software_compositor) {
DCHECK(context_provider_);
- WebKit::WebGraphicsContext3D* context =
- context_provider_->Context3d();
+ gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
- GLC(context, context->genMailboxCHROMIUM(mailbox.name));
+ GLC(gl, gl->GenMailboxCHROMIUM(mailbox.name));
if (mailbox.IsZero()) {
resource_provider_->DeleteResource(resource_id);
resource_id = 0;
} else {
ResourceProvider::ScopedWriteLockGL lock(
resource_provider_, resource_id);
- GLC(context, context->bindTexture(GL_TEXTURE_2D, lock.texture_id()));
- GLC(context, context->produceTextureCHROMIUM(GL_TEXTURE_2D,
- mailbox.name));
- GLC(context, context->bindTexture(GL_TEXTURE_2D, 0));
+ GLC(gl, gl->BindTexture(GL_TEXTURE_2D, lock.texture_id()));
+ GLC(gl, gl->ProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name));
+ GLC(gl, gl->BindTexture(GL_TEXTURE_2D, 0));
}
}
@@ -261,24 +261,30 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
0xff);
}
- // In software mode, the resource provider won't be lost. Soon this callback
- // will be called directly from the resource provider, same as 3d
- // compositing mode, so this raw unretained resource_provider will always
- // be valid when the callback is fired.
RecycleResourceData recycle_data = {
plane_resources[0].resource_id,
plane_resources[0].resource_size,
plane_resources[0].resource_format,
gpu::Mailbox()
};
+ base::SharedMemory* shared_memory =
+ resource_provider_->GetSharedMemory(plane_resources[0].resource_id);
+ if (shared_memory) {
+ external_resources.mailboxes.push_back(
+ TextureMailbox(shared_memory, plane_resources[0].resource_size));
+ external_resources.release_callbacks
+ .push_back(base::Bind(&RecycleResource, AsWeakPtr(), recycle_data));
+ external_resources.type = VideoFrameExternalResources::RGB_RESOURCE;
+ } else {
+ // TODO(jbauman): Remove this path once shared memory is available
+ // everywhere.
+ external_resources.software_resources
+ .push_back(plane_resources[0].resource_id);
+ external_resources.software_release_callback =
+ base::Bind(&RecycleResource, AsWeakPtr(), recycle_data);
+ external_resources.type = VideoFrameExternalResources::SOFTWARE_RESOURCE;
+ }
- external_resources.software_resources.push_back(
- plane_resources[0].resource_id);
- external_resources.software_release_callback =
- base::Bind(&RecycleResource, AsWeakPtr(), recycle_data);
-
-
- external_resources.type = VideoFrameExternalResources::SOFTWARE_RESOURCE;
return external_resources;
}
@@ -316,11 +322,10 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
return external_resources;
}
-static void ReturnTexture(
- scoped_refptr<media::VideoFrame::MailboxHolder> mailbox_holder,
- unsigned sync_point,
- bool lost_resource) {
- mailbox_holder->Return(sync_point);
+static void ReturnTexture(const scoped_refptr<media::VideoFrame>& frame,
+ unsigned sync_point,
+ bool lost_resource) {
+ frame->texture_mailbox()->Resync(sync_point);
}
VideoFrameExternalResources VideoResourceUpdater::CreateForHardwarePlanes(
@@ -351,7 +356,7 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForHardwarePlanes(
return VideoFrameExternalResources();
}
- scoped_refptr<media::VideoFrame::MailboxHolder> mailbox_holder =
+ media::VideoFrame::MailboxHolder* mailbox_holder =
video_frame->texture_mailbox();
external_resources.mailboxes.push_back(
@@ -359,7 +364,7 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForHardwarePlanes(
video_frame->texture_target(),
mailbox_holder->sync_point()));
external_resources.release_callbacks.push_back(
- base::Bind(&ReturnTexture, mailbox_holder));
+ base::Bind(&ReturnTexture, video_frame));
return external_resources;
}
@@ -376,8 +381,8 @@ void VideoResourceUpdater::RecycleResource(
ContextProvider* context_provider = updater->context_provider_;
if (context_provider && sync_point) {
- GLC(context_provider->Context3d(),
- context_provider->Context3d()->waitSyncPoint(sync_point));
+ GLC(context_provider->ContextGL(),
+ context_provider->ContextGL()->WaitSyncPointCHROMIUM(sync_point));
}
if (lost_resource) {
diff --git a/chromium/cc/resources/video_resource_updater.h b/chromium/cc/resources/video_resource_updater.h
index e3476d44bb4..2a27739cef7 100644
--- a/chromium/cc/resources/video_resource_updater.h
+++ b/chromium/cc/resources/video_resource_updater.h
@@ -37,11 +37,11 @@ class CC_EXPORT VideoFrameExternalResources {
STREAM_TEXTURE_RESOURCE,
IO_SURFACE,
-#if defined(GOOGLE_TV)
+#if defined(VIDEO_HOLE)
// TODO(danakj): Implement this with a solid color layer instead of a video
// frame and video layer.
HOLE,
-#endif
+#endif // defined(VIDEO_HOLE)
// TODO(danakj): Remove this and abstract TextureMailbox into
// "ExternalResource" that can hold a hardware or software backing.
diff --git a/chromium/cc/resources/video_resource_updater_unittest.cc b/chromium/cc/resources/video_resource_updater_unittest.cc
index c36689e16c1..dcb72e349d3 100644
--- a/chromium/cc/resources/video_resource_updater_unittest.cc
+++ b/chromium/cc/resources/video_resource_updater_unittest.cc
@@ -5,10 +5,10 @@
#include "cc/resources/video_resource_updater.h"
#include "base/memory/shared_memory.h"
-#include "cc/debug/test_web_graphics_context_3d.h"
#include "cc/resources/resource_provider.h"
#include "cc/test/fake_output_surface.h"
#include "cc/test/fake_output_surface_client.h"
+#include "cc/test/test_web_graphics_context_3d.h"
#include "media/base/video_frame.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -26,7 +26,7 @@ class VideoResourceUpdaterTest : public testing::Test {
FakeOutputSurface::Create3d(context3d.Pass());
CHECK(output_surface3d_->BindToClient(&client_));
resource_provider3d_ =
- ResourceProvider::Create(output_surface3d_.get(), 0, false);
+ ResourceProvider::Create(output_surface3d_.get(), NULL, 0, false, 1);
}
scoped_refptr<media::VideoFrame> CreateTestYUVVideoFrame() {
diff --git a/chromium/cc/scheduler/delay_based_time_source.cc b/chromium/cc/scheduler/delay_based_time_source.cc
index d150c717a12..00515b72f76 100644
--- a/chromium/cc/scheduler/delay_based_time_source.cc
+++ b/chromium/cc/scheduler/delay_based_time_source.cc
@@ -33,6 +33,27 @@ static const double kPhaseChangeThreshold = 0.25;
} // namespace
+// The following methods correspond to the DelayBasedTimeSource that uses
+// the base::TimeTicks::HighResNow as the timebase.
+scoped_refptr<DelayBasedTimeSourceHighRes> DelayBasedTimeSourceHighRes::Create(
+ base::TimeDelta interval,
+ base::SingleThreadTaskRunner* task_runner) {
+ return make_scoped_refptr(
+ new DelayBasedTimeSourceHighRes(interval, task_runner));
+}
+
+DelayBasedTimeSourceHighRes::DelayBasedTimeSourceHighRes(
+ base::TimeDelta interval, base::SingleThreadTaskRunner* task_runner)
+ : DelayBasedTimeSource(interval, task_runner) {}
+
+DelayBasedTimeSourceHighRes::~DelayBasedTimeSourceHighRes() {}
+
+base::TimeTicks DelayBasedTimeSourceHighRes::Now() const {
+ return base::TimeTicks::HighResNow();
+}
+
+// The following methods correspond to the DelayBasedTimeSource that uses
+// the base::TimeTicks::Now as the timebase.
scoped_refptr<DelayBasedTimeSource> DelayBasedTimeSource::Create(
base::TimeDelta interval,
base::SingleThreadTaskRunner* task_runner) {
diff --git a/chromium/cc/scheduler/delay_based_time_source.h b/chromium/cc/scheduler/delay_based_time_source.h
index 55aac5a97fb..ddb89da3566 100644
--- a/chromium/cc/scheduler/delay_based_time_source.h
+++ b/chromium/cc/scheduler/delay_based_time_source.h
@@ -15,7 +15,7 @@ namespace cc {
// This timer implements a time source that achieves the specified interval
// in face of millisecond-precision delayed callbacks and random queueing
-// delays.
+// delays. DelayBasedTimeSource uses base::TimeTicks::Now as its timebase.
class CC_EXPORT DelayBasedTimeSource : public TimeSource {
public:
static scoped_refptr<DelayBasedTimeSource> Create(
@@ -73,6 +73,23 @@ class CC_EXPORT DelayBasedTimeSource : public TimeSource {
DISALLOW_COPY_AND_ASSIGN(DelayBasedTimeSource);
};
+// DelayBasedTimeSource uses base::TimeTicks::HighResNow as its timebase.
+class DelayBasedTimeSourceHighRes : public DelayBasedTimeSource {
+ public:
+ static scoped_refptr<DelayBasedTimeSourceHighRes> Create(
+ base::TimeDelta interval, base::SingleThreadTaskRunner* task_runner);
+
+ virtual base::TimeTicks Now() const OVERRIDE;
+
+ protected:
+ DelayBasedTimeSourceHighRes(base::TimeDelta interval,
+ base::SingleThreadTaskRunner* task_runner);
+ virtual ~DelayBasedTimeSourceHighRes();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DelayBasedTimeSourceHighRes);
+};
+
} // namespace cc
#endif // CC_SCHEDULER_DELAY_BASED_TIME_SOURCE_H_
diff --git a/chromium/cc/scheduler/frame_rate_controller.cc b/chromium/cc/scheduler/frame_rate_controller.cc
index cefe764fc78..243ef6b6291 100644
--- a/chromium/cc/scheduler/frame_rate_controller.cc
+++ b/chromium/cc/scheduler/frame_rate_controller.cc
@@ -11,6 +11,7 @@
#include "base/single_thread_task_runner.h"
#include "cc/scheduler/delay_based_time_source.h"
#include "cc/scheduler/time_source.h"
+#include "ui/gfx/frame_time.h"
namespace cc {
@@ -43,8 +44,9 @@ FrameRateController::FrameRateController(scoped_refptr<TimeSource> timer)
time_source_(timer),
active_(false),
is_time_source_throttling_(true),
- weak_factory_(this),
- task_runner_(NULL) {
+ manual_tick_pending_(false),
+ task_runner_(NULL),
+ weak_factory_(this) {
time_source_client_adapter_ =
FrameRateControllerTimeSourceAdapter::Create(this);
time_source_->SetClient(time_source_client_adapter_.get());
@@ -58,8 +60,9 @@ FrameRateController::FrameRateController(
interval_(BeginFrameArgs::DefaultInterval()),
active_(false),
is_time_source_throttling_(false),
- weak_factory_(this),
- task_runner_(task_runner) {}
+ manual_tick_pending_(false),
+ task_runner_(task_runner),
+ weak_factory_(this) {}
FrameRateController::~FrameRateController() {
if (is_time_source_throttling_)
@@ -80,10 +83,12 @@ BeginFrameArgs FrameRateController::SetActive(bool active) {
missed_tick_time, deadline + deadline_adjustment_, interval_);
}
} else {
- if (active)
+ if (active) {
PostManualTick();
- else
+ } else {
weak_factory_.InvalidateWeakPtrs();
+ manual_tick_pending_ = false;
+ }
}
return BeginFrameArgs();
@@ -128,7 +133,8 @@ void FrameRateController::OnTimerTick() {
}
void FrameRateController::PostManualTick() {
- if (active_) {
+ if (active_ && !manual_tick_pending_) {
+ manual_tick_pending_ = true;
task_runner_->PostTask(FROM_HERE,
base::Bind(&FrameRateController::ManualTick,
weak_factory_.GetWeakPtr()));
@@ -136,6 +142,7 @@ void FrameRateController::PostManualTick() {
}
void FrameRateController::ManualTick() {
+ manual_tick_pending_ = false;
OnTimerTick();
}
@@ -165,7 +172,7 @@ base::TimeTicks FrameRateController::LastTickTime() {
if (is_time_source_throttling_)
return time_source_->LastTickTime();
- return base::TimeTicks::Now();
+ return gfx::FrameTime::Now();
}
} // namespace cc
diff --git a/chromium/cc/scheduler/frame_rate_controller.h b/chromium/cc/scheduler/frame_rate_controller.h
index b68c73db0c8..6d86d974966 100644
--- a/chromium/cc/scheduler/frame_rate_controller.h
+++ b/chromium/cc/scheduler/frame_rate_controller.h
@@ -88,8 +88,9 @@ class CC_EXPORT FrameRateController {
// Members for unthrottled frame-rate.
bool is_time_source_throttling_;
- base::WeakPtrFactory<FrameRateController> weak_factory_;
+ bool manual_tick_pending_;
base::SingleThreadTaskRunner* task_runner_;
+ base::WeakPtrFactory<FrameRateController> weak_factory_;
private:
DISALLOW_COPY_AND_ASSIGN(FrameRateController);
diff --git a/chromium/cc/scheduler/frame_rate_controller_unittest.cc b/chromium/cc/scheduler/frame_rate_controller_unittest.cc
index 353d9844caf..e7d75802eb3 100644
--- a/chromium/cc/scheduler/frame_rate_controller_unittest.cc
+++ b/chromium/cc/scheduler/frame_rate_controller_unittest.cc
@@ -11,20 +11,21 @@
namespace cc {
namespace {
-class FakeFrameRateControllerClient : public cc::FrameRateControllerClient {
+class FakeFrameRateControllerClient : public FrameRateControllerClient {
public:
FakeFrameRateControllerClient() { Reset(); }
- void Reset() { began_frame_ = false; }
- bool BeganFrame() const { return began_frame_; }
+ void Reset() { frame_count_ = 0; }
+ bool BeganFrame() const { return frame_count_ > 0; }
+ int frame_count() const { return frame_count_; }
virtual void FrameRateControllerTick(
bool throttled, const BeginFrameArgs& args) OVERRIDE {
- began_frame_ = !throttled;
+ frame_count_ += throttled ? 0 : 1;
}
protected:
- bool began_frame_;
+ int frame_count_;
};
TEST(FrameRateControllerTest, TestFrameThrottling_ImmediateAck) {
@@ -182,5 +183,29 @@ TEST(FrameRateControllerTest, TestFrameThrottling_Unthrottled) {
EXPECT_TRUE(client.BeganFrame());
}
+TEST(FrameRateControllerTest, TestFrameThrottling_NoDoubleTicking) {
+ scoped_refptr<base::TestSimpleTaskRunner> task_runner =
+ new base::TestSimpleTaskRunner;
+ FakeFrameRateControllerClient client;
+ FrameRateController controller(task_runner.get());
+ controller.SetClient(&client);
+
+ // SetActive triggers 1st frame and queues another tick task since the time
+ // source isn't throttling.
+ controller.SetActive(true);
+ task_runner->RunPendingTasks();
+ EXPECT_TRUE(client.BeganFrame());
+ client.Reset();
+ EXPECT_TRUE(task_runner->HasPendingTask());
+
+ // Simulate a frame swap. This shouldn't queue a second tick task.
+ controller.DidSwapBuffers();
+ controller.DidSwapBuffersComplete();
+
+ // The client should only be ticked once.
+ task_runner->RunPendingTasks();
+ EXPECT_EQ(1, client.frame_count());
+}
+
} // namespace
} // namespace cc
diff --git a/chromium/cc/scheduler/rate_limiter.cc b/chromium/cc/scheduler/rate_limiter.cc
deleted file mode 100644
index d89d95b8cf2..00000000000
--- a/chromium/cc/scheduler/rate_limiter.cc
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2011 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/scheduler/rate_limiter.h"
-
-#include "base/bind.h"
-#include "base/debug/trace_event.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/single_thread_task_runner.h"
-#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
-
-namespace cc {
-
-scoped_refptr<RateLimiter> RateLimiter::Create(
- WebKit::WebGraphicsContext3D* context,
- RateLimiterClient* client,
- base::SingleThreadTaskRunner* task_runner) {
- return make_scoped_refptr(new RateLimiter(context, client, task_runner));
-}
-
-RateLimiter::RateLimiter(WebKit::WebGraphicsContext3D* context,
- RateLimiterClient* client,
- base::SingleThreadTaskRunner* task_runner)
- : context_(context),
- active_(false),
- client_(client),
- task_runner_(task_runner) {
- DCHECK(context);
-}
-
-RateLimiter::~RateLimiter() {}
-
-void RateLimiter::Start() {
- if (active_)
- return;
-
- TRACE_EVENT0("cc", "RateLimiter::Start");
- active_ = true;
- task_runner_->PostTask(FROM_HERE,
- base::Bind(&RateLimiter::RateLimitContext, this));
-}
-
-void RateLimiter::Stop() {
- TRACE_EVENT0("cc", "RateLimiter::Stop");
- client_ = NULL;
-}
-
-void RateLimiter::RateLimitContext() {
- if (!client_)
- return;
-
- TRACE_EVENT0("cc", "RateLimiter::RateLimitContext");
-
- active_ = false;
- client_->RateLimit();
- context_->rateLimitOffscreenContextCHROMIUM();
-}
-
-} // namespace cc
diff --git a/chromium/cc/scheduler/rate_limiter.h b/chromium/cc/scheduler/rate_limiter.h
deleted file mode 100644
index 04b90772e36..00000000000
--- a/chromium/cc/scheduler/rate_limiter.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2011 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_SCHEDULER_RATE_LIMITER_H_
-#define CC_SCHEDULER_RATE_LIMITER_H_
-
-#include "base/memory/ref_counted.h"
-
-namespace base { class SingleThreadTaskRunner; }
-
-namespace WebKit { class WebGraphicsContext3D; }
-
-namespace cc {
-
-class RateLimiterClient {
- public:
- virtual void RateLimit() = 0;
-
- protected:
- virtual ~RateLimiterClient() {}
-};
-
-// A RateLimiter can be used to make sure that a single context does not
-// dominate all execution time. To use, construct a RateLimiter class around
-// the context and call Start() whenever calls are made on the context outside
-// of normal flow control. RateLimiter will block if the context is too far
-// ahead of the compositor.
-class RateLimiter : public base::RefCounted<RateLimiter> {
- public:
- static scoped_refptr<RateLimiter> Create(
- WebKit::WebGraphicsContext3D* context,
- RateLimiterClient* client,
- base::SingleThreadTaskRunner* task_runner);
-
- void Start();
-
- // Context and client will not be accessed after Stop().
- void Stop();
-
- private:
- friend class base::RefCounted<RateLimiter>;
-
- RateLimiter(WebKit::WebGraphicsContext3D* context,
- RateLimiterClient* client,
- base::SingleThreadTaskRunner* task_runner);
- ~RateLimiter();
-
- void RateLimitContext();
-
- WebKit::WebGraphicsContext3D* context_;
- bool active_;
- RateLimiterClient* client_;
- base::SingleThreadTaskRunner* task_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(RateLimiter);
-};
-
-} // namespace cc
-
-#endif // CC_SCHEDULER_RATE_LIMITER_H_
diff --git a/chromium/cc/scheduler/scheduler.cc b/chromium/cc/scheduler/scheduler.cc
index c81513feebd..d31f042e761 100644
--- a/chromium/cc/scheduler/scheduler.cc
+++ b/chromium/cc/scheduler/scheduler.cc
@@ -8,21 +8,25 @@
#include "base/auto_reset.h"
#include "base/debug/trace_event.h"
#include "base/logging.h"
+#include "cc/debug/devtools_instrumentation.h"
#include "cc/debug/traced_value.h"
+#include "ui/gfx/frame_time.h"
namespace cc {
Scheduler::Scheduler(SchedulerClient* client,
- const SchedulerSettings& scheduler_settings)
+ const SchedulerSettings& scheduler_settings,
+ int layer_tree_host_id)
: settings_(scheduler_settings),
client_(client),
- weak_factory_(this),
- last_set_needs_begin_frame_(false),
+ layer_tree_host_id_(layer_tree_host_id),
+ last_set_needs_begin_impl_frame_(false),
state_machine_(scheduler_settings),
inside_process_scheduled_actions_(false),
- inside_action_(SchedulerStateMachine::ACTION_NONE) {
+ inside_action_(SchedulerStateMachine::ACTION_NONE),
+ weak_factory_(this) {
DCHECK(client_);
- DCHECK(!state_machine_.BeginFrameNeededByImplThread());
+ DCHECK(!state_machine_.BeginImplFrameNeeded());
}
Scheduler::~Scheduler() {}
@@ -94,24 +98,28 @@ void Scheduler::FinishCommit() {
ProcessScheduledActions();
}
-void Scheduler::BeginFrameAbortedByMainThread(bool did_handle) {
- TRACE_EVENT0("cc", "Scheduler::BeginFrameAbortedByMainThread");
- state_machine_.BeginFrameAbortedByMainThread(did_handle);
+void Scheduler::BeginMainFrameAborted(bool did_handle) {
+ TRACE_EVENT0("cc", "Scheduler::BeginMainFrameAborted");
+ state_machine_.BeginMainFrameAborted(did_handle);
ProcessScheduledActions();
}
+void Scheduler::DidManageTiles() {
+ state_machine_.DidManageTiles();
+}
+
void Scheduler::DidLoseOutputSurface() {
TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface");
- last_set_needs_begin_frame_ = false;
- begin_frame_deadline_closure_.Cancel();
+ last_set_needs_begin_impl_frame_ = false;
+ begin_impl_frame_deadline_closure_.Cancel();
state_machine_.DidLoseOutputSurface();
ProcessScheduledActions();
}
void Scheduler::DidCreateAndInitializeOutputSurface() {
TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface");
- DCHECK(!last_set_needs_begin_frame_);
- DCHECK(begin_frame_deadline_closure_.IsCancelled());
+ DCHECK(!last_set_needs_begin_impl_frame_);
+ DCHECK(begin_impl_frame_deadline_closure_.IsCancelled());
state_machine_.DidCreateAndInitializeOutputSurface();
ProcessScheduledActions();
}
@@ -119,46 +127,49 @@ void Scheduler::DidCreateAndInitializeOutputSurface() {
base::TimeTicks Scheduler::AnticipatedDrawTime() {
TRACE_EVENT0("cc", "Scheduler::AnticipatedDrawTime");
- if (!last_set_needs_begin_frame_ ||
- last_begin_frame_args_.interval <= base::TimeDelta())
+ if (!last_set_needs_begin_impl_frame_ ||
+ last_begin_impl_frame_args_.interval <= base::TimeDelta())
return base::TimeTicks();
- base::TimeTicks now = base::TimeTicks::Now();
- base::TimeTicks timebase = std::max(last_begin_frame_args_.frame_time,
- last_begin_frame_args_.deadline);
- int64 intervals = 1 + ((now - timebase) / last_begin_frame_args_.interval);
- return timebase + (last_begin_frame_args_.interval * intervals);
+ base::TimeTicks now = gfx::FrameTime::Now();
+ base::TimeTicks timebase = std::max(last_begin_impl_frame_args_.frame_time,
+ last_begin_impl_frame_args_.deadline);
+ int64 intervals =
+ 1 + ((now - timebase) / last_begin_impl_frame_args_.interval);
+ return timebase + (last_begin_impl_frame_args_.interval * intervals);
}
-base::TimeTicks Scheduler::LastBeginFrameOnImplThreadTime() {
- return last_begin_frame_args_.frame_time;
+base::TimeTicks Scheduler::LastBeginImplFrameTime() {
+ return last_begin_impl_frame_args_.frame_time;
}
-void Scheduler::SetupNextBeginFrameIfNeeded() {
- bool needs_begin_frame =
- state_machine_.BeginFrameNeededByImplThread();
+void Scheduler::SetupNextBeginImplFrameIfNeeded() {
+ bool needs_begin_impl_frame =
+ state_machine_.BeginImplFrameNeeded();
bool at_end_of_deadline =
- state_machine_.begin_frame_state() ==
- SchedulerStateMachine::BEGIN_FRAME_STATE_INSIDE_DEADLINE;
-
- bool should_call_set_needs_begin_frame =
- // Always request the BeginFrame immediately if it wasn't needed before.
- (needs_begin_frame && !last_set_needs_begin_frame_) ||
- // We always need to explicitly request our next BeginFrame.
+ state_machine_.begin_impl_frame_state() ==
+ SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE;
+
+ bool should_call_set_needs_begin_impl_frame =
+ // Always request the BeginImplFrame immediately if it wasn't needed
+ // before.
+ (needs_begin_impl_frame && !last_set_needs_begin_impl_frame_) ||
+ // We always need to explicitly request our next BeginImplFrame.
at_end_of_deadline;
- if (should_call_set_needs_begin_frame) {
- client_->SetNeedsBeginFrameOnImplThread(needs_begin_frame);
- last_set_needs_begin_frame_ = needs_begin_frame;
+ if (should_call_set_needs_begin_impl_frame) {
+ client_->SetNeedsBeginImplFrame(needs_begin_impl_frame);
+ last_set_needs_begin_impl_frame_ = needs_begin_impl_frame;
}
+ bool needs_advance_commit_state_timer = false;
// Setup PollForAnticipatedDrawTriggers if we need to monitor state but
- // aren't expecting any more BeginFrames. This should only be needed by the
- // synchronous compositor when BeginFrameNeededByImplThread is false.
+ // aren't expecting any more BeginImplFrames. This should only be needed by
+ // the synchronous compositor when BeginImplFrameNeeded is false.
if (state_machine_.ShouldPollForAnticipatedDrawTriggers()) {
- DCHECK(settings_.using_synchronous_renderer_compositor);
- DCHECK(!needs_begin_frame);
+ DCHECK(!state_machine_.SupportsProactiveBeginImplFrame());
+ DCHECK(!needs_begin_impl_frame);
if (poll_for_draw_triggers_closure_.IsCancelled()) {
poll_for_draw_triggers_closure_.Reset(
base::Bind(&Scheduler::PollForAnticipatedDrawTriggers,
@@ -166,92 +177,124 @@ void Scheduler::SetupNextBeginFrameIfNeeded() {
base::MessageLoop::current()->PostDelayedTask(
FROM_HERE,
poll_for_draw_triggers_closure_.callback(),
- last_begin_frame_args_.interval);
+ last_begin_impl_frame_args_.interval);
}
} else {
poll_for_draw_triggers_closure_.Cancel();
+
+ // At this point we'd prefer to advance through the commit flow by
+ // drawing a frame, however it's possible that the frame rate controller
+ // will not give us a BeginImplFrame until the commit completes. See
+ // crbug.com/317430 for an example of a swap ack being held on commit. Thus
+ // we set a repeating timer to poll on ProcessScheduledActions until we
+ // successfully reach BeginImplFrame.
+ if (state_machine_.IsCommitStateWaiting())
+ needs_advance_commit_state_timer = true;
+ }
+ if (needs_advance_commit_state_timer !=
+ advance_commit_state_timer_.IsRunning()) {
+ if (needs_advance_commit_state_timer &&
+ last_begin_impl_frame_args_.IsValid()) {
+ // Since we'd rather get a BeginImplFrame by the normally mechanism, we set
+ // the interval to twice the interval from the previous frame.
+ advance_commit_state_timer_.Start(
+ FROM_HERE,
+ last_begin_impl_frame_args_.interval * 2,
+ base::Bind(&Scheduler::ProcessScheduledActions,
+ base::Unretained(this)));
+ } else {
+ advance_commit_state_timer_.Stop();
+ }
}
}
-void Scheduler::BeginFrame(const BeginFrameArgs& args) {
- TRACE_EVENT0("cc", "Scheduler::BeginFrame");
- DCHECK(state_machine_.begin_frame_state() ==
- SchedulerStateMachine::BEGIN_FRAME_STATE_IDLE);
+void Scheduler::BeginImplFrame(const BeginFrameArgs& args) {
+ TRACE_EVENT0("cc", "Scheduler::BeginImplFrame");
+ DCHECK(state_machine_.begin_impl_frame_state() ==
+ SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE);
DCHECK(state_machine_.HasInitializedOutputSurface());
- last_begin_frame_args_ = args;
- last_begin_frame_args_.deadline -= client_->DrawDurationEstimate();
- state_machine_.OnBeginFrame(last_begin_frame_args_);
+ last_begin_impl_frame_args_ = args;
+ last_begin_impl_frame_args_.deadline -= client_->DrawDurationEstimate();
+ state_machine_.OnBeginImplFrame(last_begin_impl_frame_args_);
+
+ if (settings_.switch_to_low_latency_if_possible) {
+ state_machine_.SetSkipBeginMainFrameToReduceLatency(
+ state_machine_.MainThreadIsInHighLatencyMode() &&
+ CanCommitAndActivateBeforeDeadline());
+ }
+
ProcessScheduledActions();
if (!state_machine_.HasInitializedOutputSurface())
return;
- state_machine_.OnBeginFrameDeadlinePending();
-
+ state_machine_.OnBeginImplFrameDeadlinePending();
+ devtools_instrumentation::didBeginFrame(layer_tree_host_id_);
if (settings_.using_synchronous_renderer_compositor) {
// The synchronous renderer compositor has to make its GL calls
- // within this call to BeginFrame.
+ // within this call to BeginImplFrame.
// TODO(brianderson): Have the OutputSurface initiate the deadline tasks
- // so the sychronous renderer compoistor can take advantage of splitting
- // up the BeginFrame and deadline as well.
- OnBeginFrameDeadline();
+ // so the sychronous renderer compositor can take advantage of splitting
+ // up the BeginImplFrame and deadline as well.
+ OnBeginImplFrameDeadline();
} else if (!settings_.deadline_scheduling_enabled) {
// We emulate the old non-deadline scheduler here by posting the
// deadline task without any delay.
- PostBeginFrameDeadline(base::TimeTicks());
- } else if (state_machine_.ShouldTriggerBeginFrameDeadlineEarly()) {
+ PostBeginImplFrameDeadline(base::TimeTicks());
+ } else if (state_machine_.ShouldTriggerBeginImplFrameDeadlineEarly()) {
// We are ready to draw a new active tree immediately.
- PostBeginFrameDeadline(base::TimeTicks());
+ PostBeginImplFrameDeadline(base::TimeTicks());
} else if (state_machine_.needs_redraw()) {
// 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.
- PostBeginFrameDeadline(last_begin_frame_args_.deadline);
+ PostBeginImplFrameDeadline(last_begin_impl_frame_args_.deadline);
} else {
// The impl thread doesn't have anything it wants to draw and we are just
// waiting for a new active tree, so post the deadline for the next
- // expected BeginFrame start. This allows us to draw immediately when
- // there is a new active tree, instead of waiting for the next BeginFrame.
+ // expected BeginImplFrame start. This allows us to draw immediately when
+ // there is a new active tree, instead of waiting for the next
+ // BeginImplFrame.
// TODO(brianderson): Handle long deadlines (that are past the next frame's
// frame time) properly instead of using this hack.
- PostBeginFrameDeadline(last_begin_frame_args_.frame_time +
- last_begin_frame_args_.interval);
+ PostBeginImplFrameDeadline(last_begin_impl_frame_args_.frame_time +
+ last_begin_impl_frame_args_.interval);
}
}
-void Scheduler::PostBeginFrameDeadline(base::TimeTicks deadline) {
- begin_frame_deadline_closure_.Cancel();
- begin_frame_deadline_closure_.Reset(
- base::Bind(&Scheduler::OnBeginFrameDeadline, weak_factory_.GetWeakPtr()));
- client_->PostBeginFrameDeadline(begin_frame_deadline_closure_.callback(),
- deadline);
+void Scheduler::PostBeginImplFrameDeadline(base::TimeTicks deadline) {
+ begin_impl_frame_deadline_closure_.Cancel();
+ begin_impl_frame_deadline_closure_.Reset(
+ base::Bind(&Scheduler::OnBeginImplFrameDeadline,
+ weak_factory_.GetWeakPtr()));
+ client_->PostBeginImplFrameDeadline(
+ begin_impl_frame_deadline_closure_.callback(), deadline);
}
-void Scheduler::OnBeginFrameDeadline() {
- TRACE_EVENT0("cc", "Scheduler::OnBeginFrameDeadline");
+void Scheduler::OnBeginImplFrameDeadline() {
+ TRACE_EVENT0("cc", "Scheduler::OnBeginImplFrameDeadline");
DCHECK(state_machine_.HasInitializedOutputSurface());
- begin_frame_deadline_closure_.Cancel();
- state_machine_.OnBeginFrameDeadline();
+ begin_impl_frame_deadline_closure_.Cancel();
+ state_machine_.OnBeginImplFrameDeadline();
ProcessScheduledActions();
if (state_machine_.HasInitializedOutputSurface()) {
- // We only transition out of BEGIN_FRAME_STATE_INSIDE_DEADLINE when all
+ // We only transition out of BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE when all
// actions that occur back-to-back in response to entering
- // BEGIN_FRAME_STATE_INSIDE_DEADLINE have completed. This is important
- // because sending the BeginFrame to the main thread will not occur if
- // we transition to BEGIN_FRAME_STATE_IDLE too early.
- state_machine_.OnBeginFrameIdle();
+ // BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE have completed. This is important
+ // because sending the BeginMainFrame will not occur if we transition to
+ // BEGIN_IMPL_FRAME_STATE_IDLE too early.
+ state_machine_.OnBeginImplFrameIdle();
}
- client_->DidBeginFrameDeadlineOnImplThread();
+ client_->DidBeginImplFrameDeadline();
}
void Scheduler::PollForAnticipatedDrawTriggers() {
TRACE_EVENT0("cc", "Scheduler::PollForAnticipatedDrawTriggers");
+ poll_for_draw_triggers_closure_.Cancel();
state_machine_.DidEnterPollForAnticipatedDrawTriggers();
ProcessScheduledActions();
state_machine_.DidLeavePollForAnticipatedDrawTriggers();
-
- poll_for_draw_triggers_closure_.Cancel();
}
void Scheduler::DrawAndSwapIfPossible() {
@@ -291,8 +334,8 @@ void Scheduler::ProcessScheduledActions() {
switch (action) {
case SchedulerStateMachine::ACTION_NONE:
break;
- case SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD:
- client_->ScheduledActionSendBeginFrameToMainThread();
+ case SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME:
+ client_->ScheduledActionSendBeginMainFrame();
break;
case SchedulerStateMachine::ACTION_COMMIT:
client_->ScheduledActionCommit();
@@ -328,15 +371,26 @@ void Scheduler::ProcessScheduledActions() {
}
} while (action != SchedulerStateMachine::ACTION_NONE);
- SetupNextBeginFrameIfNeeded();
+ SetupNextBeginImplFrameIfNeeded();
client_->DidAnticipatedDrawTimeChange(AnticipatedDrawTime());
- if (state_machine_.ShouldTriggerBeginFrameDeadlineEarly())
- PostBeginFrameDeadline(base::TimeTicks());
+ if (state_machine_.ShouldTriggerBeginImplFrameDeadlineEarly())
+ PostBeginImplFrameDeadline(base::TimeTicks());
}
bool Scheduler::WillDrawIfNeeded() const {
return !state_machine_.PendingDrawsShouldBeAborted();
}
+bool Scheduler::CanCommitAndActivateBeforeDeadline() const {
+ // Check if the main thread computation and commit can be finished before the
+ // impl thread's deadline.
+ base::TimeTicks estimated_draw_time =
+ last_begin_impl_frame_args_.frame_time +
+ client_->BeginMainFrameToCommitDurationEstimate() +
+ client_->CommitToActivateDurationEstimate();
+
+ return estimated_draw_time < last_begin_impl_frame_args_.deadline;
+}
+
} // namespace cc
diff --git a/chromium/cc/scheduler/scheduler.h b/chromium/cc/scheduler/scheduler.h
index 3403b7a2e06..92097829390 100644
--- a/chromium/cc/scheduler/scheduler.h
+++ b/chromium/cc/scheduler/scheduler.h
@@ -33,8 +33,8 @@ struct DrawSwapReadbackResult {
class SchedulerClient {
public:
- virtual void SetNeedsBeginFrameOnImplThread(bool enable) = 0;
- virtual void ScheduledActionSendBeginFrameToMainThread() = 0;
+ virtual void SetNeedsBeginImplFrame(bool enable) = 0;
+ virtual void ScheduledActionSendBeginMainFrame() = 0;
virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapIfPossible() = 0;
virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapForced() = 0;
virtual DrawSwapReadbackResult ScheduledActionDrawAndReadback() = 0;
@@ -46,11 +46,11 @@ class SchedulerClient {
virtual void ScheduledActionManageTiles() = 0;
virtual void DidAnticipatedDrawTimeChange(base::TimeTicks time) = 0;
virtual base::TimeDelta DrawDurationEstimate() = 0;
- virtual base::TimeDelta BeginFrameToCommitDurationEstimate() = 0;
+ virtual base::TimeDelta BeginMainFrameToCommitDurationEstimate() = 0;
virtual base::TimeDelta CommitToActivateDurationEstimate() = 0;
- virtual void PostBeginFrameDeadline(const base::Closure& closure,
- base::TimeTicks deadline) = 0;
- virtual void DidBeginFrameDeadlineOnImplThread() = 0;
+ virtual void PostBeginImplFrameDeadline(const base::Closure& closure,
+ base::TimeTicks deadline) = 0;
+ virtual void DidBeginImplFrameDeadline() = 0;
protected:
virtual ~SchedulerClient() {}
@@ -60,8 +60,10 @@ class CC_EXPORT Scheduler {
public:
static scoped_ptr<Scheduler> Create(
SchedulerClient* client,
- const SchedulerSettings& scheduler_settings) {
- return make_scoped_ptr(new Scheduler(client, scheduler_settings));
+ const SchedulerSettings& scheduler_settings,
+ int layer_tree_host_id) {
+ return make_scoped_ptr(
+ new Scheduler(client, scheduler_settings, layer_tree_host_id));
}
virtual ~Scheduler();
@@ -89,8 +91,9 @@ class CC_EXPORT Scheduler {
void SetSmoothnessTakesPriority(bool smoothness_takes_priority);
void FinishCommit();
- void BeginFrameAbortedByMainThread(bool did_handle);
+ void BeginMainFrameAborted(bool did_handle);
+ void DidManageTiles();
void DidLoseOutputSurface();
void DidCreateAndInitializeOutputSurface();
bool HasInitializedOutputSurface() const {
@@ -102,15 +105,18 @@ class CC_EXPORT Scheduler {
bool ManageTilesPending() const {
return state_machine_.ManageTilesPending();
}
+ bool MainThreadIsInHighLatencyMode() const {
+ return state_machine_.MainThreadIsInHighLatencyMode();
+ }
bool WillDrawIfNeeded() const;
base::TimeTicks AnticipatedDrawTime();
- base::TimeTicks LastBeginFrameOnImplThreadTime();
+ base::TimeTicks LastBeginImplFrameTime();
- void BeginFrame(const BeginFrameArgs& args);
- void OnBeginFrameDeadline();
+ void BeginImplFrame(const BeginFrameArgs& args);
+ void OnBeginImplFrameDeadline();
void PollForAnticipatedDrawTriggers();
scoped_ptr<base::Value> StateAsValue() {
@@ -123,29 +129,36 @@ class CC_EXPORT Scheduler {
private:
Scheduler(SchedulerClient* client,
- const SchedulerSettings& scheduler_settings);
+ const SchedulerSettings& scheduler_settings,
+ int layer_tree_host_id);
- void PostBeginFrameDeadline(base::TimeTicks deadline);
- void SetupNextBeginFrameIfNeeded();
+ void PostBeginImplFrameDeadline(base::TimeTicks deadline);
+ void SetupNextBeginImplFrameIfNeeded();
void ActivatePendingTree();
void DrawAndSwapIfPossible();
void DrawAndSwapForced();
void DrawAndReadback();
void ProcessScheduledActions();
+ bool CanCommitAndActivateBeforeDeadline() const;
+ void AdvanceCommitStateIfPossible();
+
const SchedulerSettings settings_;
SchedulerClient* client_;
+ int layer_tree_host_id_;
- base::WeakPtrFactory<Scheduler> weak_factory_;
- bool last_set_needs_begin_frame_;
- BeginFrameArgs last_begin_frame_args_;
- base::CancelableClosure begin_frame_deadline_closure_;
+ bool last_set_needs_begin_impl_frame_;
+ BeginFrameArgs last_begin_impl_frame_args_;
+ base::CancelableClosure begin_impl_frame_deadline_closure_;
base::CancelableClosure poll_for_draw_triggers_closure_;
+ base::RepeatingTimer<Scheduler> advance_commit_state_timer_;
SchedulerStateMachine state_machine_;
bool inside_process_scheduled_actions_;
SchedulerStateMachine::Action inside_action_;
+ base::WeakPtrFactory<Scheduler> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(Scheduler);
};
diff --git a/chromium/cc/scheduler/scheduler_settings.cc b/chromium/cc/scheduler/scheduler_settings.cc
index 6c1db6bf10c..ad925d4d135 100644
--- a/chromium/cc/scheduler/scheduler_settings.cc
+++ b/chromium/cc/scheduler/scheduler_settings.cc
@@ -7,12 +7,13 @@
namespace cc {
SchedulerSettings::SchedulerSettings()
- : deadline_scheduling_enabled(false),
+ : deadline_scheduling_enabled(true),
impl_side_painting(false),
timeout_and_draw_when_animation_checkerboards(true),
maximum_number_of_failed_draws_before_draw_is_forced_(3),
using_synchronous_renderer_compositor(false),
- throttle_frame_production(true) {}
+ throttle_frame_production(true),
+ switch_to_low_latency_if_possible(false) {}
SchedulerSettings::~SchedulerSettings() {}
diff --git a/chromium/cc/scheduler/scheduler_settings.h b/chromium/cc/scheduler/scheduler_settings.h
index 7857a70fe9e..b35cb7e6af6 100644
--- a/chromium/cc/scheduler/scheduler_settings.h
+++ b/chromium/cc/scheduler/scheduler_settings.h
@@ -20,6 +20,7 @@ class CC_EXPORT SchedulerSettings {
int maximum_number_of_failed_draws_before_draw_is_forced_;
bool using_synchronous_renderer_compositor;
bool throttle_frame_production;
+ bool switch_to_low_latency_if_possible;
};
} // namespace cc
diff --git a/chromium/cc/scheduler/scheduler_state_machine.cc b/chromium/cc/scheduler/scheduler_state_machine.cc
index 955a6b32eee..7d8fcd721a3 100644
--- a/chromium/cc/scheduler/scheduler_state_machine.cc
+++ b/chromium/cc/scheduler/scheduler_state_machine.cc
@@ -4,17 +4,19 @@
#include "cc/scheduler/scheduler_state_machine.h"
+#include "base/debug/trace_event.h"
#include "base/format_macros.h"
#include "base/logging.h"
#include "base/strings/stringprintf.h"
#include "base/values.h"
+#include "ui/gfx/frame_time.h"
namespace cc {
SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings)
: settings_(settings),
output_surface_state_(OUTPUT_SURFACE_LOST),
- begin_frame_state_(BEGIN_FRAME_STATE_IDLE),
+ begin_impl_frame_state_(BEGIN_IMPL_FRAME_STATE_IDLE),
commit_state_(COMMIT_STATE_IDLE),
texture_state_(LAYER_TEXTURE_STATE_UNLOCKED),
forced_redraw_state_(FORCED_REDRAW_STATE_IDLE),
@@ -22,8 +24,9 @@ SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings)
commit_count_(0),
current_frame_number_(0),
last_frame_number_swap_performed_(-1),
- last_frame_number_begin_frame_sent_to_main_thread_(-1),
+ last_frame_number_begin_main_frame_sent_(-1),
last_frame_number_update_visible_tiles_was_called_(-1),
+ last_frame_number_manage_tiles_called_(-1),
consecutive_failed_draws_(0),
needs_redraw_(false),
needs_manage_tiles_(false),
@@ -39,7 +42,8 @@ SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings)
active_tree_needs_first_draw_(false),
draw_if_possible_failed_(false),
did_create_and_initialize_first_output_surface_(false),
- smoothness_takes_priority_(false) {}
+ smoothness_takes_priority_(false),
+ skip_begin_main_frame_to_reduce_latency_(false) {}
const char* SchedulerStateMachine::OutputSurfaceStateToString(
OutputSurfaceState state) {
@@ -59,17 +63,17 @@ const char* SchedulerStateMachine::OutputSurfaceStateToString(
return "???";
}
-const char* SchedulerStateMachine::BeginFrameStateToString(
- BeginFrameState state) {
+const char* SchedulerStateMachine::BeginImplFrameStateToString(
+ BeginImplFrameState state) {
switch (state) {
- case BEGIN_FRAME_STATE_IDLE:
- return "BEGIN_FRAME_STATE_IDLE";
- case BEGIN_FRAME_STATE_BEGIN_FRAME_STARTING:
- return "BEGIN_FRAME_STATE_BEGIN_FRAME_STARTING";
- case BEGIN_FRAME_STATE_INSIDE_BEGIN_FRAME:
- return "BEGIN_FRAME_STATE_INSIDE_BEGIN_FRAME";
- case BEGIN_FRAME_STATE_INSIDE_DEADLINE:
- return "BEGIN_FRAME_STATE_INSIDE_DEADLINE";
+ case BEGIN_IMPL_FRAME_STATE_IDLE:
+ return "BEGIN_IMPL_FRAME_STATE_IDLE";
+ case BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING:
+ return "BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING";
+ case BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME:
+ return "BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME";
+ case BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE:
+ return "BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE";
}
NOTREACHED();
return "???";
@@ -108,8 +112,8 @@ const char* SchedulerStateMachine::SynchronousReadbackStateToString(
switch (state) {
case READBACK_STATE_IDLE:
return "READBACK_STATE_IDLE";
- case READBACK_STATE_NEEDS_BEGIN_FRAME:
- return "READBACK_STATE_NEEDS_BEGIN_FRAME";
+ case READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME:
+ return "READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME";
case READBACK_STATE_WAITING_FOR_COMMIT:
return "READBACK_STATE_WAITING_FOR_COMMIT";
case READBACK_STATE_WAITING_FOR_ACTIVATION:
@@ -145,8 +149,8 @@ const char* SchedulerStateMachine::ActionToString(Action action) {
switch (action) {
case ACTION_NONE:
return "ACTION_NONE";
- case ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD:
- return "ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD";
+ case ACTION_SEND_BEGIN_MAIN_FRAME:
+ return "ACTION_SEND_BEGIN_MAIN_FRAME";
case ACTION_COMMIT:
return "ACTION_COMMIT";
case ACTION_UPDATE_VISIBLE_TILES:
@@ -177,8 +181,8 @@ scoped_ptr<base::Value> SchedulerStateMachine::AsValue() const {
scoped_ptr<base::DictionaryValue> major_state(new base::DictionaryValue);
major_state->SetString("next_action", ActionToString(NextAction()));
- major_state->SetString("begin_frame_state",
- BeginFrameStateToString(begin_frame_state_));
+ major_state->SetString("begin_impl_frame_state",
+ BeginImplFrameStateToString(begin_impl_frame_state_));
major_state->SetString("commit_state", CommitStateToString(commit_state_));
major_state->SetString("texture_state_",
TextureStateToString(texture_state_));
@@ -192,29 +196,33 @@ scoped_ptr<base::Value> SchedulerStateMachine::AsValue() const {
state->Set("major_state", major_state.release());
scoped_ptr<base::DictionaryValue> timestamps_state(new base::DictionaryValue);
- base::TimeTicks now = base::TimeTicks::Now();
+ base::TimeTicks now = gfx::FrameTime::Now();
timestamps_state->SetDouble(
- "0_interval", last_begin_frame_args_.interval.InMicroseconds() / 1000.0L);
+ "0_interval",
+ last_begin_impl_frame_args_.interval.InMicroseconds() / 1000.0L);
timestamps_state->SetDouble(
"1_now_to_deadline",
- (last_begin_frame_args_.deadline - now).InMicroseconds() / 1000.0L);
+ (last_begin_impl_frame_args_.deadline - now).InMicroseconds() / 1000.0L);
timestamps_state->SetDouble(
"2_frame_time_to_now",
- (now - last_begin_frame_args_.frame_time).InMicroseconds() / 1000.0L);
+ (now - last_begin_impl_frame_args_.frame_time).InMicroseconds() /
+ 1000.0L);
timestamps_state->SetDouble(
"3_frame_time_to_deadline",
- (last_begin_frame_args_.deadline - last_begin_frame_args_.frame_time)
- .InMicroseconds() /
+ (last_begin_impl_frame_args_.deadline -
+ last_begin_impl_frame_args_.frame_time).InMicroseconds() /
1000.0L);
timestamps_state->SetDouble(
"4_now", (now - base::TimeTicks()).InMicroseconds() / 1000.0L);
timestamps_state->SetDouble(
"5_frame_time",
- (last_begin_frame_args_.frame_time - base::TimeTicks()).InMicroseconds() /
+ (last_begin_impl_frame_args_.frame_time - base::TimeTicks())
+ .InMicroseconds() /
1000.0L);
timestamps_state->SetDouble(
"6_deadline",
- (last_begin_frame_args_.deadline - base::TimeTicks()).InMicroseconds() /
+ (last_begin_impl_frame_args_.deadline - base::TimeTicks())
+ .InMicroseconds() /
1000.0L);
state->Set("major_timestamps_in_ms", timestamps_state.release());
@@ -225,8 +233,8 @@ scoped_ptr<base::Value> SchedulerStateMachine::AsValue() const {
minor_state->SetInteger("last_frame_number_swap_performed",
last_frame_number_swap_performed_);
minor_state->SetInteger(
- "last_frame_number_begin_frame_sent_to_main_thread",
- last_frame_number_begin_frame_sent_to_main_thread_);
+ "last_frame_number_begin_main_frame_sent",
+ last_frame_number_begin_main_frame_sent_);
minor_state->SetInteger(
"last_frame_number_update_visible_tiles_was_called",
last_frame_number_update_visible_tiles_was_called_);
@@ -253,14 +261,18 @@ scoped_ptr<base::Value> SchedulerStateMachine::AsValue() const {
did_create_and_initialize_first_output_surface_);
minor_state->SetBoolean("smoothness_takes_priority",
smoothness_takes_priority_);
+ minor_state->SetBoolean("main_thread_is_in_high_latency_mode",
+ MainThreadIsInHighLatencyMode());
+ minor_state->SetBoolean("skip_begin_main_frame_to_reduce_latency",
+ skip_begin_main_frame_to_reduce_latency_);
state->Set("minor_state", minor_state.release());
return state.PassAs<base::Value>();
}
-bool SchedulerStateMachine::HasSentBeginFrameToMainThreadThisFrame() const {
+bool SchedulerStateMachine::HasSentBeginMainFrameThisFrame() const {
return current_frame_number_ ==
- last_frame_number_begin_frame_sent_to_main_thread_;
+ last_frame_number_begin_main_frame_sent_;
}
bool SchedulerStateMachine::HasUpdatedVisibleTilesThisFrame() const {
@@ -356,8 +368,9 @@ bool SchedulerStateMachine::ShouldDraw() const {
if (HasSwappedThisFrame())
return false;
- // Except for the cases above, do not draw outside of the BeginFrame deadline.
- if (begin_frame_state_ != BEGIN_FRAME_STATE_INSIDE_DEADLINE)
+ // Except for the cases above, do not draw outside of the BeginImplFrame
+ // deadline.
+ if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE)
return false;
// Only handle forced redraws due to timeouts on the regular deadline.
@@ -409,7 +422,7 @@ bool SchedulerStateMachine::ShouldUpdateVisibleTiles() const {
// We should not check for visible tiles until we've entered the deadline so
// we check as late as possible and give the tiles more time to initialize.
- if (begin_frame_state_ != BEGIN_FRAME_STATE_INSIDE_DEADLINE)
+ if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE)
return false;
// If the last swap drew with checkerboard or missing tiles, we should
@@ -421,12 +434,11 @@ bool SchedulerStateMachine::ShouldUpdateVisibleTiles() const {
return false;
}
-bool SchedulerStateMachine::ShouldSendBeginFrameToMainThread() const {
+bool SchedulerStateMachine::ShouldSendBeginMainFrame() const {
if (!needs_commit_)
return false;
- // Only send BeginFrame to the main thread when there isn't another commit
- // pending already.
+ // Only send BeginMainFrame when there isn't another commit pending already.
if (commit_state_ != COMMIT_STATE_IDLE)
return false;
@@ -435,10 +447,10 @@ bool SchedulerStateMachine::ShouldSendBeginFrameToMainThread() const {
return false;
// We want to handle readback commits immediately to unblock the main thread.
- // Note: This BeginFrame will correspond to the replacement commit that comes
- // after the readback commit itself, so we only send the BeginFrame if a
- // commit isn't already pending behind the readback.
- if (readback_state_ == READBACK_STATE_NEEDS_BEGIN_FRAME)
+ // Note: This BeginMainFrame will correspond to the replacement commit that
+ // comes after the readback commit itself, so we only send the BeginMainFrame
+ // if a commit isn't already pending behind the readback.
+ if (readback_state_ == READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME)
return !CommitPending();
// We do not need commits if we are not visible, unless there's a
@@ -450,21 +462,20 @@ bool SchedulerStateMachine::ShouldSendBeginFrameToMainThread() const {
if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT)
return true;
- // With deadline scheduling enabled, we should not send BeginFrame to the
- // main thread while we are in BEGIN_FRAME_STATE_IDLE, since we might have
- // new user input coming in soon.
- // However, if we are not expecting a BeginFrame on the Impl thread to take
- // us out of idle, we should not early out here to avoid blocking commits
- // forever.
+ // With deadline scheduling enabled, we should not send BeginMainFrame while
+ // we are in BEGIN_IMPL_FRAME_STATE_IDLE, since we might have new user input
+ // coming in soon.
+ // However, if we are not expecting a BeginImplFrame to take us out of idle,
+ // we should not early out here to avoid blocking commits forever.
// This only works well when deadline scheduling is enabled because there is
// an interval over which to accept the commit and draw. Without deadline
// scheduling, delaying the commit could prevent us from having something
- // to draw on the next BeginFrame.
- // TODO(brianderson): Allow sending BeginFrame to main thread while idle
- // when the main thread isn't consuming user input.
+ // to draw on the next BeginImplFrame.
+ // TODO(brianderson): Allow sending BeginMainFrame while idle when the main
+ // thread isn't consuming user input.
if (settings_.deadline_scheduling_enabled &&
- begin_frame_state_ == BEGIN_FRAME_STATE_IDLE &&
- BeginFrameNeededByImplThread())
+ begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_IDLE &&
+ BeginImplFrameNeeded())
return false;
// We need a new commit for the forced redraw. This honors the
@@ -473,13 +484,16 @@ bool SchedulerStateMachine::ShouldSendBeginFrameToMainThread() const {
return true;
// After this point, we only start a commit once per frame.
- if (HasSentBeginFrameToMainThreadThisFrame())
+ if (HasSentBeginMainFrameThisFrame())
return false;
// We shouldn't normally accept commits if there isn't an OutputSurface.
if (!HasInitializedOutputSurface())
return false;
+ if (skip_begin_main_frame_to_reduce_latency_)
+ return false;
+
return true;
}
@@ -487,11 +501,21 @@ bool SchedulerStateMachine::ShouldCommit() const {
return commit_state_ == COMMIT_STATE_READY_TO_COMMIT;
}
+bool SchedulerStateMachine::IsCommitStateWaiting() const {
+ return commit_state_ == COMMIT_STATE_FRAME_IN_PROGRESS;
+}
+
bool SchedulerStateMachine::ShouldManageTiles() const {
+ // ManageTiles only really needs to be called immediately after commit
+ // and then periodically after that. Limiting to once per frame prevents
+ // post-commit and post-draw ManageTiles on the same frame.
+ if (last_frame_number_manage_tiles_called_ == current_frame_number_)
+ return false;
+
// Limiting to once per-frame is not enough, since we only want to
// manage tiles _after_ draws. Polling for draw triggers and
// begin-frame are mutually exclusive, so we limit to these two cases.
- if (begin_frame_state_ != BEGIN_FRAME_STATE_INSIDE_DEADLINE &&
+ if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE &&
!inside_poll_for_anticipated_draw_triggers_)
return false;
return needs_manage_tiles_;
@@ -518,8 +542,8 @@ SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const {
}
if (ShouldManageTiles())
return ACTION_MANAGE_TILES;
- if (ShouldSendBeginFrameToMainThread())
- return ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD;
+ if (ShouldSendBeginMainFrame())
+ return ACTION_SEND_BEGIN_MAIN_FRAME;
if (ShouldBeginOutputSurfaceCreation())
return ACTION_BEGIN_OUTPUT_SURFACE_CREATION;
return ACTION_NONE;
@@ -546,14 +570,15 @@ void SchedulerStateMachine::UpdateState(Action action) {
UpdateStateOnActivation();
return;
- case ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD:
+ case ACTION_SEND_BEGIN_MAIN_FRAME:
DCHECK(!has_pending_tree_);
- DCHECK(visible_ || readback_state_ == READBACK_STATE_NEEDS_BEGIN_FRAME);
+ DCHECK(visible_ ||
+ readback_state_ == READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME);
commit_state_ = COMMIT_STATE_FRAME_IN_PROGRESS;
needs_commit_ = false;
- if (readback_state_ == READBACK_STATE_NEEDS_BEGIN_FRAME)
+ if (readback_state_ == READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME)
readback_state_ = READBACK_STATE_WAITING_FOR_COMMIT;
- last_frame_number_begin_frame_sent_to_main_thread_ =
+ last_frame_number_begin_main_frame_sent_ =
current_frame_number_;
return;
@@ -650,13 +675,15 @@ void SchedulerStateMachine::UpdateStateOnCommit(bool commit_was_aborted) {
// Update the commit state. We expect and wait for a draw if the commit
// was not aborted or if we are in a readback or forced draw.
- if (!commit_was_aborted)
+ if (!commit_was_aborted) {
+ DCHECK(commit_state_ == COMMIT_STATE_READY_TO_COMMIT);
commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_DRAW;
- else if (readback_state_ != READBACK_STATE_IDLE ||
- forced_redraw_state_ != FORCED_REDRAW_STATE_IDLE)
+ } else if (readback_state_ != READBACK_STATE_IDLE ||
+ forced_redraw_state_ != FORCED_REDRAW_STATE_IDLE) {
commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_DRAW;
- else
+ } else {
commit_state_ = COMMIT_STATE_IDLE;
+ }
// Update state if we have a new active tree to draw, or if the active tree
// was unchanged but we need to do a readback or forced draw.
@@ -715,7 +742,7 @@ void SchedulerStateMachine::UpdateStateOnDraw(bool did_swap) {
// we should not have a pending tree.
DCHECK(!has_pending_tree_);
// We transition to COMMIT_STATE_FRAME_IN_PROGRESS because there is a
- // pending BeginFrame on the main thread behind the readback request.
+ // pending BeginMainFrame behind the readback request.
commit_state_ = COMMIT_STATE_FRAME_IN_PROGRESS;
readback_state_ = READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT;
} else if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) {
@@ -748,38 +775,50 @@ void SchedulerStateMachine::SetMainThreadNeedsLayerTextures() {
main_thread_needs_layer_textures_ = true;
}
-bool SchedulerStateMachine::BeginFrameNeededByImplThread() const {
- // Proactive BeginFrames are bad for the synchronous compositor because we
- // have to draw when we get the BeginFrame and could end up drawing many
+void SchedulerStateMachine::SetSkipBeginMainFrameToReduceLatency(bool skip) {
+ skip_begin_main_frame_to_reduce_latency_ = skip;
+}
+
+bool SchedulerStateMachine::BeginImplFrameNeeded() const {
+ // Proactive BeginImplFrames are bad for the synchronous compositor because we
+ // have to draw when we get the BeginImplFrame and could end up drawing many
// duplicate frames if our new frame isn't ready in time.
// To poll for state with the synchronous compositor without having to draw,
// we rely on ShouldPollForAnticipatedDrawTriggers instead.
- if (settings_.using_synchronous_renderer_compositor)
- return BeginFrameNeededToDrawByImplThread();
+ if (!SupportsProactiveBeginImplFrame())
+ return BeginImplFrameNeededToDraw();
- return BeginFrameNeededToDrawByImplThread() ||
- ProactiveBeginFrameWantedByImplThread();
+ return BeginImplFrameNeededToDraw() ||
+ ProactiveBeginImplFrameWanted();
}
bool SchedulerStateMachine::ShouldPollForAnticipatedDrawTriggers() const {
// ShouldPollForAnticipatedDrawTriggers is what we use in place of
- // ProactiveBeginFrameWantedByImplThread when we are using the synchronous
+ // ProactiveBeginImplFrameWanted when we are using the synchronous
// compositor.
- if (settings_.using_synchronous_renderer_compositor) {
- return !BeginFrameNeededToDrawByImplThread() &&
- ProactiveBeginFrameWantedByImplThread();
+ if (!SupportsProactiveBeginImplFrame()) {
+ return !BeginImplFrameNeededToDraw() &&
+ ProactiveBeginImplFrameWanted();
}
// Non synchronous compositors should rely on
- // ProactiveBeginFrameWantedByImplThread to poll for state instead.
+ // ProactiveBeginImplFrameWanted to poll for state instead.
return false;
}
+bool SchedulerStateMachine::SupportsProactiveBeginImplFrame() const {
+ // Both the synchronous compositor and disabled vsync settings
+ // make it undesirable to proactively request BeginImplFrames.
+ // If this is true, the scheduler should poll.
+ return !settings_.using_synchronous_renderer_compositor &&
+ settings_.throttle_frame_production;
+}
+
// These are the cases where we definitely (or almost definitely) have a
// new frame to draw and can draw.
-bool SchedulerStateMachine::BeginFrameNeededToDrawByImplThread() const {
- // The output surface is the provider of BeginFrames for the impl thread,
- // so we are not going to get them even if we ask for them.
+bool SchedulerStateMachine::BeginImplFrameNeededToDraw() const {
+ // The output surface is the provider of BeginImplFrames, so we are not going
+ // to get them even if we ask for them.
if (!HasInitializedOutputSurface())
return false;
@@ -788,7 +827,7 @@ bool SchedulerStateMachine::BeginFrameNeededToDrawByImplThread() const {
return false;
// The forced draw respects our normal draw scheduling, so we need to
- // request a BeginFrame on the impl thread for it.
+ // request a BeginImplFrame for it.
if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)
return true;
@@ -796,8 +835,8 @@ bool SchedulerStateMachine::BeginFrameNeededToDrawByImplThread() const {
if (!visible_)
return false;
- // We need to draw a more complete frame than we did the last BeginFrame,
- // so request another BeginFrame in anticipation that we will have
+ // We need to draw a more complete frame than we did the last BeginImplFrame,
+ // so request another BeginImplFrame in anticipation that we will have
// additional visible tiles.
if (swap_used_incomplete_tile_)
return true;
@@ -806,29 +845,25 @@ bool SchedulerStateMachine::BeginFrameNeededToDrawByImplThread() const {
}
// These are cases where we are very likely to draw soon, but might not
-// actually have a new frame to draw when we receive the next BeginFrame.
-// Proactively requesting the BeginFrame helps hide the round trip latency of
-// the SetNeedsBeginFrame request that has to go to the Browser.
-bool SchedulerStateMachine::ProactiveBeginFrameWantedByImplThread() const {
- // The output surface is the provider of BeginFrames for the impl thread,
+// actually have a new frame to draw when we receive the next BeginImplFrame.
+// Proactively requesting the BeginImplFrame helps hide the round trip latency
+// of the SetNeedsBeginImplFrame request that has to go to the Browser.
+bool SchedulerStateMachine::ProactiveBeginImplFrameWanted() const {
+ // The output surface is the provider of BeginImplFrames,
// so we are not going to get them even if we ask for them.
if (!HasInitializedOutputSurface())
return false;
- // Do not be proactive if vsync is off.
- if (!settings_.throttle_frame_production)
- return false;
-
// Do not be proactive when invisible.
if (!visible_)
return false;
- // We should proactively request a BeginFrame if a commit is pending
+ // We should proactively request a BeginImplFrame if a commit is pending
// because we will want to draw if the commit completes quickly.
if (needs_commit_ || commit_state_ != COMMIT_STATE_IDLE)
return true;
- // If the pending tree activates quickly, we'll want a BeginFrame soon
+ // If the pending tree activates quickly, we'll want a BeginImplFrame soon
// to draw the new active tree.
if (has_pending_tree_)
return true;
@@ -839,41 +874,43 @@ bool SchedulerStateMachine::ProactiveBeginFrameWantedByImplThread() const {
return true;
// If we just swapped, it's likely that we are going to produce another
- // frame soon. This helps avoid negative glitches in our SetNeedsBeginFrame
- // requests, which may propagate to the BeginFrame provider and get sampled
- // at an inopportune time, delaying the next BeginFrame.
+ // frame soon. This helps avoid negative glitches in our
+ // SetNeedsBeginImplFrame requests, which may propagate to the BeginImplFrame
+ // provider and get sampled at an inopportune time, delaying the next
+ // BeginImplFrame.
if (last_frame_number_swap_performed_ == current_frame_number_)
return true;
return false;
}
-void SchedulerStateMachine::OnBeginFrame(const BeginFrameArgs& args) {
+void SchedulerStateMachine::OnBeginImplFrame(const BeginFrameArgs& args) {
current_frame_number_++;
- last_begin_frame_args_ = args;
- DCHECK_EQ(begin_frame_state_, BEGIN_FRAME_STATE_IDLE) << *AsValue();
- begin_frame_state_ = BEGIN_FRAME_STATE_BEGIN_FRAME_STARTING;
+ last_begin_impl_frame_args_ = args;
+ DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_IDLE) << *AsValue();
+ begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING;
}
-void SchedulerStateMachine::OnBeginFrameDeadlinePending() {
- DCHECK_EQ(begin_frame_state_, BEGIN_FRAME_STATE_BEGIN_FRAME_STARTING)
+void SchedulerStateMachine::OnBeginImplFrameDeadlinePending() {
+ DCHECK_EQ(begin_impl_frame_state_,
+ BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING)
<< *AsValue();
- begin_frame_state_ = BEGIN_FRAME_STATE_INSIDE_BEGIN_FRAME;
+ begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME;
}
-void SchedulerStateMachine::OnBeginFrameDeadline() {
- DCHECK_EQ(begin_frame_state_, BEGIN_FRAME_STATE_INSIDE_BEGIN_FRAME)
+void SchedulerStateMachine::OnBeginImplFrameDeadline() {
+ DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME)
<< *AsValue();
- begin_frame_state_ = BEGIN_FRAME_STATE_INSIDE_DEADLINE;
+ begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE;
}
-void SchedulerStateMachine::OnBeginFrameIdle() {
- DCHECK_EQ(begin_frame_state_, BEGIN_FRAME_STATE_INSIDE_DEADLINE)
+void SchedulerStateMachine::OnBeginImplFrameIdle() {
+ DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE)
<< *AsValue();
- begin_frame_state_ = BEGIN_FRAME_STATE_IDLE;
+ begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_IDLE;
}
-bool SchedulerStateMachine::ShouldTriggerBeginFrameDeadlineEarly() const {
+bool SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineEarly() const {
// TODO(brianderson): This should take into account multiple commit sources.
// If we are in the middle of the readback, we won't swap, so there is
@@ -881,7 +918,7 @@ bool SchedulerStateMachine::ShouldTriggerBeginFrameDeadlineEarly() const {
if (readback_state_ != READBACK_STATE_IDLE)
return false;
- if (begin_frame_state_ != BEGIN_FRAME_STATE_INSIDE_BEGIN_FRAME)
+ if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME)
return false;
if (active_tree_needs_first_draw_)
@@ -905,6 +942,44 @@ bool SchedulerStateMachine::ShouldTriggerBeginFrameDeadlineEarly() const {
return false;
}
+bool SchedulerStateMachine::MainThreadIsInHighLatencyMode() const {
+ // If we just sent a BeginMainFrame and haven't hit the deadline yet, the main
+ // thread is in a low latency mode.
+ if (last_frame_number_begin_main_frame_sent_ == current_frame_number_ &&
+ (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 (commit_state_ == COMMIT_STATE_FRAME_IN_PROGRESS ||
+ commit_state_ == COMMIT_STATE_READY_TO_COMMIT)
+ 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
+ // drawn 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_ ||
+ last_frame_number_swap_performed_ == current_frame_number_) &&
+ last_frame_number_begin_main_frame_sent_ != current_frame_number_;
+ }
+
+ // 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_;
+}
+
void SchedulerStateMachine::DidEnterPollForAnticipatedDrawTriggers() {
current_frame_number_++;
inside_poll_for_anticipated_draw_triggers_ = true;
@@ -921,7 +996,11 @@ void SchedulerStateMachine::SetCanDraw(bool can_draw) { can_draw_ = can_draw; }
void SchedulerStateMachine::SetNeedsRedraw() { needs_redraw_ = true; }
void SchedulerStateMachine::SetNeedsManageTiles() {
- needs_manage_tiles_ = true;
+ if (!needs_manage_tiles_) {
+ TRACE_EVENT0("cc",
+ "SchedulerStateMachine::SetNeedsManageTiles");
+ needs_manage_tiles_ = true;
+ }
}
void SchedulerStateMachine::SetSwapUsedIncompleteTile(
@@ -938,6 +1017,12 @@ void SchedulerStateMachine::DidDrawIfPossibleCompleted(bool success) {
draw_if_possible_failed_ = !success;
if (draw_if_possible_failed_) {
needs_redraw_ = true;
+
+ // If we're already in the middle of a redraw, we don't need to
+ // restart it.
+ if (forced_redraw_state_ != FORCED_REDRAW_STATE_IDLE)
+ return;
+
needs_commit_ = true;
consecutive_failed_draws_++;
if (settings_.timeout_and_draw_when_animation_checkerboards &&
@@ -950,6 +1035,7 @@ void SchedulerStateMachine::DidDrawIfPossibleCompleted(bool success) {
}
} else {
consecutive_failed_draws_ = 0;
+ forced_redraw_state_ = FORCED_REDRAW_STATE_IDLE;
}
}
@@ -966,14 +1052,14 @@ void SchedulerStateMachine::SetNeedsForcedCommitForReadback() {
// If there is already a commit in progress when we get the readback request
// (we are in COMMIT_STATE_FRAME_IN_PROGRESS), then we don't need to send a
- // BeginFrame for the replacement commit, since there's already a BeginFrame
- // behind the readback request. In that case, we can skip
- // READBACK_STATE_NEEDS_BEGIN_FRAME and go directly to
+ // BeginMainFrame for the replacement commit, since there's already a
+ // BeginMainFrame behind the readback request. In that case, we can skip
+ // READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME and go directly to
// READBACK_STATE_WAITING_FOR_COMMIT
if (commit_state_ == COMMIT_STATE_FRAME_IN_PROGRESS)
readback_state_ = READBACK_STATE_WAITING_FOR_COMMIT;
else
- readback_state_ = READBACK_STATE_NEEDS_BEGIN_FRAME;
+ readback_state_ = READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME;
}
void SchedulerStateMachine::FinishCommit() {
@@ -981,7 +1067,7 @@ void SchedulerStateMachine::FinishCommit() {
commit_state_ = COMMIT_STATE_READY_TO_COMMIT;
}
-void SchedulerStateMachine::BeginFrameAbortedByMainThread(bool did_handle) {
+void SchedulerStateMachine::BeginMainFrameAborted(bool did_handle) {
DCHECK_EQ(commit_state_, COMMIT_STATE_FRAME_IN_PROGRESS);
if (did_handle) {
bool commit_was_aborted = true;
@@ -993,13 +1079,18 @@ void SchedulerStateMachine::BeginFrameAbortedByMainThread(bool did_handle) {
}
}
+void SchedulerStateMachine::DidManageTiles() {
+ needs_manage_tiles_ = false;
+ last_frame_number_manage_tiles_called_ = current_frame_number_;
+}
+
void SchedulerStateMachine::DidLoseOutputSurface() {
if (output_surface_state_ == OUTPUT_SURFACE_LOST ||
output_surface_state_ == OUTPUT_SURFACE_CREATING)
return;
output_surface_state_ = OUTPUT_SURFACE_LOST;
needs_redraw_ = false;
- begin_frame_state_ = BEGIN_FRAME_STATE_IDLE;
+ begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_IDLE;
}
void SchedulerStateMachine::NotifyReadyToActivate() {
diff --git a/chromium/cc/scheduler/scheduler_state_machine.h b/chromium/cc/scheduler/scheduler_state_machine.h
index a3d67ef765e..2e61224fb28 100644
--- a/chromium/cc/scheduler/scheduler_state_machine.h
+++ b/chromium/cc/scheduler/scheduler_state_machine.h
@@ -45,17 +45,17 @@ class CC_EXPORT SchedulerStateMachine {
};
static const char* OutputSurfaceStateToString(OutputSurfaceState state);
- // Note: BeginFrameState will always cycle through all the states in order.
- // Whether or not it actually waits or draws, it will at least try to wait in
- // BEGIN_FRAME_STATE_INSIDE_BEGIN_FRAME and try to draw in
- // BEGIN_FRAME_STATE_INSIDE_DEADLINE
- enum BeginFrameState {
- BEGIN_FRAME_STATE_IDLE,
- BEGIN_FRAME_STATE_BEGIN_FRAME_STARTING,
- BEGIN_FRAME_STATE_INSIDE_BEGIN_FRAME,
- BEGIN_FRAME_STATE_INSIDE_DEADLINE,
+ // Note: BeginImplFrameState will always cycle through all the states in
+ // order. Whether or not it actually waits or draws, it will at least try to
+ // wait in BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME and try to draw in
+ // BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE
+ enum BeginImplFrameState {
+ BEGIN_IMPL_FRAME_STATE_IDLE,
+ BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING,
+ BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME,
+ BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE,
};
- static const char* BeginFrameStateToString(BeginFrameState state);
+ static const char* BeginImplFrameStateToString(BeginImplFrameState state);
enum CommitState {
COMMIT_STATE_IDLE,
@@ -74,7 +74,7 @@ class CC_EXPORT SchedulerStateMachine {
enum SynchronousReadbackState {
READBACK_STATE_IDLE,
- READBACK_STATE_NEEDS_BEGIN_FRAME,
+ READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME,
READBACK_STATE_WAITING_FOR_COMMIT,
READBACK_STATE_WAITING_FOR_ACTIVATION,
READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK,
@@ -103,7 +103,7 @@ class CC_EXPORT SchedulerStateMachine {
enum Action {
ACTION_NONE,
- ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD,
+ ACTION_SEND_BEGIN_MAIN_FRAME,
ACTION_COMMIT,
ACTION_UPDATE_VISIBLE_TILES,
ACTION_ACTIVATE_PENDING_TREE,
@@ -124,28 +124,32 @@ class CC_EXPORT SchedulerStateMachine {
void CheckInvariants();
- // Indicates whether the main thread needs a begin frame callback in order to
- // make progress.
- bool BeginFrameNeededByImplThread() const;
+ // Indicates whether the impl thread needs a BeginImplFrame callback in order
+ // to make progress.
+ bool BeginImplFrameNeeded() const;
- // Idicates that we need to independently poll for new state and actions
- // because we can't expect a BeginFrame. This is mostly used to avoid
+ // Indicates that we need to independently poll for new state and actions
+ // because we can't expect a BeginImplFrame. This is mostly used to avoid
// drawing repeat frames with the synchronous compositor without dropping
// necessary actions on the floor.
bool ShouldPollForAnticipatedDrawTriggers() const;
- // Indicates that the system has entered and left a BeginFrame callback.
- // The scheduler will not draw more than once in a given BeginFrame
- // callback nor send more than one BeginFrame message.
- void OnBeginFrame(const BeginFrameArgs& args);
- void OnBeginFrameDeadlinePending();
- void OnBeginFrameDeadline();
- void OnBeginFrameIdle();
- bool ShouldTriggerBeginFrameDeadlineEarly() const;
- BeginFrameState begin_frame_state() const {
- return begin_frame_state_;
+ // Indicates that the system has entered and left a BeginImplFrame callback.
+ // The scheduler will not draw more than once in a given BeginImplFrame
+ // callback nor send more than one BeginMainFrame message.
+ void OnBeginImplFrame(const BeginFrameArgs& args);
+ void OnBeginImplFrameDeadlinePending();
+ void OnBeginImplFrameDeadline();
+ void OnBeginImplFrameIdle();
+ bool ShouldTriggerBeginImplFrameDeadlineEarly() const;
+ BeginImplFrameState begin_impl_frame_state() const {
+ return begin_impl_frame_state_;
}
+ // 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;
+
// PollForAnticipatedDrawTriggers is used by the synchronous compositor to
// avoid requesting BeginImplFrames when we won't actually draw but still
// need to advance our state at vsync intervals.
@@ -183,22 +187,21 @@ class CC_EXPORT SchedulerStateMachine {
// thread to main.
void SetNeedsCommit();
- // As SetNeedsCommit(), but ensures the begin frame will be sent to the main
- // thread even if we are not visible. After this call we expect to go through
+ // As SetNeedsCommit(), but ensures the BeginMainFrame will be sent even
+ // if we are not visible. After this call we expect to go through
// the forced commit flow and then return to waiting for a non-forced
- // begin frame to finish.
+ // BeginMainFrame to finish.
void SetNeedsForcedCommitForReadback();
- // Call this only in response to receiving an
- // ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD from NextAction.
+ // Call this only in response to receiving an ACTION_SEND_BEGIN_MAIN_FRAME
+ // from NextAction.
// Indicates that all painting is complete.
void FinishCommit();
- // Call this only in response to receiving an
- // ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD from NextAction if the client
- // rejects the begin frame message. If did_handle is false, then
- // another commit will be retried soon.
- void BeginFrameAbortedByMainThread(bool did_handle);
+ // Call this only in response to receiving an ACTION_SEND_BEGIN_MAIN_FRAME
+ // from NextAction if the client rejects the BeginMainFrame message.
+ // If did_handle is false, then another commit will be retried soon.
+ void BeginMainFrameAborted(bool did_handle);
// Request exclusive access to the textures that back single buffered
// layers on behalf of the main thread. Upon acquisition,
@@ -210,8 +213,10 @@ class CC_EXPORT SchedulerStateMachine {
// Set that we can create the first OutputSurface and start the scheduler.
void SetCanStart() { can_start_ = true; }
+ void SetSkipBeginMainFrameToReduceLatency(bool skip);
+
// Indicates whether drawing would, at this time, make sense.
- // CanDraw can be used to supress flashes or checkerboarding
+ // CanDraw can be used to suppress flashes or checkerboarding
// when such behavior would be undesirable.
void SetCanDraw(bool can);
@@ -220,6 +225,7 @@ class CC_EXPORT SchedulerStateMachine {
bool has_pending_tree() const { return has_pending_tree_; }
+ void DidManageTiles();
void DidLoseOutputSurface();
void DidCreateAndInitializeOutputSurface();
bool HasInitializedOutputSurface() const;
@@ -227,9 +233,13 @@ class CC_EXPORT SchedulerStateMachine {
// True if we need to abort draws to make forward progress.
bool PendingDrawsShouldBeAborted() const;
+ bool SupportsProactiveBeginImplFrame() const;
+
+ bool IsCommitStateWaiting() const;
+
protected:
- bool BeginFrameNeededToDrawByImplThread() const;
- bool ProactiveBeginFrameWantedByImplThread() const;
+ bool BeginImplFrameNeededToDraw() const;
+ bool ProactiveBeginImplFrameWanted() const;
// True if we need to force activations to make forward progress.
bool PendingActivationsShouldBeForced() const;
@@ -240,11 +250,11 @@ class CC_EXPORT SchedulerStateMachine {
bool ShouldActivatePendingTree() const;
bool ShouldAcquireLayerTexturesForMainThread() const;
bool ShouldUpdateVisibleTiles() const;
- bool ShouldSendBeginFrameToMainThread() const;
+ bool ShouldSendBeginMainFrame() const;
bool ShouldCommit() const;
bool ShouldManageTiles() const;
- bool HasSentBeginFrameToMainThreadThisFrame() const;
+ bool HasSentBeginMainFrameThisFrame() const;
bool HasScheduledManageTilesThisFrame() const;
bool HasUpdatedVisibleTilesThisFrame() const;
bool HasSwappedThisFrame() const;
@@ -257,19 +267,20 @@ class CC_EXPORT SchedulerStateMachine {
const SchedulerSettings settings_;
OutputSurfaceState output_surface_state_;
- BeginFrameState begin_frame_state_;
+ BeginImplFrameState begin_impl_frame_state_;
CommitState commit_state_;
TextureState texture_state_;
ForcedRedrawOnTimeoutState forced_redraw_state_;
SynchronousReadbackState readback_state_;
- BeginFrameArgs last_begin_frame_args_;
+ BeginFrameArgs last_begin_impl_frame_args_;
int commit_count_;
int current_frame_number_;
int last_frame_number_swap_performed_;
- int last_frame_number_begin_frame_sent_to_main_thread_;
+ int last_frame_number_begin_main_frame_sent_;
int last_frame_number_update_visible_tiles_was_called_;
+ int last_frame_number_manage_tiles_called_;
int consecutive_failed_draws_;
bool needs_redraw_;
@@ -287,6 +298,7 @@ class CC_EXPORT SchedulerStateMachine {
bool draw_if_possible_failed_;
bool did_create_and_initialize_first_output_surface_;
bool smoothness_takes_priority_;
+ bool skip_begin_main_frame_to_reduce_latency_;
private:
DISALLOW_COPY_AND_ASSIGN(SchedulerStateMachine);
diff --git a/chromium/cc/scheduler/scheduler_state_machine_unittest.cc b/chromium/cc/scheduler/scheduler_state_machine_unittest.cc
index af3231b0db3..67925a059b3 100644
--- a/chromium/cc/scheduler/scheduler_state_machine_unittest.cc
+++ b/chromium/cc/scheduler/scheduler_state_machine_unittest.cc
@@ -7,38 +7,38 @@
#include "cc/scheduler/scheduler.h"
#include "testing/gtest/include/gtest/gtest.h"
-#define EXPECT_ACTION_UPDATE_STATE(action) \
- EXPECT_EQ(action, state.NextAction()) << *state.AsValue(); \
- if (action == SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE || \
- action == SchedulerStateMachine::ACTION_DRAW_AND_SWAP_FORCED) { \
- if (SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW == \
- state.CommitState() && \
- SchedulerStateMachine::OUTPUT_SURFACE_ACTIVE != \
- state.output_surface_state()) \
- return; \
- EXPECT_EQ(SchedulerStateMachine::BEGIN_FRAME_STATE_INSIDE_DEADLINE, \
- state.begin_frame_state()) \
- << *state.AsValue(); \
- } \
- state.UpdateState(action); \
- if (action == SchedulerStateMachine::ACTION_NONE) { \
- if (state.begin_frame_state() == \
- SchedulerStateMachine::BEGIN_FRAME_STATE_BEGIN_FRAME_STARTING) \
- state.OnBeginFrameDeadlinePending(); \
- if (state.begin_frame_state() == \
- SchedulerStateMachine::BEGIN_FRAME_STATE_INSIDE_DEADLINE) \
- state.OnBeginFrameIdle(); \
+#define EXPECT_ACTION_UPDATE_STATE(action) \
+ EXPECT_EQ(action, state.NextAction()) << *state.AsValue(); \
+ if (action == SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE || \
+ action == SchedulerStateMachine::ACTION_DRAW_AND_SWAP_FORCED) { \
+ if (SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW == \
+ state.CommitState() && \
+ SchedulerStateMachine::OUTPUT_SURFACE_ACTIVE != \
+ state.output_surface_state()) \
+ return; \
+ EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE, \
+ state.begin_impl_frame_state()) \
+ << *state.AsValue(); \
+ } \
+ state.UpdateState(action); \
+ if (action == SchedulerStateMachine::ACTION_NONE) { \
+ if (state.begin_impl_frame_state() == \
+ SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING) \
+ state.OnBeginImplFrameDeadlinePending(); \
+ if (state.begin_impl_frame_state() == \
+ SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) \
+ state.OnBeginImplFrameIdle(); \
}
namespace cc {
namespace {
-const SchedulerStateMachine::BeginFrameState all_begin_frame_states[] = {
- SchedulerStateMachine::BEGIN_FRAME_STATE_IDLE,
- SchedulerStateMachine::BEGIN_FRAME_STATE_BEGIN_FRAME_STARTING,
- SchedulerStateMachine::BEGIN_FRAME_STATE_INSIDE_BEGIN_FRAME,
- SchedulerStateMachine::BEGIN_FRAME_STATE_INSIDE_DEADLINE, };
+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,
@@ -60,9 +60,17 @@ class StateMachine : public SchedulerStateMachine {
void SetCommitState(CommitState cs) { commit_state_ = cs; }
CommitState CommitState() const { return commit_state_; }
- void SetBeginFrameState(BeginFrameState bfs) { begin_frame_state_ = bfs; }
+ ForcedRedrawOnTimeoutState ForcedRedrawState() const {
+ return forced_redraw_state_;
+ }
+
+ void SetBeginImplFrameState(BeginImplFrameState bifs) {
+ begin_impl_frame_state_ = bifs;
+ }
- BeginFrameState begin_frame_state() const { return begin_frame_state_; }
+ BeginImplFrameState begin_impl_frame_state() const {
+ return begin_impl_frame_state_;
+ }
OutputSurfaceState output_surface_state() const {
return output_surface_state_;
@@ -115,14 +123,14 @@ TEST(SchedulerStateMachineTest, TestNextActionBeginsMainFrameIfNeeded) {
state.SetNeedsRedraw(false);
state.SetVisible(true);
- EXPECT_FALSE(state.BeginFrameNeededByImplThread());
+ EXPECT_FALSE(state.BeginImplFrameNeeded());
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- EXPECT_FALSE(state.BeginFrameNeededByImplThread());
- state.OnBeginFrame(BeginFrameArgs::CreateForTesting());
+ EXPECT_FALSE(state.BeginImplFrameNeeded());
+ state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- state.OnBeginFrameDeadline();
+ state.OnBeginImplFrameDeadline();
}
// If commit requested but can_start is still false, do nothing.
@@ -132,13 +140,13 @@ TEST(SchedulerStateMachineTest, TestNextActionBeginsMainFrameIfNeeded) {
state.SetNeedsRedraw(false);
state.SetVisible(true);
- EXPECT_FALSE(state.BeginFrameNeededByImplThread());
+ EXPECT_FALSE(state.BeginImplFrameNeeded());
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- EXPECT_FALSE(state.BeginFrameNeededByImplThread());
- state.OnBeginFrame(BeginFrameArgs::CreateForTesting());
+ EXPECT_FALSE(state.BeginImplFrameNeeded());
+ state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- state.OnBeginFrameDeadline();
+ state.OnBeginImplFrameDeadline();
}
// If commit requested, begin a main frame.
@@ -148,7 +156,7 @@ TEST(SchedulerStateMachineTest, TestNextActionBeginsMainFrameIfNeeded) {
state.SetCanStart();
state.SetNeedsRedraw(false);
state.SetVisible(true);
- EXPECT_FALSE(state.BeginFrameNeededByImplThread());
+ EXPECT_FALSE(state.BeginImplFrameNeeded());
}
// Begin the frame, make sure needs_commit and commit_state update correctly.
@@ -158,8 +166,7 @@ TEST(SchedulerStateMachineTest, TestNextActionBeginsMainFrameIfNeeded) {
state.UpdateState(state.NextAction());
state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
state.SetVisible(true);
- state.UpdateState(
- SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD);
+ state.UpdateState(SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS,
state.CommitState());
EXPECT_FALSE(state.NeedsCommit());
@@ -177,10 +184,10 @@ TEST(SchedulerStateMachineTest,
state.SetCanDraw(true);
state.SetNeedsRedraw(true);
EXPECT_TRUE(state.RedrawPending());
- EXPECT_TRUE(state.BeginFrameNeededByImplThread());
- state.OnBeginFrame(BeginFrameArgs::CreateForTesting());
+ EXPECT_TRUE(state.BeginImplFrameNeeded());
+ state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- state.OnBeginFrameDeadline();
+ state.OnBeginImplFrameDeadline();
// We're drawing now.
EXPECT_ACTION_UPDATE_STATE(
@@ -192,9 +199,9 @@ TEST(SchedulerStateMachineTest,
// Failing the draw makes us require a commit.
state.DidDrawIfPossibleCompleted(false);
- state.OnBeginFrame(BeginFrameArgs::CreateForTesting());
+ state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD);
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
EXPECT_TRUE(state.RedrawPending());
EXPECT_TRUE(state.CommitPending());
}
@@ -211,10 +218,10 @@ TEST(SchedulerStateMachineTest,
state.SetCanDraw(true);
state.SetNeedsRedraw(true);
EXPECT_TRUE(state.RedrawPending());
- EXPECT_TRUE(state.BeginFrameNeededByImplThread());
- state.OnBeginFrame(BeginFrameArgs::CreateForTesting());
+ EXPECT_TRUE(state.BeginImplFrameNeeded());
+ state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- state.OnBeginFrameDeadline();
+ state.OnBeginImplFrameDeadline();
// We're drawing now.
EXPECT_ACTION_UPDATE_STATE(
@@ -223,16 +230,16 @@ TEST(SchedulerStateMachineTest,
EXPECT_FALSE(state.RedrawPending());
EXPECT_FALSE(state.CommitPending());
- // While still in the same begin frame callback on the main thread,
+ // While still in the same BeginMainFrame callback on the main thread,
// set needs redraw again. This should not redraw.
state.SetNeedsRedraw(true);
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
// Failing the draw makes us require a commit.
state.DidDrawIfPossibleCompleted(false);
- state.OnBeginFrame(BeginFrameArgs::CreateForTesting());
+ state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD);
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
EXPECT_TRUE(state.RedrawPending());
}
@@ -252,27 +259,27 @@ void TestFailedDrawsWillEventuallyForceADrawAfterTheNextCommit(
state.SetNeedsCommit();
if (!deadline_scheduling_enabled) {
EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD);
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
}
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- state.OnBeginFrame(BeginFrameArgs::CreateForTesting());
+ state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
if (deadline_scheduling_enabled) {
EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD);
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
}
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
EXPECT_TRUE(state.CommitPending());
// Then initiate a draw.
state.SetNeedsRedraw(true);
- state.OnBeginFrameDeadline();
+ state.OnBeginImplFrameDeadline();
EXPECT_ACTION_UPDATE_STATE(
SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
// Fail the draw.
state.DidDrawIfPossibleCompleted(false);
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- EXPECT_TRUE(state.BeginFrameNeededByImplThread());
+ EXPECT_TRUE(state.BeginImplFrameNeeded());
EXPECT_TRUE(state.RedrawPending());
// But the commit is ongoing.
EXPECT_TRUE(state.CommitPending());
@@ -284,10 +291,10 @@ void TestFailedDrawsWillEventuallyForceADrawAfterTheNextCommit(
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
EXPECT_TRUE(state.RedrawPending());
- // The redraw should be forced at the end of the next BeginFrame.
- state.OnBeginFrame(BeginFrameArgs::CreateForTesting());
+ // The redraw should be forced at the end of the next BeginImplFrame.
+ state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- state.OnBeginFrameDeadline();
+ state.OnBeginImplFrameDeadline();
EXPECT_ACTION_UPDATE_STATE(
SchedulerStateMachine::ACTION_DRAW_AND_SWAP_FORCED);
}
@@ -306,8 +313,90 @@ TEST(SchedulerStateMachineTest,
deadline_scheduling_enabled);
}
+void TestFailedDrawsDoNotRestartForcedDraw(
+ bool deadline_scheduling_enabled) {
+ SchedulerSettings scheduler_settings;
+ int drawLimit = 1;
+ scheduler_settings.maximum_number_of_failed_draws_before_draw_is_forced_ =
+ drawLimit;
+ scheduler_settings.deadline_scheduling_enabled = deadline_scheduling_enabled;
+ scheduler_settings.impl_side_painting = true;
+ StateMachine state(scheduler_settings);
+ state.SetCanStart();
+ state.UpdateState(state.NextAction());
+ state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
+ state.SetVisible(true);
+ state.SetCanDraw(true);
+
+ // Start a commit.
+ state.SetNeedsCommit();
+ if (!deadline_scheduling_enabled) {
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
+ }
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
+ if (deadline_scheduling_enabled) {
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
+ }
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ EXPECT_TRUE(state.CommitPending());
+
+ // Then initiate a draw.
+ state.SetNeedsRedraw(true);
+ state.OnBeginImplFrameDeadline();
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
+
+ // Fail the draw enough times to force a redraw,
+ // then once more for good measure.
+ for (int i = 0; i < drawLimit; ++i)
+ state.DidDrawIfPossibleCompleted(false);
+ state.DidDrawIfPossibleCompleted(false);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ EXPECT_TRUE(state.BeginImplFrameNeeded());
+ EXPECT_TRUE(state.RedrawPending());
+ // But the commit is ongoing.
+ EXPECT_TRUE(state.CommitPending());
+ EXPECT_TRUE(state.ForcedRedrawState() ==
+ SchedulerStateMachine::FORCED_REDRAW_STATE_WAITING_FOR_COMMIT);
+
+ state.FinishCommit();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ EXPECT_TRUE(state.RedrawPending());
+ EXPECT_FALSE(state.CommitPending());
+
+ // Now force redraw should be in waiting for activation
+ EXPECT_TRUE(state.ForcedRedrawState() ==
+ SchedulerStateMachine::FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION);
+
+ // After failing additional draws, we should still be in a forced
+ // redraw, but not back in WAITING_FOR_COMMIT.
+ for (int i = 0; i < drawLimit; ++i)
+ state.DidDrawIfPossibleCompleted(false);
+ state.DidDrawIfPossibleCompleted(false);
+ EXPECT_TRUE(state.RedrawPending());
+ EXPECT_TRUE(state.ForcedRedrawState() ==
+ SchedulerStateMachine::FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION);
+}
+
+TEST(SchedulerStateMachineTest,
+ TestFailedDrawsDoNotRestartForcedDraw) {
+ bool deadline_scheduling_enabled = false;
+ TestFailedDrawsDoNotRestartForcedDraw(
+ deadline_scheduling_enabled);
+}
+
TEST(SchedulerStateMachineTest,
- TestFailedDrawIsRetriedInNextBeginFrameForImplThread) {
+ TestFailedDrawsDoNotRestartForcedDraw_Deadline) {
+ bool deadline_scheduling_enabled = true;
+ TestFailedDrawsDoNotRestartForcedDraw(
+ deadline_scheduling_enabled);
+}
+
+TEST(SchedulerStateMachineTest, TestFailedDrawIsRetriedInNextBeginImplFrame) {
SchedulerSettings default_scheduler_settings;
StateMachine state(default_scheduler_settings);
state.SetCanStart();
@@ -318,10 +407,10 @@ TEST(SchedulerStateMachineTest,
// Start a draw.
state.SetNeedsRedraw(true);
- EXPECT_TRUE(state.BeginFrameNeededByImplThread());
- state.OnBeginFrame(BeginFrameArgs::CreateForTesting());
+ EXPECT_TRUE(state.BeginImplFrameNeeded());
+ state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- state.OnBeginFrameDeadline();
+ state.OnBeginImplFrameDeadline();
EXPECT_TRUE(state.RedrawPending());
EXPECT_ACTION_UPDATE_STATE(
SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
@@ -329,18 +418,18 @@ TEST(SchedulerStateMachineTest,
// Fail the draw
state.DidDrawIfPossibleCompleted(false);
EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD);
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
EXPECT_TRUE(state.RedrawPending());
// We should not be trying to draw again now, but we have a commit pending.
- EXPECT_TRUE(state.BeginFrameNeededByImplThread());
- state.OnBeginFrame(BeginFrameArgs::CreateForTesting());
+ EXPECT_TRUE(state.BeginImplFrameNeeded());
+ state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- // We should try to draw again at the end of the next BeginFrame on
+ // We should try to draw again at the end of the next BeginImplFrame on
// the impl thread.
- state.OnBeginFrameDeadline();
+ state.OnBeginImplFrameDeadline();
EXPECT_ACTION_UPDATE_STATE(
SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
@@ -357,57 +446,58 @@ TEST(SchedulerStateMachineTest, TestDoestDrawTwiceInSameFrame) {
state.SetNeedsRedraw(true);
// Draw the first frame.
- EXPECT_TRUE(state.BeginFrameNeededByImplThread());
- state.OnBeginFrame(BeginFrameArgs::CreateForTesting());
+ EXPECT_TRUE(state.BeginImplFrameNeeded());
+ state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- state.OnBeginFrameDeadline();
+ state.OnBeginImplFrameDeadline();
EXPECT_ACTION_UPDATE_STATE(
SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
state.DidDrawIfPossibleCompleted(true);
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- // Before the next begin frame for the impl thread, set needs redraw
- // again. This should not redraw until the next begin frame.
+ // Before the next BeginImplFrame, set needs redraw again.
+ // This should not redraw until the next BeginImplFrame.
state.SetNeedsRedraw(true);
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
// Move to another frame. This should now draw.
- EXPECT_TRUE(state.BeginFrameNeededByImplThread());
- state.OnBeginFrame(BeginFrameArgs::CreateForTesting());
+ EXPECT_TRUE(state.BeginImplFrameNeeded());
+ state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- state.OnBeginFrameDeadline();
+ state.OnBeginImplFrameDeadline();
EXPECT_ACTION_UPDATE_STATE(
SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
state.DidDrawIfPossibleCompleted(true);
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- // We just swapped, so we should proactively request another BeginFrame.
- EXPECT_TRUE(state.BeginFrameNeededByImplThread());
+ // We just swapped, so we should proactively request another BeginImplFrame.
+ EXPECT_TRUE(state.BeginImplFrameNeeded());
}
-TEST(SchedulerStateMachineTest, TestNextActionDrawsOnBeginFrame) {
+TEST(SchedulerStateMachineTest, TestNextActionDrawsOnBeginImplFrame) {
SchedulerSettings default_scheduler_settings;
- // When not in BeginFrame deadline, or in BeginFrame deadline but not visible,
- // don't draw.
+ // 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_frame_states =
- sizeof(all_begin_frame_states) /
- sizeof(SchedulerStateMachine::BeginFrameState);
+ 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 j = 0; j < num_begin_frame_states; ++j) {
+ for (size_t j = 0; j < num_begin_impl_frame_states; ++j) {
StateMachine state(default_scheduler_settings);
state.SetCanStart();
state.UpdateState(state.NextAction());
state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
state.SetCommitState(all_commit_states[i]);
- state.SetBeginFrameState(all_begin_frame_states[j]);
- bool visible = (all_begin_frame_states[j] !=
- SchedulerStateMachine::BEGIN_FRAME_STATE_INSIDE_DEADLINE);
+ 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
@@ -422,7 +512,7 @@ TEST(SchedulerStateMachineTest, TestNextActionDrawsOnBeginFrame) {
}
}
- // When in BeginFrame deadline we should always draw for SetNeedsRedraw or
+ // When in BeginImplFrame deadline we should always draw for SetNeedsRedraw or
// SetNeedsForcedRedrawForReadback have been called... 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) {
@@ -441,8 +531,8 @@ TEST(SchedulerStateMachineTest, TestNextActionDrawsOnBeginFrame) {
state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
state.SetCanDraw(true);
state.SetCommitState(all_commit_states[i]);
- state.SetBeginFrameState(
- SchedulerStateMachine::BEGIN_FRAME_STATE_INSIDE_DEADLINE);
+ state.SetBeginImplFrameState(
+ SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE);
if (request_readback) {
state.SetNeedsForcedRedrawForReadback();
} else {
@@ -466,13 +556,13 @@ TEST(SchedulerStateMachineTest, TestNextActionDrawsOnBeginFrame) {
}
// Case 1: needs_commit=false.
- EXPECT_NE(state.BeginFrameNeededByImplThread(), request_readback)
+ EXPECT_NE(state.BeginImplFrameNeeded(), request_readback)
<< *state.AsValue();
EXPECT_EQ(expected_action, state.NextAction()) << *state.AsValue();
// Case 2: needs_commit=true.
state.SetNeedsCommit();
- EXPECT_NE(state.BeginFrameNeededByImplThread(), request_readback)
+ EXPECT_NE(state.BeginImplFrameNeeded(), request_readback)
<< *state.AsValue();
EXPECT_EQ(expected_action, state.NextAction()) << *state.AsValue();
}
@@ -485,7 +575,7 @@ TEST(SchedulerStateMachineTest, TestNoCommitStatesRedrawWhenInvisible) {
size_t num_commit_states =
sizeof(all_commit_states) / sizeof(SchedulerStateMachine::CommitState);
for (size_t i = 0; i < num_commit_states; ++i) {
- // There shouldn't be any drawing regardless of BeginFrame.
+ // There shouldn't be any drawing regardless of BeginImplFrame.
for (size_t j = 0; j < 2; ++j) {
StateMachine state(default_scheduler_settings);
state.SetCanStart();
@@ -495,8 +585,8 @@ TEST(SchedulerStateMachineTest, TestNoCommitStatesRedrawWhenInvisible) {
state.SetVisible(false);
state.SetNeedsRedraw(true);
if (j == 1) {
- state.SetBeginFrameState(
- SchedulerStateMachine::BEGIN_FRAME_STATE_INSIDE_DEADLINE);
+ state.SetBeginImplFrameState(
+ SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE);
}
// Case 1: needs_commit=false.
@@ -518,7 +608,7 @@ TEST(SchedulerStateMachineTest, TestCanRedraw_StopsDraw) {
size_t num_commit_states =
sizeof(all_commit_states) / sizeof(SchedulerStateMachine::CommitState);
for (size_t i = 0; i < num_commit_states; ++i) {
- // There shouldn't be any drawing regardless of BeginFrame.
+ // There shouldn't be any drawing regardless of BeginImplFrame.
for (size_t j = 0; j < 2; ++j) {
StateMachine state(default_scheduler_settings);
state.SetCanStart();
@@ -528,7 +618,7 @@ TEST(SchedulerStateMachineTest, TestCanRedraw_StopsDraw) {
state.SetVisible(false);
state.SetNeedsRedraw(true);
if (j == 1)
- state.OnBeginFrame(BeginFrameArgs::CreateForTesting());
+ state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
state.SetCanDraw(false);
EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE,
@@ -552,14 +642,14 @@ TEST(SchedulerStateMachineTest,
state.SetNeedsRedraw(true);
state.SetVisible(true);
state.SetCanDraw(false);
- state.OnBeginFrame(BeginFrameArgs::CreateForTesting());
+ state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT);
EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD);
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
state.FinishCommit();
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
- state.OnBeginFrameDeadline();
+ state.OnBeginImplFrameDeadline();
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT);
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
}
@@ -574,12 +664,12 @@ TEST(SchedulerStateMachineTest, TestsetNeedsCommitIsNotLost) {
state.SetVisible(true);
state.SetCanDraw(true);
- EXPECT_TRUE(state.BeginFrameNeededByImplThread());
+ EXPECT_TRUE(state.BeginImplFrameNeeded());
// Begin the frame.
- state.OnBeginFrame(BeginFrameArgs::CreateForTesting());
+ state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD);
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS,
state.CommitState());
@@ -592,35 +682,35 @@ TEST(SchedulerStateMachineTest, TestsetNeedsCommitIsNotLost) {
EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT,
state.CommitState());
- // Expect to commit regardless of BeginFrame state.
- EXPECT_EQ(SchedulerStateMachine::BEGIN_FRAME_STATE_BEGIN_FRAME_STARTING,
- state.begin_frame_state());
+ // Expect to commit regardless of BeginImplFrame state.
+ EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING,
+ state.begin_impl_frame_state());
EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction());
- state.OnBeginFrameDeadlinePending();
- EXPECT_EQ(SchedulerStateMachine::BEGIN_FRAME_STATE_INSIDE_BEGIN_FRAME,
- state.begin_frame_state());
+ state.OnBeginImplFrameDeadlinePending();
+ EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME,
+ state.begin_impl_frame_state());
EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction());
- state.OnBeginFrameDeadline();
- EXPECT_EQ(SchedulerStateMachine::BEGIN_FRAME_STATE_INSIDE_DEADLINE,
- state.begin_frame_state());
+ state.OnBeginImplFrameDeadline();
+ EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE,
+ state.begin_impl_frame_state());
EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction());
- state.OnBeginFrameIdle();
- EXPECT_EQ(SchedulerStateMachine::BEGIN_FRAME_STATE_IDLE,
- state.begin_frame_state());
+ state.OnBeginImplFrameIdle();
+ EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE,
+ state.begin_impl_frame_state());
EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction());
- state.OnBeginFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_EQ(SchedulerStateMachine::BEGIN_FRAME_STATE_BEGIN_FRAME_STARTING,
- state.begin_frame_state());
+ state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
+ EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING,
+ state.begin_impl_frame_state());
EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction());
- // Commit and make sure we draw on next BeginFrame
+ // Commit and make sure we draw on next BeginImplFrame
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- state.OnBeginFrameDeadline();
+ state.OnBeginImplFrameDeadline();
EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW,
state.CommitState());
EXPECT_ACTION_UPDATE_STATE(
@@ -629,7 +719,7 @@ TEST(SchedulerStateMachineTest, TestsetNeedsCommitIsNotLost) {
// Verify that another commit will start immediately after draw.
EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD);
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
}
@@ -646,9 +736,9 @@ TEST(SchedulerStateMachineTest, TestFullCycle) {
state.SetNeedsCommit();
// Begin the frame.
- state.OnBeginFrame(BeginFrameArgs::CreateForTesting());
+ state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD);
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS,
state.CommitState());
EXPECT_FALSE(state.NeedsCommit());
@@ -665,11 +755,11 @@ TEST(SchedulerStateMachineTest, TestFullCycle) {
state.CommitState());
EXPECT_TRUE(state.needs_redraw());
- // Expect to do nothing until BeginFrame deadline
+ // Expect to do nothing until BeginImplFrame deadline
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- // At BeginFrame deadline, draw.
- state.OnBeginFrameDeadline();
+ // At BeginImplFrame deadline, draw.
+ state.OnBeginImplFrameDeadline();
EXPECT_ACTION_UPDATE_STATE(
SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
state.DidDrawIfPossibleCompleted(true);
@@ -693,9 +783,9 @@ TEST(SchedulerStateMachineTest, TestFullCycleWithCommitRequestInbetween) {
state.SetNeedsCommit();
// Begin the frame.
- state.OnBeginFrame(BeginFrameArgs::CreateForTesting());
+ state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD);
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS,
state.CommitState());
EXPECT_FALSE(state.NeedsCommit());
@@ -716,11 +806,11 @@ TEST(SchedulerStateMachineTest, TestFullCycleWithCommitRequestInbetween) {
state.CommitState());
EXPECT_TRUE(state.needs_redraw());
- // Expect to do nothing until BeginFrame deadline.
+ // Expect to do nothing until BeginImplFrame deadline.
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- // At BeginFrame deadline, draw.
- state.OnBeginFrameDeadline();
+ // At BeginImplFrame deadline, draw.
+ state.OnBeginImplFrameDeadline();
EXPECT_ACTION_UPDATE_STATE(
SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
state.DidDrawIfPossibleCompleted(true);
@@ -730,10 +820,10 @@ TEST(SchedulerStateMachineTest, TestFullCycleWithCommitRequestInbetween) {
EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState());
EXPECT_FALSE(state.needs_redraw());
- // Next BeginFrame should initiate second commit.
- state.OnBeginFrame(BeginFrameArgs::CreateForTesting());
+ // Next BeginImplFrame should initiate second commit.
+ state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD);
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
}
TEST(SchedulerStateMachineTest, TestRequestCommitInvisible) {
@@ -759,39 +849,39 @@ TEST(SchedulerStateMachineTest, TestGoesInvisibleBeforeFinishCommit) {
state.SetNeedsCommit();
// Begin the frame while visible.
- state.OnBeginFrame(BeginFrameArgs::CreateForTesting());
+ state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD);
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS,
state.CommitState());
EXPECT_FALSE(state.NeedsCommit());
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- // Become invisible and abort the main thread's begin frame.
+ // Become invisible and abort BeginMainFrame.
state.SetVisible(false);
- state.BeginFrameAbortedByMainThread(false);
+ state.BeginMainFrameAborted(false);
// We should now be back in the idle state as if we never started the frame.
EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState());
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- // We shouldn't do anything on the BeginFrame deadline.
- state.OnBeginFrameDeadline();
+ // We shouldn't do anything on the BeginImplFrame deadline.
+ state.OnBeginImplFrameDeadline();
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
// Become visible again.
state.SetVisible(true);
// Although we have aborted on this frame and haven't cancelled the commit
- // (i.e. need another), don't send another begin frame yet.
+ // (i.e. need another), don't send another BeginMainFrame yet.
EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState());
EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
EXPECT_TRUE(state.NeedsCommit());
// Start a new frame.
- state.OnBeginFrame(BeginFrameArgs::CreateForTesting());
+ state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD);
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
// We should be starting the commit now.
EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS,
@@ -799,7 +889,7 @@ TEST(SchedulerStateMachineTest, TestGoesInvisibleBeforeFinishCommit) {
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
}
-TEST(SchedulerStateMachineTest, AbortBeginFrameAndCancelCommit) {
+TEST(SchedulerStateMachineTest, AbortBeginMainFrameAndCancelCommit) {
SchedulerSettings default_scheduler_settings;
StateMachine state(default_scheduler_settings);
state.SetCanStart();
@@ -812,14 +902,14 @@ TEST(SchedulerStateMachineTest, AbortBeginFrameAndCancelCommit) {
state.SetNeedsCommit();
EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD);
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS,
state.CommitState());
EXPECT_FALSE(state.NeedsCommit());
EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
// Abort the commit, cancelling future commits.
- state.BeginFrameAbortedByMainThread(true);
+ state.BeginMainFrameAborted(true);
// Verify that another commit doesn't start on the same frame.
EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState());
@@ -828,9 +918,9 @@ TEST(SchedulerStateMachineTest, AbortBeginFrameAndCancelCommit) {
// Start a new frame; draw because this is the first frame since output
// surface init'd.
- state.OnBeginFrame(BeginFrameArgs::CreateForTesting());
+ state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- state.OnBeginFrameDeadline();
+ state.OnBeginImplFrameDeadline();
EXPECT_ACTION_UPDATE_STATE(
SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
@@ -842,7 +932,7 @@ TEST(SchedulerStateMachineTest, AbortBeginFrameAndCancelCommit) {
// Verify another commit can start if requested, though.
state.SetNeedsCommit();
EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState());
- EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD,
+ EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME,
state.NextAction());
}
@@ -859,16 +949,16 @@ TEST(SchedulerStateMachineTest, TestFirstContextCreation) {
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
// Check that the first init does not SetNeedsCommit.
- state.OnBeginFrame(BeginFrameArgs::CreateForTesting());
+ state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- state.OnBeginFrameDeadline();
+ state.OnBeginImplFrameDeadline();
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- // Check that a needs commit initiates a BeginFrame to the main thread.
+ // Check that a needs commit initiates a BeginMainFrame.
state.SetNeedsCommit();
- state.OnBeginFrame(BeginFrameArgs::CreateForTesting());
+ state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD);
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
}
TEST(SchedulerStateMachineTest, TestContextLostWhenCompletelyIdle) {
@@ -896,9 +986,9 @@ TEST(SchedulerStateMachineTest, TestContextLostWhenCompletelyIdle) {
state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
// When the context is recreated, we should begin a commit.
- state.OnBeginFrame(BeginFrameArgs::CreateForTesting());
+ state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD);
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
}
TEST(SchedulerStateMachineTest,
@@ -920,16 +1010,16 @@ TEST(SchedulerStateMachineTest,
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
// Once context recreation begins, nothing should happen.
- state.OnBeginFrame(BeginFrameArgs::CreateForTesting());
+ state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- state.OnBeginFrameDeadline();
+ state.OnBeginImplFrameDeadline();
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
// While context is recreating, commits shouldn't begin.
state.SetNeedsCommit();
- state.OnBeginFrame(BeginFrameArgs::CreateForTesting());
+ state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- state.OnBeginFrameDeadline();
+ state.OnBeginImplFrameDeadline();
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
// Recreate the context
@@ -938,7 +1028,7 @@ TEST(SchedulerStateMachineTest,
// When the context is recreated, we should begin a commit
EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD);
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS,
state.CommitState());
@@ -951,9 +1041,9 @@ TEST(SchedulerStateMachineTest,
// Once the context is recreated, whether we draw should be based on
// SetCanDraw.
- state.OnBeginFrame(BeginFrameArgs::CreateForTesting());
+ state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- state.OnBeginFrameDeadline();
+ state.OnBeginImplFrameDeadline();
EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE,
state.NextAction());
state.SetCanDraw(false);
@@ -978,24 +1068,23 @@ void TestContextLostWhileCommitInProgress(bool deadline_scheduling_enabled) {
state.SetNeedsCommit();
if (!deadline_scheduling_enabled) {
EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD);
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
}
// Set damage and expect a draw.
state.SetNeedsRedraw(true);
- state.OnBeginFrame(BeginFrameArgs::CreateForTesting());
+ state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
if (deadline_scheduling_enabled) {
EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD);
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
}
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- state.OnBeginFrameDeadline();
+ state.OnBeginImplFrameDeadline();
EXPECT_ACTION_UPDATE_STATE(
SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- // Cause a lost context while the begin frame is in flight
- // for the main thread.
+ // Cause a lost context while the BeginMainFrame is in flight.
state.DidLoseOutputSurface();
// Ask for another draw. Expect nothing happens.
@@ -1013,27 +1102,27 @@ void TestContextLostWhileCommitInProgress(bool deadline_scheduling_enabled) {
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT);
// Expect to be told to begin context recreation, independent of
- // BeginFrame state.
- EXPECT_EQ(SchedulerStateMachine::BEGIN_FRAME_STATE_IDLE,
- state.begin_frame_state());
+ // BeginImplFrame state.
+ EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE,
+ state.begin_impl_frame_state());
EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION,
state.NextAction());
- state.OnBeginFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_EQ(SchedulerStateMachine::BEGIN_FRAME_STATE_BEGIN_FRAME_STARTING,
- state.begin_frame_state());
+ state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
+ EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING,
+ state.begin_impl_frame_state());
EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION,
state.NextAction());
- state.OnBeginFrameDeadlinePending();
- EXPECT_EQ(SchedulerStateMachine::BEGIN_FRAME_STATE_INSIDE_BEGIN_FRAME,
- state.begin_frame_state());
+ state.OnBeginImplFrameDeadlinePending();
+ EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME,
+ state.begin_impl_frame_state());
EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION,
state.NextAction());
- state.OnBeginFrameDeadline();
- EXPECT_EQ(SchedulerStateMachine::BEGIN_FRAME_STATE_INSIDE_DEADLINE,
- state.begin_frame_state());
+ state.OnBeginImplFrameDeadline();
+ EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE,
+ state.begin_impl_frame_state());
EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION,
state.NextAction());
}
@@ -1063,25 +1152,24 @@ void TestContextLostWhileCommitInProgressAndAnotherCommitRequested(
state.SetNeedsCommit();
if (!deadline_scheduling_enabled) {
EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD);
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
}
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
// Set damage and expect a draw.
state.SetNeedsRedraw(true);
- state.OnBeginFrame(BeginFrameArgs::CreateForTesting());
+ state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
if (deadline_scheduling_enabled) {
EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD);
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
}
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- state.OnBeginFrameDeadline();
+ state.OnBeginImplFrameDeadline();
EXPECT_ACTION_UPDATE_STATE(
SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- // Cause a lost context while the begin frame is in flight
- // for the main thread.
+ // Cause a lost context while the BeginMainFrame is in flight.
state.DidLoseOutputSurface();
// Ask for another draw and also set needs commit. Expect nothing happens.
@@ -1099,27 +1187,27 @@ void TestContextLostWhileCommitInProgressAndAnotherCommitRequested(
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT);
// Expect to be told to begin context recreation, independent of
- // BeginFrame state
- EXPECT_EQ(SchedulerStateMachine::BEGIN_FRAME_STATE_IDLE,
- state.begin_frame_state());
+ // BeginImplFrame state
+ EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE,
+ state.begin_impl_frame_state());
EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION,
state.NextAction());
- state.OnBeginFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_EQ(SchedulerStateMachine::BEGIN_FRAME_STATE_BEGIN_FRAME_STARTING,
- state.begin_frame_state());
+ state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
+ EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING,
+ state.begin_impl_frame_state());
EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION,
state.NextAction());
- state.OnBeginFrameDeadlinePending();
- EXPECT_EQ(SchedulerStateMachine::BEGIN_FRAME_STATE_INSIDE_BEGIN_FRAME,
- state.begin_frame_state());
+ state.OnBeginImplFrameDeadlinePending();
+ EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME,
+ state.begin_impl_frame_state());
EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION,
state.NextAction());
- state.OnBeginFrameDeadline();
- EXPECT_EQ(SchedulerStateMachine::BEGIN_FRAME_STATE_INSIDE_DEADLINE,
- state.begin_frame_state());
+ state.OnBeginImplFrameDeadline();
+ EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE,
+ state.begin_impl_frame_state());
EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION,
state.NextAction());
@@ -1127,15 +1215,15 @@ void TestContextLostWhileCommitInProgressAndAnotherCommitRequested(
EXPECT_ACTION_UPDATE_STATE(
SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION);
state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
- state.OnBeginFrameIdle();
- state.OnBeginFrame(BeginFrameArgs::CreateForTesting());
+ state.OnBeginImplFrameIdle();
+ state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD);
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
state.FinishCommit();
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- state.OnBeginFrameDeadline();
+ state.OnBeginImplFrameDeadline();
EXPECT_ACTION_UPDATE_STATE(
SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
@@ -1171,7 +1259,7 @@ TEST(SchedulerStateMachineTest, TestFinishAllRenderingWhileContextLost) {
state.SetCommitState(
SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW);
state.SetNeedsForcedRedrawForReadback();
- state.OnBeginFrame(BeginFrameArgs::CreateForTesting());
+ state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_READBACK);
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
@@ -1186,12 +1274,12 @@ TEST(SchedulerStateMachineTest, TestFinishAllRenderingWhileContextLost) {
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT);
// Expect to be told to begin context recreation, independent of
- // BeginFrame state
+ // BeginImplFrame state
EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState());
EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION,
state.NextAction());
- state.OnBeginFrameDeadline();
+ state.OnBeginImplFrameDeadline();
EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION,
state.NextAction());
@@ -1222,13 +1310,13 @@ TEST(SchedulerStateMachineTest, DontDrawBeforeCommitAfterLostOutputSurface) {
state.DidCreateAndInitializeOutputSurface();
EXPECT_FALSE(state.RedrawPending());
- state.OnBeginFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD,
+ state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
+ EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME,
state.NextAction());
}
TEST(SchedulerStateMachineTest,
- TestSendBeginFrameToMainThreadWhenInvisibleAndForceCommit) {
+ TestSendBeginMainFrameWhenInvisibleAndForceCommit) {
SchedulerSettings default_scheduler_settings;
StateMachine state(default_scheduler_settings);
state.SetCanStart();
@@ -1237,19 +1325,19 @@ TEST(SchedulerStateMachineTest,
state.SetVisible(false);
state.SetNeedsCommit();
state.SetNeedsForcedCommitForReadback();
- EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD,
+ EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME,
state.NextAction());
}
TEST(SchedulerStateMachineTest,
- TestSendBeginFrameToMainThreadWhenCanStartFalseAndForceCommit) {
+ TestSendBeginMainFrameWhenCanStartFalseAndForceCommit) {
SchedulerSettings default_scheduler_settings;
StateMachine state(default_scheduler_settings);
state.SetVisible(true);
state.SetCanDraw(true);
state.SetNeedsCommit();
state.SetNeedsForcedCommitForReadback();
- EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD,
+ EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME,
state.NextAction());
}
@@ -1292,8 +1380,8 @@ TEST(SchedulerStateMachineTest, TestFinishCommitWhenForcedCommitInProgress) {
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_READBACK);
// When the readback interrupts the normal commit, we should not get
- // another BeginFrame on the impl thread when the readback completes.
- EXPECT_NE(SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD,
+ // another BeginMainFrame when the readback completes.
+ EXPECT_NE(SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME,
state.NextAction());
// The normal commit can then proceed.
@@ -1321,19 +1409,19 @@ TEST(SchedulerStateMachineTest, TestInitialActionsWhenContextLost) {
EXPECT_EQ(state.output_surface_state(),
SchedulerStateMachine::OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT);
- // We should not send a BeginFrame to them main thread when we are invisible,
- // even if we've lost the output surface and are trying to get the first
- // commit, since the main thread will just abort anyway.
+ // We should not send a BeginMainFrame when we are invisible, even if we've
+ // lost the output surface and are trying to get the first commit, since the
+ // main thread will just abort anyway.
state.SetVisible(false);
- EXPECT_EQ(SchedulerStateMachine::ACTION_NONE,
- state.NextAction()) << *state.AsValue();
+ EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction())
+ << *state.AsValue();
// If there is a forced commit, however, we could be blocking a readback
// on the main thread, so we need to unblock it before we can get our
// output surface, even if we are not visible.
state.SetNeedsForcedCommitForReadback();
- EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD,
- state.NextAction())
+ EXPECT_EQ(
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME, state.NextAction())
<< *state.AsValue();
}
@@ -1350,7 +1438,7 @@ TEST(SchedulerStateMachineTest, TestImmediateFinishCommit) {
state.SetNeedsCommit();
state.SetNeedsForcedCommitForReadback();
EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD);
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
state.FinishCommit();
EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT,
@@ -1365,7 +1453,7 @@ TEST(SchedulerStateMachineTest, TestImmediateFinishCommit) {
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- // Should be waiting for the normal begin frame from the main thread.
+ // Should be waiting for the normal BeginMainFrame.
EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS,
state.CommitState());
}
@@ -1384,7 +1472,7 @@ void TestImmediateFinishCommitDuringCommit(bool deadline_scheduling_enabled) {
state.SetNeedsCommit();
if (!deadline_scheduling_enabled) {
EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD);
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
}
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
@@ -1392,7 +1480,7 @@ void TestImmediateFinishCommitDuringCommit(bool deadline_scheduling_enabled) {
state.SetNeedsForcedCommitForReadback();
if (deadline_scheduling_enabled) {
EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD);
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
}
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
state.FinishCommit();
@@ -1407,14 +1495,13 @@ void TestImmediateFinishCommitDuringCommit(bool deadline_scheduling_enabled) {
state.DidDrawIfPossibleCompleted(true);
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- // Should be waiting for the normal begin frame from the main thread.
+ // Should be waiting for the normal BeginMainFrame.
EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS,
state.CommitState())
<< *state.AsValue();
}
-TEST(SchedulerStateMachineTest,
- TestImmediateFinishCommitDuringCommit) {
+TEST(SchedulerStateMachineTest, TestImmediateFinishCommitDuringCommit) {
bool deadline_scheduling_enabled = false;
TestImmediateFinishCommitDuringCommit(deadline_scheduling_enabled);
}
@@ -1425,7 +1512,7 @@ TEST(SchedulerStateMachineTest,
TestImmediateFinishCommitDuringCommit(deadline_scheduling_enabled);
}
-void ImmediateBeginFrameAbortedByMainThreadWhileInvisible(
+void ImmediateBeginMainFrameAbortedWhileInvisible(
bool deadline_scheduling_enabled) {
SchedulerSettings scheduler_settings;
scheduler_settings.deadline_scheduling_enabled = deadline_scheduling_enabled;
@@ -1439,7 +1526,7 @@ void ImmediateBeginFrameAbortedByMainThreadWhileInvisible(
state.SetNeedsCommit();
if (!deadline_scheduling_enabled) {
EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD);
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
}
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
@@ -1447,7 +1534,7 @@ void ImmediateBeginFrameAbortedByMainThreadWhileInvisible(
state.SetNeedsForcedCommitForReadback();
if (deadline_scheduling_enabled) {
EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD);
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
}
state.FinishCommit();
@@ -1462,14 +1549,14 @@ void ImmediateBeginFrameAbortedByMainThreadWhileInvisible(
state.DidDrawIfPossibleCompleted(true);
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
- // Should be waiting for the main thread's begin frame.
+ // Should be waiting for BeginMainFrame.
EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS,
state.CommitState())
<< *state.AsValue();
- // Become invisible and abort the main thread's begin frame.
+ // Become invisible and abort BeginMainFrame.
state.SetVisible(false);
- state.BeginFrameAbortedByMainThread(false);
+ state.BeginMainFrameAborted(false);
// Should be back in the idle state, but needing a commit.
EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState());
@@ -1477,16 +1564,16 @@ void ImmediateBeginFrameAbortedByMainThreadWhileInvisible(
}
TEST(SchedulerStateMachineTest,
- ImmediateBeginFrameAbortedByMainThreadWhileInvisible) {
+ ImmediateBeginMainFrameAbortedWhileInvisible) {
bool deadline_scheduling_enabled = false;
- ImmediateBeginFrameAbortedByMainThreadWhileInvisible(
+ ImmediateBeginMainFrameAbortedWhileInvisible(
deadline_scheduling_enabled);
}
TEST(SchedulerStateMachineTest,
- ImmediateBeginFrameAbortedByMainThreadWhileInvisible_Deadline) {
+ ImmediateBeginMainFrameAbortedWhileInvisible_Deadline) {
bool deadline_scheduling_enabled = true;
- ImmediateBeginFrameAbortedByMainThreadWhileInvisible(
+ ImmediateBeginMainFrameAbortedWhileInvisible(
deadline_scheduling_enabled);
}
@@ -1564,9 +1651,9 @@ TEST(SchedulerStateMachineTest, ReportIfNotDrawingFromAcquiredTextures) {
EXPECT_TRUE(state.PendingActivationsShouldBeForced());
state.SetNeedsCommit();
- state.OnBeginFrame(BeginFrameArgs::CreateForTesting());
+ state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD);
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
EXPECT_TRUE(state.PendingDrawsShouldBeAborted());
EXPECT_TRUE(state.PendingActivationsShouldBeForced());
@@ -1600,14 +1687,14 @@ TEST(SchedulerStateMachineTest, AcquireTexturesWithAbort) {
EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
state.SetNeedsCommit();
- EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD,
+ EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME,
state.NextAction());
state.UpdateState(state.NextAction());
EXPECT_TRUE(state.PendingDrawsShouldBeAborted());
EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
- state.BeginFrameAbortedByMainThread(true);
+ state.BeginMainFrameAborted(true);
EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
EXPECT_FALSE(state.PendingDrawsShouldBeAborted());
@@ -1627,7 +1714,7 @@ TEST(SchedulerStateMachineTest,
// This test mirrors what happens during the first frame of a scroll gesture.
// First we get the input event and a BeginFrame.
- state.OnBeginFrame(BeginFrameArgs::CreateForTesting());
+ state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
// As a response the compositor requests a redraw and a commit to tell the
// main thread about the new scroll offset.
@@ -1636,16 +1723,16 @@ TEST(SchedulerStateMachineTest,
// We should start the commit normally.
EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD);
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
// Since only the scroll offset changed, the main thread will abort the
// commit.
- state.BeginFrameAbortedByMainThread(true);
+ state.BeginMainFrameAborted(true);
// Since the commit was aborted, we should draw right away instead of waiting
// for the deadline.
- EXPECT_TRUE(state.ShouldTriggerBeginFrameDeadlineEarly());
+ EXPECT_TRUE(state.ShouldTriggerBeginImplFrameDeadlineEarly());
}
TEST(SchedulerStateMachineTest, TestTriggerDeadlineEarlyForSmoothness) {
@@ -1661,17 +1748,17 @@ TEST(SchedulerStateMachineTest, TestTriggerDeadlineEarlyForSmoothness) {
// This test ensures that impl-draws are prioritized over main thread updates
// in prefer smoothness mode.
- state.OnBeginFrame(BeginFrameArgs::CreateForTesting());
+ state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
state.SetNeedsRedraw(true);
state.SetNeedsCommit();
EXPECT_ACTION_UPDATE_STATE(
- SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD);
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
// The deadline is not triggered early until we enter prefer smoothness mode.
- EXPECT_FALSE(state.ShouldTriggerBeginFrameDeadlineEarly());
+ EXPECT_FALSE(state.ShouldTriggerBeginImplFrameDeadlineEarly());
state.SetSmoothnessTakesPriority(true);
- EXPECT_TRUE(state.ShouldTriggerBeginFrameDeadlineEarly());
+ EXPECT_TRUE(state.ShouldTriggerBeginImplFrameDeadlineEarly());
}
} // namespace
diff --git a/chromium/cc/scheduler/scheduler_unittest.cc b/chromium/cc/scheduler/scheduler_unittest.cc
index a1da822cff1..6f5eb2c2dcd 100644
--- a/chromium/cc/scheduler/scheduler_unittest.cc
+++ b/chromium/cc/scheduler/scheduler_unittest.cc
@@ -8,6 +8,9 @@
#include "base/logging.h"
#include "base/memory/scoped_vector.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "base/time/time.h"
#include "cc/test/scheduler_test_common.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -33,17 +36,18 @@ void InitializeOutputSurfaceAndFirstCommit(Scheduler* scheduler) {
scheduler->SetNeedsCommit();
scheduler->FinishCommit();
// Go through the motions to draw the commit.
- scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
- scheduler->OnBeginFrameDeadline();
- // We need another BeginFrame so Scheduler calls SetNeedsBeginFrame(false).
- scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
- scheduler->OnBeginFrameDeadline();
+ scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
+ scheduler->OnBeginImplFrameDeadline();
+ // We need another BeginImplFrame so Scheduler calls
+ // SetNeedsBeginImplFrame(false).
+ scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
+ scheduler->OnBeginImplFrameDeadline();
}
class FakeSchedulerClient : public SchedulerClient {
public:
FakeSchedulerClient()
- : needs_begin_frame_(false) {
+ : needs_begin_impl_frame_(false) {
Reset();
}
@@ -53,14 +57,20 @@ class FakeSchedulerClient : public SchedulerClient {
draw_will_happen_ = true;
swap_will_happen_if_draw_happens_ = true;
num_draws_ = 0;
+ log_anticipated_draw_time_change_ = false;
}
Scheduler* CreateScheduler(const SchedulerSettings& settings) {
- scheduler_ = Scheduler::Create(this, settings);
+ scheduler_ = Scheduler::Create(this, settings, 0);
return scheduler_.get();
}
- bool needs_begin_frame() { return needs_begin_frame_; }
+ // Most tests don't care about DidAnticipatedDrawTimeChange, so only record it
+ // for tests that do.
+ void set_log_anticipated_draw_time_change(bool log) {
+ log_anticipated_draw_time_change_ = log;
+ }
+ bool needs_begin_impl_frame() { return needs_begin_impl_frame_; }
int num_draws() const { return num_draws_; }
int num_actions_() const { return static_cast<int>(actions_.size()); }
const char* Action(int i) const { return actions_[i]; }
@@ -84,14 +94,14 @@ class FakeSchedulerClient : public SchedulerClient {
swap_will_happen_if_draw_happens_ = swap_will_happen_if_draw_happens;
}
- // Scheduler Implementation.
- virtual void SetNeedsBeginFrameOnImplThread(bool enable) OVERRIDE {
- actions_.push_back("SetNeedsBeginFrameOnImplThread");
+ // SchedulerClient implementation.
+ virtual void SetNeedsBeginImplFrame(bool enable) OVERRIDE {
+ actions_.push_back("SetNeedsBeginImplFrame");
states_.push_back(scheduler_->StateAsValue().release());
- needs_begin_frame_ = enable;
+ needs_begin_impl_frame_ = enable;
}
- virtual void ScheduledActionSendBeginFrameToMainThread() OVERRIDE {
- actions_.push_back("ScheduledActionSendBeginFrameToMainThread");
+ virtual void ScheduledActionSendBeginMainFrame() OVERRIDE {
+ actions_.push_back("ScheduledActionSendBeginMainFrame");
states_.push_back(scheduler_->StateAsValue().release());
}
virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapIfPossible()
@@ -145,36 +155,40 @@ class FakeSchedulerClient : public SchedulerClient {
actions_.push_back("ScheduledActionManageTiles");
states_.push_back(scheduler_->StateAsValue().release());
}
- virtual void DidAnticipatedDrawTimeChange(base::TimeTicks) OVERRIDE {}
+ virtual void DidAnticipatedDrawTimeChange(base::TimeTicks) OVERRIDE {
+ if (log_anticipated_draw_time_change_)
+ actions_.push_back("DidAnticipatedDrawTimeChange");
+ }
virtual base::TimeDelta DrawDurationEstimate() OVERRIDE {
return base::TimeDelta();
}
- virtual base::TimeDelta BeginFrameToCommitDurationEstimate() OVERRIDE {
+ virtual base::TimeDelta BeginMainFrameToCommitDurationEstimate() OVERRIDE {
return base::TimeDelta();
}
virtual base::TimeDelta CommitToActivateDurationEstimate() OVERRIDE {
return base::TimeDelta();
}
- virtual void PostBeginFrameDeadline(const base::Closure& closure,
- base::TimeTicks deadline) OVERRIDE {
- actions_.push_back("PostBeginFrameDeadlineTask");
+ virtual void PostBeginImplFrameDeadline(const base::Closure& closure,
+ base::TimeTicks deadline) OVERRIDE {
+ actions_.push_back("PostBeginImplFrameDeadlineTask");
states_.push_back(scheduler_->StateAsValue().release());
}
- virtual void DidBeginFrameDeadlineOnImplThread() OVERRIDE {}
+ virtual void DidBeginImplFrameDeadline() OVERRIDE {}
protected:
- bool needs_begin_frame_;
+ bool needs_begin_impl_frame_;
bool draw_will_happen_;
bool swap_will_happen_if_draw_happens_;
int num_draws_;
+ bool log_anticipated_draw_time_change_;
std::vector<const char*> actions_;
ScopedVector<base::Value> states_;
scoped_ptr<Scheduler> scheduler_;
};
-TEST(SchedulerTest, InitializeOutputSurfaceDoesNotBeginFrame) {
+TEST(SchedulerTest, InitializeOutputSurfaceDoesNotBeginImplFrame) {
FakeSchedulerClient client;
SchedulerSettings default_scheduler_settings;
Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
@@ -200,63 +214,64 @@ void RequestCommit(bool deadline_scheduling_enabled) {
EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
InitializeOutputSurfaceAndFirstCommit(scheduler);
- // SetNeedsCommit should begin the frame on the next BeginFrame.
+ // SetNeedsCommit should begin the frame on the next BeginImplFrame.
client.Reset();
scheduler->SetNeedsCommit();
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(client.needs_begin_impl_frame());
if (deadline_scheduling_enabled) {
- EXPECT_SINGLE_ACTION("SetNeedsBeginFrameOnImplThread", client);
+ EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
} else {
EXPECT_EQ(client.num_actions_(), 2);
- EXPECT_TRUE(client.HasAction("ScheduledActionSendBeginFrameToMainThread"));
- EXPECT_TRUE(client.HasAction("SetNeedsBeginFrameOnImplThread"));
+ EXPECT_TRUE(client.HasAction("ScheduledActionSendBeginMainFrame"));
+ EXPECT_TRUE(client.HasAction("SetNeedsBeginImplFrame"));
}
client.Reset();
- scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
+ scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
if (deadline_scheduling_enabled) {
- EXPECT_ACTION("ScheduledActionSendBeginFrameToMainThread", client, 0, 2);
- EXPECT_ACTION("PostBeginFrameDeadlineTask", client, 1, 2);
+ EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 0, 2);
+ EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client, 1, 2);
} else {
- EXPECT_SINGLE_ACTION("PostBeginFrameDeadlineTask", client);
+ EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
}
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(client.needs_begin_impl_frame());
client.Reset();
- // If we don't swap on the deadline, we need to request another BeginFrame.
- scheduler->OnBeginFrameDeadline();
- EXPECT_SINGLE_ACTION("SetNeedsBeginFrameOnImplThread", client);
- EXPECT_TRUE(client.needs_begin_frame());
+ // If we don't swap on the deadline, we need to request another
+ // BeginImplFrame.
+ scheduler->OnBeginImplFrameDeadline();
+ EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
+ EXPECT_TRUE(client.needs_begin_impl_frame());
client.Reset();
// FinishCommit should commit
scheduler->FinishCommit();
EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(client.needs_begin_impl_frame());
client.Reset();
- // BeginFrame should prepare the draw.
- scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_SINGLE_ACTION("PostBeginFrameDeadlineTask", client);
- EXPECT_TRUE(client.needs_begin_frame());
+ // BeginImplFrame should prepare the draw.
+ scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
+ EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
+ EXPECT_TRUE(client.needs_begin_impl_frame());
client.Reset();
- // BeginFrame deadline should draw.
- scheduler->OnBeginFrameDeadline();
+ // BeginImplFrame deadline should draw.
+ scheduler->OnBeginImplFrameDeadline();
EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 2);
- EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client, 1, 2);
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_ACTION("SetNeedsBeginImplFrame", client, 1, 2);
+ EXPECT_TRUE(client.needs_begin_impl_frame());
client.Reset();
- // The following BeginFrame deadline should SetNeedsBeginFrame(false) to avoid
- // excessive toggles.
- scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_SINGLE_ACTION("PostBeginFrameDeadlineTask", client);
+ // The following BeginImplFrame deadline should SetNeedsBeginImplFrame(false)
+ // to avoid excessive toggles.
+ scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
+ EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
client.Reset();
- scheduler->OnBeginFrameDeadline();
- EXPECT_SINGLE_ACTION("SetNeedsBeginFrameOnImplThread", client);
- EXPECT_FALSE(client.needs_begin_frame());
+ scheduler->OnBeginImplFrameDeadline();
+ EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
+ EXPECT_FALSE(client.needs_begin_impl_frame());
client.Reset();
}
@@ -270,7 +285,7 @@ TEST(SchedulerTest, RequestCommit_Deadline) {
RequestCommit(deadline_scheduling_enabled);
}
-void RequestCommitAfterBeginFrameSentToMainThread(
+void RequestCommitAfterBeginMainFrameSent(
bool deadline_scheduling_enabled) {
FakeSchedulerClient client;
SchedulerSettings scheduler_settings;
@@ -287,24 +302,24 @@ void RequestCommitAfterBeginFrameSentToMainThread(
// SetNeedsCommit should begin the frame.
scheduler->SetNeedsCommit();
if (deadline_scheduling_enabled) {
- EXPECT_SINGLE_ACTION("SetNeedsBeginFrameOnImplThread", client);
+ EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
} else {
EXPECT_EQ(client.num_actions_(), 2);
- EXPECT_TRUE(client.HasAction("SetNeedsBeginFrameOnImplThread"));
- EXPECT_TRUE(client.HasAction("ScheduledActionSendBeginFrameToMainThread"));
+ EXPECT_TRUE(client.HasAction("SetNeedsBeginImplFrame"));
+ EXPECT_TRUE(client.HasAction("ScheduledActionSendBeginMainFrame"));
}
client.Reset();
- scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
+ scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
if (deadline_scheduling_enabled) {
EXPECT_EQ(client.num_actions_(), 2);
- EXPECT_TRUE(client.HasAction("ScheduledActionSendBeginFrameToMainThread"));
- EXPECT_TRUE(client.HasAction("PostBeginFrameDeadlineTask"));
+ EXPECT_TRUE(client.HasAction("ScheduledActionSendBeginMainFrame"));
+ EXPECT_TRUE(client.HasAction("PostBeginImplFrameDeadlineTask"));
} else {
- EXPECT_SINGLE_ACTION("PostBeginFrameDeadlineTask", client);
+ EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
}
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(client.needs_begin_impl_frame());
client.Reset();
// Now SetNeedsCommit again. Calling here means we need a second commit.
@@ -315,32 +330,32 @@ void RequestCommitAfterBeginFrameSentToMainThread(
// Finish the first commit.
scheduler->FinishCommit();
EXPECT_ACTION("ScheduledActionCommit", client, 0, 2);
- EXPECT_ACTION("PostBeginFrameDeadlineTask", client, 1, 2);
+ EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client, 1, 2);
client.Reset();
- scheduler->OnBeginFrameDeadline();
+ scheduler->OnBeginImplFrameDeadline();
if (deadline_scheduling_enabled) {
EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 2);
- EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client, 1, 2);
+ EXPECT_ACTION("SetNeedsBeginImplFrame", client, 1, 2);
} else {
EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 3);
- EXPECT_ACTION("ScheduledActionSendBeginFrameToMainThread", client, 1, 3);
- EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client, 2, 3);
+ EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 3);
+ EXPECT_ACTION("SetNeedsBeginImplFrame", client, 2, 3);
}
// Because we just swapped, the Scheduler should also request the next
- // BeginFrame from the OutputSurface.
- EXPECT_TRUE(client.needs_begin_frame());
+ // BeginImplFrame from the OutputSurface.
+ EXPECT_TRUE(client.needs_begin_impl_frame());
client.Reset();
- // Since another commit is needed, the next BeginFrame should initiate
+ // Since another commit is needed, the next BeginImplFrame should initiate
// the second commit.
- scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
+ scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
if (deadline_scheduling_enabled) {
EXPECT_EQ(client.num_actions_(), 2);
- EXPECT_TRUE(client.HasAction("ScheduledActionSendBeginFrameToMainThread"));
- EXPECT_TRUE(client.HasAction("PostBeginFrameDeadlineTask"));
+ EXPECT_TRUE(client.HasAction("ScheduledActionSendBeginMainFrame"));
+ EXPECT_TRUE(client.HasAction("PostBeginImplFrameDeadlineTask"));
} else {
- EXPECT_SINGLE_ACTION("PostBeginFrameDeadlineTask", client);
+ EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
}
client.Reset();
@@ -348,30 +363,30 @@ void RequestCommitAfterBeginFrameSentToMainThread(
// to trigger the deadline early.
scheduler->FinishCommit();
EXPECT_ACTION("ScheduledActionCommit", client, 0, 2);
- EXPECT_ACTION("PostBeginFrameDeadlineTask", client, 1, 2);
+ EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client, 1, 2);
client.Reset();
- scheduler->OnBeginFrameDeadline();
+ scheduler->OnBeginImplFrameDeadline();
EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 2);
- EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client, 1, 2);
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_ACTION("SetNeedsBeginImplFrame", client, 1, 2);
+ EXPECT_TRUE(client.needs_begin_impl_frame());
client.Reset();
- // On the next BeginFrame, verify we go back to a quiescent state and
- // no longer request BeginFrames.
- scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
- scheduler->OnBeginFrameDeadline();
- EXPECT_FALSE(client.needs_begin_frame());
+ // On the next BeginImplFrame, verify we go back to a quiescent state and
+ // no longer request BeginImplFrames.
+ scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
+ scheduler->OnBeginImplFrameDeadline();
+ EXPECT_FALSE(client.needs_begin_impl_frame());
client.Reset();
}
-TEST(SchedulerTest, RequestCommitAfterBeginFrameSentToMainThread) {
+TEST(SchedulerTest, RequestCommitAfterBeginMainFrameSent) {
bool deadline_scheduling_enabled = false;
- RequestCommitAfterBeginFrameSentToMainThread(deadline_scheduling_enabled);
+ RequestCommitAfterBeginMainFrameSent(deadline_scheduling_enabled);
}
-TEST(SchedulerTest, RequestCommitAfterBeginFrameSentToMainThread_Deadline) {
+TEST(SchedulerTest, RequestCommitAfterBeginMainFrameSent_Deadline) {
bool deadline_scheduling_enabled = true;
- RequestCommitAfterBeginFrameSentToMainThread(deadline_scheduling_enabled);
+ RequestCommitAfterBeginMainFrameSent(deadline_scheduling_enabled);
}
void TextureAcquisitionCausesCommitInsteadOfDraw(
@@ -389,90 +404,90 @@ void TextureAcquisitionCausesCommitInsteadOfDraw(
client.Reset();
scheduler->SetNeedsRedraw();
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_SINGLE_ACTION("SetNeedsBeginFrameOnImplThread", client);
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
+ EXPECT_TRUE(client.needs_begin_impl_frame());
client.Reset();
- scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_SINGLE_ACTION("PostBeginFrameDeadlineTask", client);
+ scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
+ EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
client.Reset();
- scheduler->OnBeginFrameDeadline();
+ scheduler->OnBeginImplFrameDeadline();
EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 2);
- EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client, 1, 2);
+ EXPECT_ACTION("SetNeedsBeginImplFrame", client, 1, 2);
EXPECT_FALSE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(client.needs_begin_impl_frame());
client.Reset();
- scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_SINGLE_ACTION("PostBeginFrameDeadlineTask", client);
+ scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
+ EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
client.Reset();
- scheduler->OnBeginFrameDeadline();
- EXPECT_SINGLE_ACTION("SetNeedsBeginFrameOnImplThread", client);
+ scheduler->OnBeginImplFrameDeadline();
+ EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
EXPECT_FALSE(scheduler->RedrawPending());
- EXPECT_FALSE(client.needs_begin_frame());
+ EXPECT_FALSE(client.needs_begin_impl_frame());
client.Reset();
scheduler->SetMainThreadNeedsLayerTextures();
EXPECT_SINGLE_ACTION("ScheduledActionAcquireLayerTexturesForMainThread",
client);
- // We should request a BeginFrame in anticipation of a draw.
+ // We should request a BeginImplFrame in anticipation of a draw.
client.Reset();
scheduler->SetNeedsRedraw();
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_SINGLE_ACTION("SetNeedsBeginFrameOnImplThread", client);
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
+ EXPECT_TRUE(client.needs_begin_impl_frame());
// No draw happens since the textures are acquired by the main thread.
client.Reset();
- scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_SINGLE_ACTION("PostBeginFrameDeadlineTask", client);
+ scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
+ EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
client.Reset();
- scheduler->OnBeginFrameDeadline();
- EXPECT_SINGLE_ACTION("SetNeedsBeginFrameOnImplThread", client);
+ scheduler->OnBeginImplFrameDeadline();
+ EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(client.needs_begin_impl_frame());
client.Reset();
scheduler->SetNeedsCommit();
if (deadline_scheduling_enabled) {
EXPECT_EQ(0, client.num_actions_());
} else {
- EXPECT_SINGLE_ACTION("ScheduledActionSendBeginFrameToMainThread", client);
+ EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client);
}
client.Reset();
- scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
+ scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
if (deadline_scheduling_enabled) {
- EXPECT_ACTION("ScheduledActionSendBeginFrameToMainThread", client, 0, 2);
- EXPECT_ACTION("PostBeginFrameDeadlineTask", client, 1, 2);
+ EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 0, 2);
+ EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client, 1, 2);
} else {
- EXPECT_SINGLE_ACTION("PostBeginFrameDeadlineTask", client);
+ EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
}
// Commit will release the texture.
client.Reset();
scheduler->FinishCommit();
EXPECT_ACTION("ScheduledActionCommit", client, 0, 2);
- EXPECT_ACTION("PostBeginFrameDeadlineTask", client, 1, 2);
+ EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client, 1, 2);
EXPECT_TRUE(scheduler->RedrawPending());
// Now we can draw again after the commit happens.
client.Reset();
- scheduler->OnBeginFrameDeadline();
+ scheduler->OnBeginImplFrameDeadline();
EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 2);
- EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client, 1, 2);
+ EXPECT_ACTION("SetNeedsBeginImplFrame", client, 1, 2);
EXPECT_FALSE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(client.needs_begin_impl_frame());
- // Make sure we stop requesting BeginFrames if we don't swap.
+ // Make sure we stop requesting BeginImplFrames if we don't swap.
client.Reset();
- scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_SINGLE_ACTION("PostBeginFrameDeadlineTask", client);
+ scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
+ EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
client.Reset();
- scheduler->OnBeginFrameDeadline();
- EXPECT_SINGLE_ACTION("SetNeedsBeginFrameOnImplThread", client);
- EXPECT_FALSE(client.needs_begin_frame());
+ scheduler->OnBeginImplFrameDeadline();
+ EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
+ EXPECT_FALSE(client.needs_begin_impl_frame());
}
TEST(SchedulerTest, TextureAcquisitionCausesCommitInsteadOfDraw) {
@@ -500,10 +515,10 @@ void TextureAcquisitionCollision(bool deadline_scheduling_enabled) {
client.Reset();
scheduler->SetNeedsCommit();
if (deadline_scheduling_enabled) {
- EXPECT_SINGLE_ACTION("SetNeedsBeginFrameOnImplThread", client);
+ EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
} else {
- EXPECT_ACTION("ScheduledActionSendBeginFrameToMainThread", client, 0, 2);
- EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client, 1, 2);
+ EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 0, 2);
+ EXPECT_ACTION("SetNeedsBeginImplFrame", client, 1, 2);
}
client.Reset();
@@ -512,26 +527,26 @@ if (deadline_scheduling_enabled) {
"ScheduledActionAcquireLayerTexturesForMainThread", client);
client.Reset();
- scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
+ scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
if (deadline_scheduling_enabled) {
- EXPECT_ACTION("ScheduledActionSendBeginFrameToMainThread", client, 0, 2);
- EXPECT_ACTION("PostBeginFrameDeadlineTask", client, 1, 2);
+ EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 0, 2);
+ EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client, 1, 2);
} else {
- EXPECT_SINGLE_ACTION("PostBeginFrameDeadlineTask", client);
+ EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
}
client.Reset();
- scheduler->OnBeginFrameDeadline();
- EXPECT_SINGLE_ACTION("SetNeedsBeginFrameOnImplThread", client);
+ scheduler->OnBeginImplFrameDeadline();
+ EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
// Although the compositor cannot draw because textures are locked by main
- // thread, we continue requesting SetNeedsBeginFrame in anticipation of the
- // unlock.
- EXPECT_TRUE(client.needs_begin_frame());
+ // thread, we continue requesting SetNeedsBeginImplFrame in anticipation of
+ // the unlock.
+ EXPECT_TRUE(client.needs_begin_impl_frame());
// Trigger the commit
scheduler->FinishCommit();
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(client.needs_begin_impl_frame());
// Between commit and draw, texture acquisition for main thread delayed,
// and main thread blocks.
@@ -541,61 +556,61 @@ if (deadline_scheduling_enabled) {
// No implicit commit is expected.
client.Reset();
- scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_SINGLE_ACTION("PostBeginFrameDeadlineTask", client);
+ scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
+ EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
client.Reset();
- scheduler->OnBeginFrameDeadline();
+ scheduler->OnBeginImplFrameDeadline();
EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 3);
EXPECT_ACTION(
"ScheduledActionAcquireLayerTexturesForMainThread", client, 1, 3);
- EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client, 2, 3);
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_ACTION("SetNeedsBeginImplFrame", client, 2, 3);
+ EXPECT_TRUE(client.needs_begin_impl_frame());
// The compositor should not draw because textures are locked by main
// thread.
client.Reset();
- scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_SINGLE_ACTION("PostBeginFrameDeadlineTask", client);
+ scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
+ EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
client.Reset();
- scheduler->OnBeginFrameDeadline();
- EXPECT_SINGLE_ACTION("SetNeedsBeginFrameOnImplThread", client);
- EXPECT_FALSE(client.needs_begin_frame());
+ scheduler->OnBeginImplFrameDeadline();
+ EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
+ EXPECT_FALSE(client.needs_begin_impl_frame());
// The impl thread need an explicit commit from the main thread to lock
// the textures.
client.Reset();
scheduler->SetNeedsCommit();
if (deadline_scheduling_enabled) {
- EXPECT_SINGLE_ACTION("SetNeedsBeginFrameOnImplThread", client);
+ EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
} else {
- EXPECT_ACTION("ScheduledActionSendBeginFrameToMainThread", client, 0, 2);
- EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client, 1, 2);
+ EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 0, 2);
+ EXPECT_ACTION("SetNeedsBeginImplFrame", client, 1, 2);
}
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(client.needs_begin_impl_frame());
client.Reset();
- scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
+ scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
if (deadline_scheduling_enabled) {
- EXPECT_ACTION("ScheduledActionSendBeginFrameToMainThread", client, 0, 2);
- EXPECT_ACTION("PostBeginFrameDeadlineTask", client, 1, 2);
+ EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 0, 2);
+ EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client, 1, 2);
} else {
- EXPECT_SINGLE_ACTION("PostBeginFrameDeadlineTask", client);
+ EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
}
client.Reset();
// Trigger the commit, which will trigger the deadline task early.
scheduler->FinishCommit();
EXPECT_ACTION("ScheduledActionCommit", client, 0, 2);
- EXPECT_ACTION("PostBeginFrameDeadlineTask", client, 1, 2);
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client, 1, 2);
+ EXPECT_TRUE(client.needs_begin_impl_frame());
client.Reset();
- // Verify we draw on the next BeginFrame deadline
- scheduler->OnBeginFrameDeadline();
+ // Verify we draw on the next BeginImplFrame deadline
+ scheduler->OnBeginImplFrameDeadline();
EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 2);
- EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client, 1, 2);
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_ACTION("SetNeedsBeginImplFrame", client, 1, 2);
+ EXPECT_TRUE(client.needs_begin_impl_frame());
client.Reset();
}
@@ -624,8 +639,8 @@ void VisibilitySwitchWithTextureAcquisition(bool deadline_scheduling_enabled) {
scheduler->SetNeedsCommit();
if (deadline_scheduling_enabled) {
- scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
- scheduler->OnBeginFrameDeadline();
+ scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
+ scheduler->OnBeginImplFrameDeadline();
}
scheduler->FinishCommit();
scheduler->SetMainThreadNeedsLayerTextures();
@@ -640,15 +655,15 @@ void VisibilitySwitchWithTextureAcquisition(bool deadline_scheduling_enabled) {
client.Reset();
scheduler->SetVisible(true);
EXPECT_EQ(0, client.num_actions_());
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(client.needs_begin_impl_frame());
// Regaining visibility with textures acquired by main thread while
// compositor is waiting for first draw should result in a request
// for a new frame in order to escape a deadlock.
client.Reset();
- scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_ACTION("ScheduledActionSendBeginFrameToMainThread", client, 0, 2);
- EXPECT_ACTION("PostBeginFrameDeadlineTask", client, 1, 2);
+ scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
+ EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 0, 2);
+ EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client, 1, 2);
}
TEST(SchedulerTest, VisibilitySwitchWithTextureAcquisition) {
@@ -663,7 +678,7 @@ TEST(SchedulerTest, VisibilitySwitchWithTextureAcquisition_Deadline) {
class SchedulerClientThatsetNeedsDrawInsideDraw : public FakeSchedulerClient {
public:
- virtual void ScheduledActionSendBeginFrameToMainThread() OVERRIDE {}
+ virtual void ScheduledActionSendBeginMainFrame() OVERRIDE {}
virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapIfPossible()
OVERRIDE {
// Only SetNeedsRedraw the first time this is called
@@ -701,27 +716,28 @@ TEST(SchedulerTest, RequestRedrawInsideDraw) {
scheduler->SetNeedsRedraw();
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(client.needs_begin_impl_frame());
EXPECT_EQ(0, client.num_draws());
- scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
- scheduler->OnBeginFrameDeadline();
+ scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
+ scheduler->OnBeginImplFrameDeadline();
EXPECT_EQ(1, client.num_draws());
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(client.needs_begin_impl_frame());
- scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
- scheduler->OnBeginFrameDeadline();
+ scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
+ scheduler->OnBeginImplFrameDeadline();
EXPECT_EQ(2, client.num_draws());
EXPECT_FALSE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(client.needs_begin_impl_frame());
- // We stop requesting BeginFrames after a BeginFrame where we don't swap.
- scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
- scheduler->OnBeginFrameDeadline();
+ // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
+ // swap.
+ scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
+ scheduler->OnBeginImplFrameDeadline();
EXPECT_EQ(2, client.num_draws());
EXPECT_FALSE(scheduler->RedrawPending());
- EXPECT_FALSE(client.needs_begin_frame());
+ EXPECT_FALSE(client.needs_begin_impl_frame());
}
// Test that requesting redraw inside a failed draw doesn't lose the request.
@@ -739,36 +755,36 @@ TEST(SchedulerTest, RequestRedrawInsideFailedDraw) {
scheduler->SetNeedsRedraw();
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(client.needs_begin_impl_frame());
EXPECT_EQ(0, client.num_draws());
// Fail the draw.
- scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
- scheduler->OnBeginFrameDeadline();
+ scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
+ scheduler->OnBeginImplFrameDeadline();
EXPECT_EQ(1, client.num_draws());
// We have a commit pending and the draw failed, and we didn't lose the redraw
// request.
EXPECT_TRUE(scheduler->CommitPending());
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(client.needs_begin_impl_frame());
// Fail the draw again.
- scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
- scheduler->OnBeginFrameDeadline();
+ scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
+ scheduler->OnBeginImplFrameDeadline();
EXPECT_EQ(2, client.num_draws());
EXPECT_TRUE(scheduler->CommitPending());
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(client.needs_begin_impl_frame());
// Draw successfully.
client.SetDrawWillHappen(true);
- scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
- scheduler->OnBeginFrameDeadline();
+ scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
+ scheduler->OnBeginImplFrameDeadline();
EXPECT_EQ(3, client.num_draws());
EXPECT_TRUE(scheduler->CommitPending());
EXPECT_FALSE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(client.needs_begin_impl_frame());
}
class SchedulerClientThatSetNeedsCommitInsideDraw : public FakeSchedulerClient {
@@ -776,7 +792,7 @@ class SchedulerClientThatSetNeedsCommitInsideDraw : public FakeSchedulerClient {
SchedulerClientThatSetNeedsCommitInsideDraw()
: set_needs_commit_on_next_draw_(false) {}
- virtual void ScheduledActionSendBeginFrameToMainThread() OVERRIDE {}
+ virtual void ScheduledActionSendBeginMainFrame() OVERRIDE {}
virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapIfPossible()
OVERRIDE {
// Only SetNeedsCommit the first time this is called
@@ -817,36 +833,37 @@ TEST(SchedulerTest, RequestCommitInsideDraw) {
InitializeOutputSurfaceAndFirstCommit(scheduler);
client.Reset();
- EXPECT_FALSE(client.needs_begin_frame());
+ EXPECT_FALSE(client.needs_begin_impl_frame());
scheduler->SetNeedsRedraw();
EXPECT_TRUE(scheduler->RedrawPending());
EXPECT_EQ(0, client.num_draws());
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(client.needs_begin_impl_frame());
client.SetNeedsCommitOnNextDraw();
- scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
+ scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
client.SetNeedsCommitOnNextDraw();
- scheduler->OnBeginFrameDeadline();
+ scheduler->OnBeginImplFrameDeadline();
EXPECT_EQ(1, client.num_draws());
EXPECT_TRUE(scheduler->CommitPending());
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(client.needs_begin_impl_frame());
scheduler->FinishCommit();
- scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
- scheduler->OnBeginFrameDeadline();
+ scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
+ scheduler->OnBeginImplFrameDeadline();
EXPECT_EQ(2, client.num_draws());
EXPECT_FALSE(scheduler->RedrawPending());
EXPECT_FALSE(scheduler->CommitPending());
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(client.needs_begin_impl_frame());
- // We stop requesting BeginFrames after a BeginFrame where we don't swap.
- scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
- scheduler->OnBeginFrameDeadline();
+ // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
+ // swap.
+ scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
+ scheduler->OnBeginImplFrameDeadline();
EXPECT_EQ(2, client.num_draws());
EXPECT_FALSE(scheduler->RedrawPending());
EXPECT_FALSE(scheduler->CommitPending());
- EXPECT_FALSE(client.needs_begin_frame());
+ EXPECT_FALSE(client.needs_begin_impl_frame());
}
// Tests that when a draw fails then the pending commit should not be dropped.
@@ -864,36 +881,36 @@ TEST(SchedulerTest, RequestCommitInsideFailedDraw) {
scheduler->SetNeedsRedraw();
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(client.needs_begin_impl_frame());
EXPECT_EQ(0, client.num_draws());
// Fail the draw.
- scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
- scheduler->OnBeginFrameDeadline();
+ scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
+ scheduler->OnBeginImplFrameDeadline();
EXPECT_EQ(1, client.num_draws());
// We have a commit pending and the draw failed, and we didn't lose the commit
// request.
EXPECT_TRUE(scheduler->CommitPending());
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(client.needs_begin_impl_frame());
// Fail the draw again.
- scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
- scheduler->OnBeginFrameDeadline();
+ scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
+ scheduler->OnBeginImplFrameDeadline();
EXPECT_EQ(2, client.num_draws());
EXPECT_TRUE(scheduler->CommitPending());
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(client.needs_begin_impl_frame());
// Draw successfully.
client.SetDrawWillHappen(true);
- scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
- scheduler->OnBeginFrameDeadline();
+ scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
+ scheduler->OnBeginImplFrameDeadline();
EXPECT_EQ(3, client.num_draws());
EXPECT_TRUE(scheduler->CommitPending());
EXPECT_FALSE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(client.needs_begin_impl_frame());
}
TEST(SchedulerTest, NoSwapWhenDrawFails) {
@@ -908,24 +925,24 @@ TEST(SchedulerTest, NoSwapWhenDrawFails) {
scheduler->SetNeedsRedraw();
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(client.needs_begin_impl_frame());
EXPECT_EQ(0, client.num_draws());
// Draw successfully, this starts a new frame.
client.SetNeedsCommitOnNextDraw();
- scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
- scheduler->OnBeginFrameDeadline();
+ scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
+ scheduler->OnBeginImplFrameDeadline();
EXPECT_EQ(1, client.num_draws());
scheduler->SetNeedsRedraw();
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(client.needs_begin_impl_frame());
// Fail to draw, this should not start a frame.
client.SetDrawWillHappen(false);
client.SetNeedsCommitOnNextDraw();
- scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
- scheduler->OnBeginFrameDeadline();
+ scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
+ scheduler->OnBeginImplFrameDeadline();
EXPECT_EQ(2, client.num_draws());
}
@@ -992,26 +1009,26 @@ TEST(SchedulerTest, ManageTiles) {
InitializeOutputSurfaceAndFirstCommit(scheduler);
// Request both draw and manage tiles. ManageTiles shouldn't
- // be trigged until BeginFrame.
+ // be trigged until BeginImplFrame.
client.Reset();
scheduler->SetNeedsManageTiles();
scheduler->SetNeedsRedraw();
EXPECT_TRUE(scheduler->RedrawPending());
EXPECT_TRUE(scheduler->ManageTilesPending());
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(client.needs_begin_impl_frame());
EXPECT_EQ(0, client.num_draws());
EXPECT_FALSE(client.HasAction("ScheduledActionManageTiles"));
EXPECT_FALSE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
- // We have no immediate actions to perform, so the BeginFrame should post
+ // We have no immediate actions to perform, so the BeginImplFrame should post
// the deadline task.
client.Reset();
- scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_SINGLE_ACTION("PostBeginFrameDeadlineTask", client);
+ scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
+ EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
// On the deadline, he actions should have occured in the right order.
client.Reset();
- scheduler->OnBeginFrameDeadline();
+ scheduler->OnBeginImplFrameDeadline();
EXPECT_EQ(1, client.num_draws());
EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
EXPECT_TRUE(client.HasAction("ScheduledActionManageTiles"));
@@ -1025,20 +1042,20 @@ TEST(SchedulerTest, ManageTiles) {
scheduler->SetNeedsRedraw();
EXPECT_TRUE(scheduler->RedrawPending());
EXPECT_FALSE(scheduler->ManageTilesPending());
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(client.needs_begin_impl_frame());
EXPECT_EQ(0, client.num_draws());
- // We have no immediate actions to perform, so the BeginFrame should post
+ // We have no immediate actions to perform, so the BeginImplFrame should post
// the deadline task.
client.Reset();
- scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_SINGLE_ACTION("PostBeginFrameDeadlineTask", client);
+ scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
+ EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
// Draw. The draw will trigger SetNeedsManageTiles, and
// then the ManageTiles action will be triggered after the Draw.
// Afterwards, neither a draw nor ManageTiles are pending.
client.Reset();
- scheduler->OnBeginFrameDeadline();
+ scheduler->OnBeginImplFrameDeadline();
EXPECT_EQ(1, client.num_draws());
EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
EXPECT_TRUE(client.HasAction("ScheduledActionManageTiles"));
@@ -1047,34 +1064,223 @@ TEST(SchedulerTest, ManageTiles) {
EXPECT_FALSE(scheduler->RedrawPending());
EXPECT_FALSE(scheduler->ManageTilesPending());
- // We need a BeginFrame where we don't swap to go idle.
+ // We need a BeginImplFrame where we don't swap to go idle.
client.Reset();
- scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_SINGLE_ACTION("PostBeginFrameDeadlineTask", client);
+ scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
+ EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
client.Reset();
- scheduler->OnBeginFrameDeadline();
- EXPECT_SINGLE_ACTION("SetNeedsBeginFrameOnImplThread", client);;
+ scheduler->OnBeginImplFrameDeadline();
+ EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);;
EXPECT_EQ(0, client.num_draws());
// Now trigger a ManageTiles outside of a draw. We will then need
// a begin-frame for the ManageTiles, but we don't need a draw.
client.Reset();
- EXPECT_FALSE(client.needs_begin_frame());
+ EXPECT_FALSE(client.needs_begin_impl_frame());
scheduler->SetNeedsManageTiles();
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(client.needs_begin_impl_frame());
EXPECT_TRUE(scheduler->ManageTilesPending());
EXPECT_FALSE(scheduler->RedrawPending());
- // BeginFrame. There will be no draw, only ManageTiles.
+ // BeginImplFrame. There will be no draw, only ManageTiles.
client.Reset();
- scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_SINGLE_ACTION("PostBeginFrameDeadlineTask", client);
+ scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
+ EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
client.Reset();
- scheduler->OnBeginFrameDeadline();
+ scheduler->OnBeginImplFrameDeadline();
EXPECT_EQ(0, client.num_draws());
EXPECT_FALSE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
EXPECT_TRUE(client.HasAction("ScheduledActionManageTiles"));
}
+// Test that ManageTiles only happens once per frame. If an external caller
+// initiates it, then the state machine should not on that frame.
+TEST(SchedulerTest, ManageTilesOncePerFrame) {
+ FakeSchedulerClient client;
+ SchedulerSettings default_scheduler_settings;
+ Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
+ scheduler->SetCanStart();
+ scheduler->SetVisible(true);
+ scheduler->SetCanDraw(true);
+ InitializeOutputSurfaceAndFirstCommit(scheduler);
+
+ // If DidManageTiles during a frame, then ManageTiles should not occur again.
+ scheduler->SetNeedsManageTiles();
+ scheduler->SetNeedsRedraw();
+ client.Reset();
+ scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
+ EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
+
+ EXPECT_TRUE(scheduler->ManageTilesPending());
+ scheduler->DidManageTiles();
+ EXPECT_FALSE(scheduler->ManageTilesPending());
+
+ client.Reset();
+ scheduler->OnBeginImplFrameDeadline();
+ EXPECT_EQ(1, client.num_draws());
+ EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
+ EXPECT_FALSE(client.HasAction("ScheduledActionManageTiles"));
+ EXPECT_FALSE(scheduler->RedrawPending());
+ EXPECT_FALSE(scheduler->ManageTilesPending());
+
+ // Next frame without DidManageTiles should ManageTiles with draw.
+ scheduler->SetNeedsManageTiles();
+ scheduler->SetNeedsRedraw();
+ client.Reset();
+ scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
+ EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
+
+ client.Reset();
+ scheduler->OnBeginImplFrameDeadline();
+ EXPECT_EQ(1, client.num_draws());
+ EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
+ EXPECT_TRUE(client.HasAction("ScheduledActionManageTiles"));
+ EXPECT_LT(client.ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
+ client.ActionIndex("ScheduledActionManageTiles"));
+ EXPECT_FALSE(scheduler->RedrawPending());
+ EXPECT_FALSE(scheduler->ManageTilesPending());
+}
+
+class SchedulerClientWithFixedEstimates : public FakeSchedulerClient {
+ public:
+ SchedulerClientWithFixedEstimates(
+ base::TimeDelta draw_duration,
+ base::TimeDelta begin_main_frame_to_commit_duration,
+ base::TimeDelta commit_to_activate_duration)
+ : draw_duration_(draw_duration),
+ begin_main_frame_to_commit_duration_(
+ begin_main_frame_to_commit_duration),
+ commit_to_activate_duration_(commit_to_activate_duration) {}
+
+ virtual base::TimeDelta DrawDurationEstimate() OVERRIDE {
+ return draw_duration_;
+ }
+ virtual base::TimeDelta BeginMainFrameToCommitDurationEstimate() OVERRIDE {
+ return begin_main_frame_to_commit_duration_;
+ }
+ virtual base::TimeDelta CommitToActivateDurationEstimate() OVERRIDE {
+ return commit_to_activate_duration_;
+ }
+
+ private:
+ base::TimeDelta draw_duration_;
+ base::TimeDelta begin_main_frame_to_commit_duration_;
+ base::TimeDelta commit_to_activate_duration_;
+};
+
+void MainFrameInHighLatencyMode(int64 begin_main_frame_to_commit_estimate_in_ms,
+ int64 commit_to_activate_estimate_in_ms,
+ bool should_send_begin_main_frame) {
+ // Set up client with specified estimates (draw duration is set to 1).
+ SchedulerClientWithFixedEstimates client(
+ base::TimeDelta::FromMilliseconds(1),
+ base::TimeDelta::FromMilliseconds(
+ begin_main_frame_to_commit_estimate_in_ms),
+ base::TimeDelta::FromMilliseconds(commit_to_activate_estimate_in_ms));
+ SchedulerSettings scheduler_settings;
+ scheduler_settings.deadline_scheduling_enabled = true;
+ scheduler_settings.switch_to_low_latency_if_possible = true;
+ Scheduler* scheduler = client.CreateScheduler(scheduler_settings);
+ scheduler->SetCanStart();
+ scheduler->SetVisible(true);
+ scheduler->SetCanDraw(true);
+ InitializeOutputSurfaceAndFirstCommit(scheduler);
+
+ // Impl thread hits deadline before commit finishes.
+ client.Reset();
+ scheduler->SetNeedsCommit();
+ EXPECT_FALSE(scheduler->MainThreadIsInHighLatencyMode());
+ scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
+ EXPECT_FALSE(scheduler->MainThreadIsInHighLatencyMode());
+ scheduler->OnBeginImplFrameDeadline();
+ EXPECT_TRUE(scheduler->MainThreadIsInHighLatencyMode());
+ scheduler->FinishCommit();
+ EXPECT_TRUE(scheduler->MainThreadIsInHighLatencyMode());
+ EXPECT_TRUE(client.HasAction("ScheduledActionSendBeginMainFrame"));
+
+ client.Reset();
+ scheduler->SetNeedsCommit();
+ EXPECT_TRUE(scheduler->MainThreadIsInHighLatencyMode());
+ scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
+ EXPECT_TRUE(scheduler->MainThreadIsInHighLatencyMode());
+ scheduler->OnBeginImplFrameDeadline();
+ EXPECT_EQ(scheduler->MainThreadIsInHighLatencyMode(),
+ should_send_begin_main_frame);
+ EXPECT_EQ(client.HasAction("ScheduledActionSendBeginMainFrame"),
+ should_send_begin_main_frame);
+}
+
+TEST(SchedulerTest,
+ SkipMainFrameIfHighLatencyAndCanCommitAndActivateBeforeDeadline) {
+ // Set up client so that estimates indicate that we can commit and activate
+ // before the deadline (~8ms by default).
+ MainFrameInHighLatencyMode(1, 1, false);
+}
+
+TEST(SchedulerTest, NotSkipMainFrameIfHighLatencyAndCanCommitTooLong) {
+ // Set up client so that estimates indicate that the commit cannot finish
+ // before the deadline (~8ms by default).
+ MainFrameInHighLatencyMode(10, 1, true);
+}
+
+TEST(SchedulerTest, NotSkipMainFrameIfHighLatencyAndCanActivateTooLong) {
+ // Set up client so that estimates indicate that the activate cannot finish
+ // before the deadline (~8ms by default).
+ MainFrameInHighLatencyMode(1, 10, true);
+}
+
+void SpinForMillis(int millis) {
+ base::RunLoop run_loop;
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ run_loop.QuitClosure(),
+ base::TimeDelta::FromMilliseconds(millis));
+ run_loop.Run();
+}
+
+TEST(SchedulerTest, PollForCommitCompletion) {
+ FakeSchedulerClient client;
+ client.set_log_anticipated_draw_time_change(true);
+ SchedulerSettings settings = SchedulerSettings();
+ settings.throttle_frame_production = false;
+ Scheduler* scheduler = client.CreateScheduler(settings);
+
+ scheduler->SetCanDraw(true);
+ scheduler->SetCanStart();
+ scheduler->SetVisible(true);
+ scheduler->DidCreateAndInitializeOutputSurface();
+
+ scheduler->SetNeedsCommit();
+ EXPECT_TRUE(scheduler->CommitPending());
+ scheduler->FinishCommit();
+ scheduler->SetNeedsRedraw();
+ BeginFrameArgs impl_frame_args = BeginFrameArgs::CreateForTesting();
+ const int interval = 1;
+ impl_frame_args.interval = base::TimeDelta::FromMilliseconds(interval);
+ scheduler->BeginImplFrame(impl_frame_args);
+ scheduler->OnBeginImplFrameDeadline();
+
+ // At this point, we've drawn a frame. Start another commit, but hold off on
+ // the FinishCommit for now.
+ EXPECT_FALSE(scheduler->CommitPending());
+ scheduler->SetNeedsCommit();
+ EXPECT_TRUE(scheduler->CommitPending());
+
+ // Spin the event loop a few times and make sure we get more
+ // DidAnticipateDrawTimeChange calls every time.
+ int actions_so_far = client.num_actions_();
+
+ // Does three iterations to make sure that the timer is properly repeating.
+ for (int i = 0; i < 3; ++i) {
+ // Wait for 2x the frame interval to match
+ // Scheduler::advance_commit_state_timer_'s rate.
+ SpinForMillis(interval * 2);
+ EXPECT_GT(client.num_actions_(), actions_so_far);
+ EXPECT_STREQ(client.Action(client.num_actions_() - 1),
+ "DidAnticipatedDrawTimeChange");
+ actions_so_far = client.num_actions_();
+ }
+}
+
} // namespace
} // namespace cc
diff --git a/chromium/cc/scheduler/texture_uploader.cc b/chromium/cc/scheduler/texture_uploader.cc
index 677029081fc..6758f11de2d 100644
--- a/chromium/cc/scheduler/texture_uploader.cc
+++ b/chromium/cc/scheduler/texture_uploader.cc
@@ -13,12 +13,14 @@
#include "cc/resources/prioritized_resource.h"
#include "cc/resources/resource.h"
#include "gpu/GLES2/gl2extchromium.h"
-#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/khronos/GLES2/gl2ext.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/vector2d.h"
+using gpu::gles2::GLES2Interface;
+
namespace {
// How many previous uploads to use when predicting future throughput.
@@ -38,50 +40,46 @@ static const size_t kTextureUploadFlushPeriod = 4;
namespace cc {
-TextureUploader::Query::Query(WebKit::WebGraphicsContext3D* context)
- : context_(context),
+TextureUploader::Query::Query(GLES2Interface* gl)
+ : gl_(gl),
query_id_(0),
value_(0),
has_value_(false),
is_non_blocking_(false) {
- query_id_ = context_->createQueryEXT();
+ gl_->GenQueriesEXT(1, &query_id_);
}
-TextureUploader::Query::~Query() { context_->deleteQueryEXT(query_id_); }
+TextureUploader::Query::~Query() { gl_->DeleteQueriesEXT(1, &query_id_); }
void TextureUploader::Query::Begin() {
has_value_ = false;
is_non_blocking_ = false;
- context_->beginQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM, query_id_);
+ gl_->BeginQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM, query_id_);
}
void TextureUploader::Query::End() {
- context_->endQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM);
+ gl_->EndQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM);
}
bool TextureUploader::Query::IsPending() {
unsigned available = 1;
- context_->getQueryObjectuivEXT(
+ gl_->GetQueryObjectuivEXT(
query_id_, GL_QUERY_RESULT_AVAILABLE_EXT, &available);
return !available;
}
unsigned TextureUploader::Query::Value() {
if (!has_value_) {
- context_->getQueryObjectuivEXT(query_id_, GL_QUERY_RESULT_EXT, &value_);
+ gl_->GetQueryObjectuivEXT(query_id_, GL_QUERY_RESULT_EXT, &value_);
has_value_ = true;
}
return value_;
}
-TextureUploader::TextureUploader(WebKit::WebGraphicsContext3D* context,
- bool use_map_tex_sub_image,
- bool use_shallow_flush)
- : context_(context),
+TextureUploader::TextureUploader(GLES2Interface* gl)
+ : gl_(gl),
num_blocking_texture_uploads_(0),
- use_map_tex_sub_image_(use_map_tex_sub_image),
sub_image_size_(0),
- use_shallow_flush_(use_shallow_flush),
num_texture_uploads_since_last_flush_(0) {
for (size_t i = kUploadHistorySizeInitial; i > 0; i--)
textures_per_second_history_.insert(kDefaultEstimatedTexturesPerSecond);
@@ -119,7 +117,7 @@ double TextureUploader::EstimatedTexturesPerSecond() {
void TextureUploader::BeginQuery() {
if (available_queries_.empty())
- available_queries_.push_back(Query::Create(context_));
+ available_queries_.push_back(Query::Create(gl_));
available_queries_.front()->Begin();
}
@@ -143,11 +141,13 @@ void TextureUploader::Upload(const uint8* image,
if (is_full_upload)
BeginQuery();
- if (use_map_tex_sub_image_) {
+ if (format == ETC1) {
+ // ETC1 does not support subimage uploads.
+ DCHECK(is_full_upload);
+ UploadWithTexImageETC1(image, size);
+ } else {
UploadWithMapTexSubImage(
image, image_rect, source_rect, dest_offset, format);
- } else {
- UploadWithTexSubImage(image, image_rect, source_rect, dest_offset, format);
}
if (is_full_upload)
@@ -162,8 +162,7 @@ void TextureUploader::Flush() {
if (!num_texture_uploads_since_last_flush_)
return;
- if (use_shallow_flush_)
- context_->shallowFlushCHROMIUM();
+ gl_->ShallowFlushCHROMIUM();
num_texture_uploads_since_last_flush_ = 0;
}
@@ -190,7 +189,7 @@ void TextureUploader::UploadWithTexSubImage(const uint8* image,
gfx::Vector2d offset(source_rect.origin() - image_rect.origin());
const uint8* pixel_source;
- unsigned bytes_per_pixel = ResourceProvider::BytesPerPixel(format);
+ unsigned bytes_per_pixel = BitsPerPixel(format) / 8;
// Use 4-byte row alignment (OpenGL default) for upload performance.
// Assuming that GL_UNPACK_ALIGNMENT has not changed from default.
unsigned upload_image_stride =
@@ -210,21 +209,21 @@ void TextureUploader::UploadWithTexSubImage(const uint8* image,
for (int row = 0; row < source_rect.height(); ++row)
memcpy(&sub_image_[upload_image_stride * row],
&image[bytes_per_pixel *
- (offset.x() + (offset.y() + row) * image_rect.width())],
+ (offset.x() + (offset.y() + row) * image_rect.width())],
source_rect.width() * bytes_per_pixel);
pixel_source = &sub_image_[0];
}
- context_->texSubImage2D(GL_TEXTURE_2D,
- 0,
- dest_offset.x(),
- dest_offset.y(),
- source_rect.width(),
- source_rect.height(),
- ResourceProvider::GetGLDataFormat(format),
- ResourceProvider::GetGLDataType(format),
- pixel_source);
+ gl_->TexSubImage2D(GL_TEXTURE_2D,
+ 0,
+ dest_offset.x(),
+ dest_offset.y(),
+ source_rect.width(),
+ source_rect.height(),
+ GLDataFormat(format),
+ GLDataType(format),
+ pixel_source);
}
void TextureUploader::UploadWithMapTexSubImage(const uint8* image,
@@ -239,29 +238,29 @@ void TextureUploader::UploadWithMapTexSubImage(const uint8* image,
if (source_rect.IsEmpty())
return;
DCHECK(image);
+ // Compressed textures have no implementation of mapTexSubImage.
+ DCHECK_NE(ETC1, format);
// Offset from image-rect to source-rect.
gfx::Vector2d offset(source_rect.origin() - image_rect.origin());
- unsigned bytes_per_pixel = ResourceProvider::BytesPerPixel(format);
+ unsigned bytes_per_pixel = BitsPerPixel(format) / 8;
// Use 4-byte row alignment (OpenGL default) for upload performance.
// Assuming that GL_UNPACK_ALIGNMENT has not changed from default.
unsigned upload_image_stride =
RoundUp(bytes_per_pixel * source_rect.width(), 4u);
// Upload tile data via a mapped transfer buffer
- uint8* pixel_dest = static_cast<uint8*>(
- context_->mapTexSubImage2DCHROMIUM(GL_TEXTURE_2D,
- 0,
- dest_offset.x(),
- dest_offset.y(),
- source_rect.width(),
- source_rect.height(),
- ResourceProvider::GetGLDataFormat(
- format),
- ResourceProvider::GetGLDataType(
- format),
- GL_WRITE_ONLY));
+ uint8* pixel_dest =
+ static_cast<uint8*>(gl_->MapTexSubImage2DCHROMIUM(GL_TEXTURE_2D,
+ 0,
+ dest_offset.x(),
+ dest_offset.y(),
+ source_rect.width(),
+ source_rect.height(),
+ GLDataFormat(format),
+ GLDataType(format),
+ GL_WRITE_ONLY));
if (!pixel_dest) {
UploadWithTexSubImage(image, image_rect, source_rect, dest_offset, format);
@@ -279,12 +278,28 @@ void TextureUploader::UploadWithMapTexSubImage(const uint8* image,
for (int row = 0; row < source_rect.height(); ++row) {
memcpy(&pixel_dest[upload_image_stride * row],
&image[bytes_per_pixel *
- (offset.x() + (offset.y() + row) * image_rect.width())],
+ (offset.x() + (offset.y() + row) * image_rect.width())],
source_rect.width() * bytes_per_pixel);
}
}
- context_->unmapTexSubImage2DCHROMIUM(pixel_dest);
+ gl_->UnmapTexSubImage2DCHROMIUM(pixel_dest);
+}
+
+void TextureUploader::UploadWithTexImageETC1(const uint8* image,
+ gfx::Size size) {
+ TRACE_EVENT0("cc", "TextureUploader::UploadWithTexImageETC1");
+ DCHECK_EQ(0, size.width() % 4);
+ DCHECK_EQ(0, size.height() % 4);
+
+ gl_->CompressedTexImage2D(GL_TEXTURE_2D,
+ 0,
+ GLInternalFormat(ETC1),
+ size.width(),
+ size.height(),
+ 0,
+ Resource::MemorySizeBytes(size, ETC1),
+ image);
}
void TextureUploader::ProcessQueries() {
diff --git a/chromium/cc/scheduler/texture_uploader.h b/chromium/cc/scheduler/texture_uploader.h
index a131ba04f9e..815282e2c4b 100644
--- a/chromium/cc/scheduler/texture_uploader.h
+++ b/chromium/cc/scheduler/texture_uploader.h
@@ -13,24 +13,24 @@
#include "cc/base/scoped_ptr_deque.h"
#include "cc/resources/resource_provider.h"
-namespace WebKit { class WebGraphicsContext3D; }
-
namespace gfx {
class Rect;
class Size;
class Vector2d;
}
+namespace gpu {
+namespace gles2 {
+class GLES2Interface;
+}
+}
+
namespace cc {
class CC_EXPORT TextureUploader {
public:
- static scoped_ptr<TextureUploader> Create(
- WebKit::WebGraphicsContext3D* context,
- bool use_map_tex_sub_image,
- bool use_shallow_flush) {
- return make_scoped_ptr(
- new TextureUploader(context, use_map_tex_sub_image, use_shallow_flush));
+ static scoped_ptr<TextureUploader> Create(gpu::gles2::GLES2Interface* gl) {
+ return make_scoped_ptr(new TextureUploader(gl));
}
~TextureUploader();
@@ -55,8 +55,8 @@ class CC_EXPORT TextureUploader {
private:
class Query {
public:
- static scoped_ptr<Query> Create(WebKit::WebGraphicsContext3D* context) {
- return make_scoped_ptr(new Query(context));
+ static scoped_ptr<Query> Create(gpu::gles2::GLES2Interface* gl) {
+ return make_scoped_ptr(new Query(gl));
}
virtual ~Query();
@@ -74,9 +74,9 @@ class CC_EXPORT TextureUploader {
}
private:
- explicit Query(WebKit::WebGraphicsContext3D* context);
+ explicit Query(gpu::gles2::GLES2Interface* gl);
- WebKit::WebGraphicsContext3D* context_;
+ gpu::gles2::GLES2Interface* gl_;
unsigned query_id_;
unsigned value_;
bool has_value_;
@@ -85,9 +85,7 @@ class CC_EXPORT TextureUploader {
DISALLOW_COPY_AND_ASSIGN(Query);
};
- TextureUploader(WebKit::WebGraphicsContext3D* context,
- bool use_map_tex_sub_image,
- bool use_shallow_flush);
+ explicit TextureUploader(gpu::gles2::GLES2Interface* gl);
void BeginQuery();
void EndQuery();
@@ -103,18 +101,17 @@ class CC_EXPORT TextureUploader {
gfx::Rect source_rect,
gfx::Vector2d dest_offset,
ResourceFormat format);
+ void UploadWithTexImageETC1(const uint8* image, gfx::Size size);
- WebKit::WebGraphicsContext3D* context_;
+ gpu::gles2::GLES2Interface* gl_;
ScopedPtrDeque<Query> pending_queries_;
ScopedPtrDeque<Query> available_queries_;
std::multiset<double> textures_per_second_history_;
size_t num_blocking_texture_uploads_;
- bool use_map_tex_sub_image_;
size_t sub_image_size_;
scoped_ptr<uint8[]> sub_image_;
- bool use_shallow_flush_;
size_t num_texture_uploads_since_last_flush_;
DISALLOW_COPY_AND_ASSIGN(TextureUploader);
diff --git a/chromium/cc/scheduler/texture_uploader_unittest.cc b/chromium/cc/scheduler/texture_uploader_unittest.cc
index 68413df92e1..792216cf081 100644
--- a/chromium/cc/scheduler/texture_uploader_unittest.cc
+++ b/chromium/cc/scheduler/texture_uploader_unittest.cc
@@ -5,29 +5,21 @@
#include "cc/scheduler/texture_uploader.h"
#include "cc/base/util.h"
-#include "cc/debug/test_web_graphics_context_3d.h"
#include "cc/resources/prioritized_resource.h"
+#include "gpu/command_buffer/client/gles2_interface_stub.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/khronos/GLES2/gl2ext.h"
-using WebKit::WGC3Denum;
-using WebKit::WGC3Dint;
-using WebKit::WGC3Dsizei;
-using WebKit::WebGLId;
-using WebKit::WGC3Duint;
-
namespace cc {
namespace {
-class TestWebGraphicsContext3DTextureUpload : public TestWebGraphicsContext3D {
+class TextureUploadTestContext : public gpu::gles2::GLES2InterfaceStub {
public:
- TestWebGraphicsContext3DTextureUpload()
- : result_available_(0),
- unpack_alignment_(4) {}
+ TextureUploadTestContext() : result_available_(0), unpack_alignment_(4) {}
- virtual void pixelStorei(WGC3Denum pname, WGC3Dint param) OVERRIDE {
+ virtual void PixelStorei(GLenum pname, GLint param) OVERRIDE {
switch (pname) {
case GL_UNPACK_ALIGNMENT:
// Param should be a power of two <= 8.
@@ -49,8 +41,9 @@ class TestWebGraphicsContext3DTextureUpload : public TestWebGraphicsContext3D {
}
}
- virtual void getQueryObjectuivEXT(WebGLId, WGC3Denum type, WGC3Duint* value)
- OVERRIDE {
+ virtual void GetQueryObjectuivEXT(GLuint,
+ GLenum type,
+ GLuint* value) OVERRIDE {
switch (type) {
case GL_QUERY_RESULT_AVAILABLE_EXT:
*value = result_available_;
@@ -61,14 +54,14 @@ class TestWebGraphicsContext3DTextureUpload : public TestWebGraphicsContext3D {
}
}
- virtual void texSubImage2D(WGC3Denum target,
- WGC3Dint level,
- WGC3Dint xoffset,
- WGC3Dint yoffset,
- WGC3Dsizei width,
- WGC3Dsizei height,
- WGC3Denum format,
- WGC3Denum type,
+ virtual void TexSubImage2D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
const void* pixels) OVERRIDE {
EXPECT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
EXPECT_EQ(0, level);
@@ -131,7 +124,7 @@ class TestWebGraphicsContext3DTextureUpload : public TestWebGraphicsContext3D {
// be 0x2.
const unsigned int stride =
RoundUp(bytes_per_pixel * width, unpack_alignment_);
- for (WGC3Dsizei row = 0; row < height; ++row) {
+ for (GLsizei row = 0; row < height; ++row) {
const uint8* row_bytes =
bytes + (xoffset * bytes_per_pixel + (yoffset + row) * stride);
EXPECT_EQ(0x1, row_bytes[0]);
@@ -147,7 +140,7 @@ class TestWebGraphicsContext3DTextureUpload : public TestWebGraphicsContext3D {
unsigned result_available_;
unsigned unpack_alignment_;
- DISALLOW_COPY_AND_ASSIGN(TestWebGraphicsContext3DTextureUpload);
+ DISALLOW_COPY_AND_ASSIGN(TextureUploadTestContext);
};
void UploadTexture(TextureUploader* uploader,
@@ -163,19 +156,17 @@ void UploadTexture(TextureUploader* uploader,
}
TEST(TextureUploaderTest, NumBlockingUploads) {
- scoped_ptr<TestWebGraphicsContext3DTextureUpload> fake_context(
- new TestWebGraphicsContext3DTextureUpload);
- scoped_ptr<TextureUploader> uploader =
- TextureUploader::Create(fake_context.get(), false, false);
+ TextureUploadTestContext context;
+ scoped_ptr<TextureUploader> uploader = TextureUploader::Create(&context);
- fake_context->SetResultAvailable(0);
+ context.SetResultAvailable(0);
EXPECT_EQ(0u, uploader->NumBlockingUploads());
UploadTexture(uploader.get(), RGBA_8888, gfx::Size(), NULL);
EXPECT_EQ(1u, uploader->NumBlockingUploads());
UploadTexture(uploader.get(), RGBA_8888, gfx::Size(), NULL);
EXPECT_EQ(2u, uploader->NumBlockingUploads());
- fake_context->SetResultAvailable(1);
+ context.SetResultAvailable(1);
EXPECT_EQ(0u, uploader->NumBlockingUploads());
UploadTexture(uploader.get(), RGBA_8888, gfx::Size(), NULL);
EXPECT_EQ(0u, uploader->NumBlockingUploads());
@@ -185,12 +176,10 @@ TEST(TextureUploaderTest, NumBlockingUploads) {
}
TEST(TextureUploaderTest, MarkPendingUploadsAsNonBlocking) {
- scoped_ptr<TestWebGraphicsContext3DTextureUpload> fake_context(
- new TestWebGraphicsContext3DTextureUpload);
- scoped_ptr<TextureUploader> uploader =
- TextureUploader::Create(fake_context.get(), false, false);
+ TextureUploadTestContext context;
+ scoped_ptr<TextureUploader> uploader = TextureUploader::Create(&context);
- fake_context->SetResultAvailable(0);
+ context.SetResultAvailable(0);
EXPECT_EQ(0u, uploader->NumBlockingUploads());
UploadTexture(uploader.get(), RGBA_8888, gfx::Size(), NULL);
UploadTexture(uploader.get(), RGBA_8888, gfx::Size(), NULL);
@@ -201,7 +190,7 @@ TEST(TextureUploaderTest, MarkPendingUploadsAsNonBlocking) {
UploadTexture(uploader.get(), RGBA_8888, gfx::Size(), NULL);
EXPECT_EQ(1u, uploader->NumBlockingUploads());
- fake_context->SetResultAvailable(1);
+ context.SetResultAvailable(1);
EXPECT_EQ(0u, uploader->NumBlockingUploads());
UploadTexture(uploader.get(), RGBA_8888, gfx::Size(), NULL);
uploader->MarkPendingUploadsAsNonBlocking();
@@ -209,10 +198,9 @@ TEST(TextureUploaderTest, MarkPendingUploadsAsNonBlocking) {
}
TEST(TextureUploaderTest, UploadContentsTest) {
- scoped_ptr<TestWebGraphicsContext3DTextureUpload> fake_context(
- new TestWebGraphicsContext3DTextureUpload);
- scoped_ptr<TextureUploader> uploader =
- TextureUploader::Create(fake_context.get(), false, false);
+ TextureUploadTestContext context;
+ scoped_ptr<TextureUploader> uploader = TextureUploader::Create(&context);
+
uint8 buffer[256 * 256 * 4];
// Upload a tightly packed 256x256 RGBA texture.
diff --git a/chromium/cc/trees/damage_tracker.cc b/chromium/cc/trees/damage_tracker.cc
index 64b15867e07..9895458c99a 100644
--- a/chromium/cc/trees/damage_tracker.cc
+++ b/chromium/cc/trees/damage_tracker.cc
@@ -21,8 +21,7 @@ scoped_ptr<DamageTracker> DamageTracker::Create() {
}
DamageTracker::DamageTracker()
- : current_rect_history_(new RectMap),
- next_rect_history_(new RectMap) {}
+ : mailboxId_(0) {}
DamageTracker::~DamageTracker() {}
@@ -52,8 +51,7 @@ void DamageTracker::UpdateDamageTrackingState(
bool target_surface_property_changed_only_from_descendant,
gfx::Rect target_surface_content_rect,
LayerImpl* target_surface_mask_layer,
- const FilterOperations& filters,
- SkImageFilter* filter) {
+ const FilterOperations& filters) {
//
// This function computes the "damage rect" of a target surface, and updates
// the state that is used to correctly track damage across frames. The damage
@@ -106,23 +104,23 @@ void DamageTracker::UpdateDamageTrackingState(
// - See comments in the rest of the code to see what exactly is considered a
// "change" in a layer/surface.
//
- // - To correctly manage exposed rects, two RectMaps are maintained:
+ // - To correctly manage exposed rects, SortedRectMap is maintained:
//
- // 1. The "current" map contains all the layer bounds that contributed to
+ // 1. All existing rects from the previous frame are marked as
+ // not updated.
+ // 2. The map contains all the layer bounds that contributed to
// the previous frame (even outside the previous damaged area). If a
// layer changes or does not exist anymore, those regions are then
// exposed and damage the target surface. As the algorithm progresses,
- // entries are removed from the map until it has only leftover layers
- // that no longer exist.
- //
- // 2. The "next" map starts out empty, and as the algorithm progresses,
- // every layer/surface that contributes to the surface is added to the
- // map.
+ // entries are updated in the map until only leftover layers
+ // that no longer exist stay marked not updated.
//
- // 3. After the damage rect is computed, the two maps are swapped, so
- // that the damage tracker is ready for the next frame.
+ // 3. After the damage rect is computed, the leftover not marked regions
+ // in a map are used to compute are damaged by deleted layers and
+ // erased from map.
//
+ PrepareRectHistoryForUpdate();
// These functions cannot be bypassed with early-exits, even if we know what
// the damage will be for this frame, because we need to update the damage
// tracker state to correctly track the next frame.
@@ -143,43 +141,35 @@ 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.HasFilterThatMovesPixels()) {
- ExpandRectWithFilters(&damage_rect_for_this_update, filters);
- } else if (filter) {
+ 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);
}
}
// Damage accumulates until we are notified that we actually did draw on that
// frame.
current_damage_rect_.Union(damage_rect_for_this_update);
-
- // The next history map becomes the current map for the next frame. Note this
- // must happen every frame to correctly track changes, even if damage
- // accumulates over multiple frames before actually being drawn.
- swap(current_rect_history_, next_rect_history_);
}
-gfx::RectF DamageTracker::RemoveRectFromCurrentFrame(int layer_id,
- bool* layer_is_new) {
- RectMap::iterator iter = current_rect_history_->find(layer_id);
- *layer_is_new = iter == current_rect_history_->end();
- if (*layer_is_new)
- return gfx::RectF();
+DamageTracker::RectMapData& DamageTracker::RectDataForLayer(
+ int layer_id,
+ bool* layer_is_new) {
- gfx::RectF ret = iter->second;
- current_rect_history_->erase(iter);
- return ret;
-}
+ RectMapData data(layer_id);
+
+ SortedRectMap::iterator it = std::lower_bound(rect_history_.begin(),
+ rect_history_.end(), data);
+
+ if (it == rect_history_.end() || it->layer_id_ != layer_id) {
+ *layer_is_new = true;
+ it = rect_history_.insert(it, data);
+ }
-void DamageTracker::SaveRectForNextFrame(int layer_id,
- const gfx::RectF& target_space_rect) {
- // This layer should not yet exist in next frame's history.
- DCHECK_GT(layer_id, 0);
- DCHECK(next_rect_history_->find(layer_id) == next_rect_history_->end());
- (*next_rect_history_)[layer_id] = target_space_rect;
+ return *it;
}
gfx::RectF DamageTracker::TrackDamageFromActiveLayers(
@@ -226,32 +216,48 @@ gfx::RectF DamageTracker::TrackDamageFromSurfaceMask(
return damage_rect;
}
+void DamageTracker::PrepareRectHistoryForUpdate() {
+ mailboxId_++;
+}
+
gfx::RectF DamageTracker::TrackDamageFromLeftoverRects() {
// After computing damage for all active layers, any leftover items in the
// current rect history correspond to layers/surfaces that no longer exist.
// So, these regions are now exposed on the target surface.
gfx::RectF damage_rect = gfx::RectF();
+ SortedRectMap::iterator cur_pos = rect_history_.begin();
+ SortedRectMap::iterator copy_pos = cur_pos;
+
+ // Loop below basically implements std::remove_if loop with and extra
+ // processing (adding deleted rect to damage_rect) for deleted items.
+ // cur_pos iterator runs through all elements of the vector, but copy_pos
+ // always points to the element after the last not deleted element. If new
+ // not deleted element found then it is copied to the *copy_pos and copy_pos
+ // moved to the next position.
+ // If there are no deleted elements then copy_pos iterator is in sync with
+ // cur_pos and no copy happens.
+ while (cur_pos < rect_history_.end()) {
+ if (cur_pos->mailboxId_ == mailboxId_) {
+ if (cur_pos != copy_pos)
+ *copy_pos = *cur_pos;
+
+ ++copy_pos;
+ } else {
+ damage_rect.Union(cur_pos->rect_);
+ }
- for (RectMap::iterator it = current_rect_history_->begin();
- it != current_rect_history_->end();
- ++it)
- damage_rect.Union(it->second);
+ ++cur_pos;
+ }
- current_rect_history_->clear();
+ if (copy_pos != rect_history_.end())
+ rect_history_.erase(copy_pos, rect_history_.end());
- return damage_rect;
-}
+ // If the vector has excessive storage, shrink it
+ if (rect_history_.capacity() > rect_history_.size() * 4)
+ SortedRectMap(rect_history_).swap(rect_history_);
-static bool LayerNeedsToRedrawOntoItsTargetSurface(LayerImpl* layer) {
- // If the layer does NOT own a surface but has SurfacePropertyChanged,
- // this means that its target surface is affected and needs to be redrawn.
- // However, if the layer DOES own a surface, then the SurfacePropertyChanged
- // flag should not be used here, because that flag represents whether the
- // layer's surface has changed.
- if (layer->render_surface())
- return layer->LayerPropertyChanged();
- return layer->LayerPropertyChanged() || layer->LayerSurfacePropertyChanged();
+ return damage_rect;
}
void DamageTracker::ExtendDamageForLayer(LayerImpl* layer,
@@ -275,15 +281,15 @@ void DamageTracker::ExtendDamageForLayer(LayerImpl* layer,
// ancestor surface, ExtendDamageForRenderSurface() must be called instead.
bool layer_is_new = false;
- gfx::RectF old_rect_in_target_space =
- RemoveRectFromCurrentFrame(layer->id(), &layer_is_new);
+ RectMapData& data = RectDataForLayer(layer->id(), &layer_is_new);
+ gfx::RectF old_rect_in_target_space = data.rect_;
gfx::RectF rect_in_target_space = MathUtil::MapClippedRect(
layer->draw_transform(),
gfx::RectF(gfx::PointF(), layer->content_bounds()));
- SaveRectForNextFrame(layer->id(), rect_in_target_space);
+ data.Update(rect_in_target_space, mailboxId_);
- if (layer_is_new || LayerNeedsToRedrawOntoItsTargetSurface(layer)) {
+ if (layer_is_new || layer->LayerPropertyChanged()) {
// If a layer is new or has changed, then its entire layer rect affects the
// target surface.
target_damage_rect->Union(rect_in_target_space);
@@ -322,18 +328,16 @@ void DamageTracker::ExtendDamageForRenderSurface(
RenderSurfaceImpl* render_surface = layer->render_surface();
bool surface_is_new = false;
- gfx::RectF old_surface_rect = RemoveRectFromCurrentFrame(layer->id(),
- &surface_is_new);
+ RectMapData& data = RectDataForLayer(layer->id(), &surface_is_new);
+ gfx::RectF old_surface_rect = data.rect_;
// The drawableContextRect() already includes the replica if it exists.
gfx::RectF surface_rect_in_target_space =
render_surface->DrawableContentRect();
- SaveRectForNextFrame(layer->id(), surface_rect_in_target_space);
+ data.Update(surface_rect_in_target_space, mailboxId_);
gfx::RectF damage_rect_in_local_space;
- if (surface_is_new ||
- render_surface->SurfacePropertyChanged() ||
- layer->LayerSurfacePropertyChanged()) {
+ if (surface_is_new || render_surface->SurfacePropertyChanged()) {
// The entire surface contributes damage.
damage_rect_in_local_space = render_surface->content_rect();
@@ -367,14 +371,15 @@ void DamageTracker::ExtendDamageForRenderSurface(
LayerImpl* replica_mask_layer = layer->replica_layer()->mask_layer();
bool replica_is_new = false;
- RemoveRectFromCurrentFrame(replica_mask_layer->id(), &replica_is_new);
+ RectMapData& data =
+ RectDataForLayer(replica_mask_layer->id(), &replica_is_new);
const gfx::Transform& replica_draw_transform =
render_surface->replica_draw_transform();
gfx::RectF replica_mask_layer_rect = MathUtil::MapClippedRect(
replica_draw_transform,
gfx::RectF(gfx::PointF(), replica_mask_layer->bounds()));
- SaveRectForNextFrame(replica_mask_layer->id(), replica_mask_layer_rect);
+ data.Update(replica_mask_layer_rect, mailboxId_);
// In the current implementation, a change in the replica mask damages the
// entire replica region.
diff --git a/chromium/cc/trees/damage_tracker.h b/chromium/cc/trees/damage_tracker.h
index ce72fcc842c..37a1900f788 100644
--- a/chromium/cc/trees/damage_tracker.h
+++ b/chromium/cc/trees/damage_tracker.h
@@ -6,7 +6,6 @@
#define CC_TREES_DAMAGE_TRACKER_H_
#include <vector>
-#include "base/containers/hash_tables.h"
#include "base/memory/scoped_ptr.h"
#include "cc/base/cc_export.h"
#include "cc/layers/layer_lists.h"
@@ -40,8 +39,7 @@ class CC_EXPORT DamageTracker {
bool target_surface_property_changed_only_from_descendant,
gfx::Rect target_surface_content_rect,
LayerImpl* target_surface_mask_layer,
- const FilterOperations& filters,
- SkImageFilter* filter);
+ const FilterOperations& filters);
gfx::RectF current_damage_rect() { return current_damage_rect_; }
@@ -54,22 +52,36 @@ class CC_EXPORT DamageTracker {
gfx::RectF TrackDamageFromSurfaceMask(LayerImpl* target_surface_mask_layer);
gfx::RectF TrackDamageFromLeftoverRects();
- gfx::RectF RemoveRectFromCurrentFrame(int layer_id, bool* layer_is_new);
- void SaveRectForNextFrame(int layer_id, const gfx::RectF& target_space_rect);
+ void PrepareRectHistoryForUpdate();
// These helper functions are used only in TrackDamageFromActiveLayers().
void ExtendDamageForLayer(LayerImpl* layer, gfx::RectF* target_damage_rect);
void ExtendDamageForRenderSurface(LayerImpl* layer,
gfx::RectF* target_damage_rect);
- // To correctly track exposed regions, two hashtables of rects are maintained.
- // The "current" map is used to compute exposed regions of the current frame,
- // while the "next" map is used to collect layer rects that are used in the
- // next frame.
- typedef base::hash_map<int, gfx::RectF> RectMap;
- scoped_ptr<RectMap> current_rect_history_;
- scoped_ptr<RectMap> next_rect_history_;
+ struct RectMapData {
+ RectMapData() : layer_id_(0), mailboxId_(0) {}
+ explicit RectMapData(int layer_id) : layer_id_(layer_id), mailboxId_(0) {}
+ void Update(const gfx::RectF& rect, unsigned int mailboxId) {
+ mailboxId_ = mailboxId;
+ rect_ = rect;
+ }
+ bool operator < (const RectMapData& other) const {
+ return layer_id_ < other.layer_id_;
+ }
+
+ int layer_id_;
+ unsigned int mailboxId_;
+ gfx::RectF rect_;
+ };
+ typedef std::vector<RectMapData> SortedRectMap;
+
+ RectMapData& RectDataForLayer(int layer_id, bool* layer_is_new);
+
+ SortedRectMap rect_history_;
+
+ unsigned int mailboxId_;
gfx::RectF current_damage_rect_;
DISALLOW_COPY_AND_ASSIGN(DamageTracker);
diff --git a/chromium/cc/trees/damage_tracker_unittest.cc b/chromium/cc/trees/damage_tracker_unittest.cc
index 8a862074410..7fb8720b83d 100644
--- a/chromium/cc/trees/damage_tracker_unittest.cc
+++ b/chromium/cc/trees/damage_tracker_unittest.cc
@@ -63,8 +63,7 @@ void EmulateDrawingOneFrame(LayerImpl* root) {
target_surface->SurfacePropertyChangedOnlyFromDescendant(),
target_surface->content_rect(),
render_surface_layer_list[i]->mask_layer(),
- render_surface_layer_list[i]->filters(),
- render_surface_layer_list[i]->filter().get());
+ render_surface_layer_list[i]->filters());
}
root->ResetAllChangeTrackingForSubtree();
@@ -446,10 +445,12 @@ TEST_F(DamageTrackerTest, VerifyDamageForImageFilter) {
skia::RefPtr<SkImageFilter> filter =
skia::AdoptRef(new SkBlurImageFilter(SkIntToScalar(2),
SkIntToScalar(2)));
+ FilterOperations filters;
+ filters.Append(FilterOperation::CreateReferenceFilter(filter));
// Setting the filter will damage the whole surface.
ClearDamageForAllSurfaces(root.get());
- child->SetFilter(filter);
+ child->SetFilters(filters);
EmulateDrawingOneFrame(root.get());
root_damage_rect =
root->render_surface()->damage_tracker()->current_damage_rect();
@@ -1297,8 +1298,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForEmptyLayerList) {
false,
gfx::Rect(),
NULL,
- FilterOperations(),
- NULL);
+ FilterOperations());
gfx::RectF damage_rect =
target_surface->damage_tracker()->current_damage_rect();
diff --git a/chromium/cc/trees/layer_sorter_unittest.cc b/chromium/cc/trees/layer_sorter_unittest.cc
index b1d7b819fc5..6669100fccf 100644
--- a/chromium/cc/trees/layer_sorter_unittest.cc
+++ b/chromium/cc/trees/layer_sorter_unittest.cc
@@ -177,7 +177,7 @@ TEST(LayerSorterTest, LayersUnderPathologicalPerspectiveTransform) {
// layer_a. When it is not clipped, its bounds will actually incorrectly
// appear much smaller and the correct sorting dependency will not be found.
gfx::Transform transform_b;
- transform_b.Translate3d(0.0, 0.0, 0.7);
+ transform_b.Translate3d(0.f, 0.f, 0.7f);
transform_b.RotateAboutYAxis(45.0);
transform_b.Translate(-5.0, -5.0);
LayerShape layer_b(10.f, 10.f, perspective_matrix * transform_b);
@@ -287,7 +287,7 @@ TEST(LayerSorterTest, VerifyConcidentLayerPrecisionLossResultsInDocumentOrder) {
// in calculated order.
gfx::Transform BehindMatrix;
- BehindMatrix.Translate3d(0.0, 0.0, 0.999999);
+ BehindMatrix.Translate3d(0.f, 0.f, 0.999999f);
BehindMatrix.RotateAboutXAxis(38.5);
BehindMatrix.RotateAboutYAxis(77.0);
gfx::Transform FrontMatrix;
diff --git a/chromium/cc/trees/layer_tree_host.cc b/chromium/cc/trees/layer_tree_host.cc
index f8f0d614440..74321976ff3 100644
--- a/chromium/cc/trees/layer_tree_host.cc
+++ b/chromium/cc/trees/layer_tree_host.cc
@@ -6,7 +6,9 @@
#include <algorithm>
#include <stack>
+#include <string>
+#include "base/atomic_sequence_num.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/debug/trace_event.h"
@@ -17,7 +19,6 @@
#include "cc/animation/animation_registrar.h"
#include "cc/animation/layer_animation_controller.h"
#include "cc/base/math_util.h"
-#include "cc/debug/benchmark_instrumentation.h"
#include "cc/debug/devtools_instrumentation.h"
#include "cc/debug/overdraw_metrics.h"
#include "cc/debug/rendering_stats_instrumentation.h"
@@ -29,7 +30,7 @@
#include "cc/layers/painted_scrollbar_layer.h"
#include "cc/layers/render_surface.h"
#include "cc/resources/prioritized_resource_manager.h"
-#include "cc/resources/ui_resource_client.h"
+#include "cc/resources/ui_resource_request.h"
#include "cc/trees/layer_tree_host_client.h"
#include "cc/trees/layer_tree_host_common.h"
#include "cc/trees/layer_tree_host_impl.h"
@@ -41,7 +42,7 @@
#include "ui/gfx/size_conversions.h"
namespace {
-static int s_num_layer_tree_instances;
+static base::StaticAtomicSequenceNumber s_layer_tree_host_sequence_number;
}
namespace cc {
@@ -49,7 +50,6 @@ namespace cc {
RendererCapabilities::RendererCapabilities()
: best_texture_format(RGBA_8888),
using_partial_swap(false),
- using_set_visibility(false),
using_egl_image(false),
allow_partial_texture_updates(false),
using_offscreen_context3d(false),
@@ -61,54 +61,38 @@ RendererCapabilities::RendererCapabilities()
RendererCapabilities::~RendererCapabilities() {}
-UIResourceRequest::UIResourceRequest(UIResourceRequestType type,
- UIResourceId id)
- : type_(type), id_(id) {}
-
-UIResourceRequest::UIResourceRequest(UIResourceRequestType type,
- UIResourceId id,
- const UIResourceBitmap& bitmap)
- : type_(type), id_(id), bitmap_(new UIResourceBitmap(bitmap)) {}
-
-UIResourceRequest::UIResourceRequest(const UIResourceRequest& request) {
- (*this) = request;
-}
-
-UIResourceRequest& UIResourceRequest::operator=(
- const UIResourceRequest& request) {
- type_ = request.type_;
- id_ = request.id_;
- if (request.bitmap_) {
- bitmap_ = make_scoped_ptr(new UIResourceBitmap(*request.bitmap_.get()));
- } else {
- bitmap_.reset();
- }
-
- return *this;
-}
-
-UIResourceRequest::~UIResourceRequest() {}
-
-bool LayerTreeHost::AnyLayerTreeHostInstanceExists() {
- return s_num_layer_tree_instances > 0;
-}
-
-scoped_ptr<LayerTreeHost> LayerTreeHost::Create(
+scoped_ptr<LayerTreeHost> LayerTreeHost::CreateThreaded(
LayerTreeHostClient* client,
+ SharedBitmapManager* manager,
const LayerTreeSettings& settings,
scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner) {
- scoped_ptr<LayerTreeHost> layer_tree_host(new LayerTreeHost(client,
- settings));
- if (!layer_tree_host->Initialize(impl_task_runner))
+ DCHECK(impl_task_runner);
+ scoped_ptr<LayerTreeHost> layer_tree_host(
+ new LayerTreeHost(client, manager, settings));
+ if (!layer_tree_host->InitializeThreaded(impl_task_runner))
+ return scoped_ptr<LayerTreeHost>();
+ return layer_tree_host.Pass();
+}
+
+scoped_ptr<LayerTreeHost> LayerTreeHost::CreateSingleThreaded(
+ LayerTreeHostClient* client,
+ LayerTreeHostSingleThreadClient* single_thread_client,
+ SharedBitmapManager* manager,
+ const LayerTreeSettings& settings) {
+ scoped_ptr<LayerTreeHost> layer_tree_host(
+ new LayerTreeHost(client, manager, settings));
+ if (!layer_tree_host->InitializeSingleThreaded(single_thread_client))
return scoped_ptr<LayerTreeHost>();
return layer_tree_host.Pass();
}
-static int s_next_tree_id = 1;
-LayerTreeHost::LayerTreeHost(LayerTreeHostClient* client,
- const LayerTreeSettings& settings)
- : next_ui_resource_id_(1),
+LayerTreeHost::LayerTreeHost(
+ LayerTreeHostClient* client,
+ SharedBitmapManager* manager,
+ const LayerTreeSettings& settings)
+ : micro_benchmark_controller_(this),
+ next_ui_resource_id_(1),
animating_(false),
needs_full_tree_sync_(true),
needs_filter_context_(false),
@@ -132,20 +116,24 @@ LayerTreeHost::LayerTreeHost(LayerTreeHostClient* client,
partial_texture_update_requests_(0),
in_paint_layer_contents_(false),
total_frames_used_for_lcd_text_metrics_(0),
- tree_id_(s_next_tree_id++) {
+ id_(s_layer_tree_host_sequence_number.GetNext() + 1),
+ next_commit_forces_redraw_(false),
+ shared_bitmap_manager_(manager) {
if (settings_.accelerated_animation_enabled)
animation_registrar_ = AnimationRegistrar::Create();
- s_num_layer_tree_instances++;
rendering_stats_instrumentation_->set_record_rendering_stats(
debug_state_.RecordRenderingStats());
}
-bool LayerTreeHost::Initialize(
+bool LayerTreeHost::InitializeThreaded(
scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner) {
- if (impl_task_runner.get())
- return InitializeProxy(ThreadProxy::Create(this, impl_task_runner));
- else
- return InitializeProxy(SingleThreadProxy::Create(this));
+ return InitializeProxy(ThreadProxy::Create(this, impl_task_runner));
+}
+
+bool LayerTreeHost::InitializeSingleThreaded(
+ LayerTreeHostSingleThreadClient* single_thread_client) {
+ return InitializeProxy(
+ SingleThreadProxy::Create(this, single_thread_client));
}
bool LayerTreeHost::InitializeForTesting(scoped_ptr<Proxy> proxy_for_testing) {
@@ -177,11 +165,6 @@ LayerTreeHost::~LayerTreeHost() {
proxy_->Stop();
}
- s_num_layer_tree_instances--;
- RateLimiterMap::iterator it = rate_limiters_.begin();
- if (it != rate_limiters_.end())
- it->second->Stop();
-
if (root_layer_.get()) {
// The layer tree must be destroyed before the layer tree host. We've
// made a contract with our animation controllers that the registrar
@@ -194,6 +177,10 @@ void LayerTreeHost::SetLayerTreeHostClientReady() {
proxy_->SetLayerTreeHostClientReady();
}
+static void LayerTreeHostOnOutputSurfaceCreatedCallback(Layer* layer) {
+ layer->OnOutputSurfaceCreated();
+}
+
LayerTreeHost::CreateResult
LayerTreeHost::OnCreateAndInitializeOutputSurfaceAttempted(bool success) {
TRACE_EVENT1("cc",
@@ -205,24 +192,19 @@ LayerTreeHost::OnCreateAndInitializeOutputSurfaceAttempted(bool success) {
if (success) {
output_surface_lost_ = false;
- // Update settings_ based on partial update capability.
- size_t max_partial_texture_updates = 0;
- if (proxy_->GetRendererCapabilities().allow_partial_texture_updates &&
- !settings_.impl_side_painting) {
- max_partial_texture_updates = std::min(
- settings_.max_partial_texture_updates,
- proxy_->MaxPartialTextureUpdates());
- }
- settings_.max_partial_texture_updates = max_partial_texture_updates;
-
- if (!contents_texture_manager_ &&
- (!settings_.impl_side_painting || !settings_.solid_color_scrollbars)) {
+ if (!contents_texture_manager_ && !settings_.impl_side_painting) {
contents_texture_manager_ =
PrioritizedResourceManager::Create(proxy_.get());
surface_memory_placeholder_ =
contents_texture_manager_->CreateTexture(gfx::Size(), RGBA_8888);
}
+ if (root_layer()) {
+ LayerTreeHostCommon::CallFunctionForSubtree(
+ root_layer(),
+ base::Bind(&LayerTreeHostOnOutputSurfaceCreatedCallback));
+ }
+
client_->DidInitializeOutputSurface(true);
return CreateSucceeded;
}
@@ -257,8 +239,8 @@ void LayerTreeHost::AcquireLayerTextures() {
proxy_->AcquireLayerTextures();
}
-void LayerTreeHost::DidBeginFrame() {
- client_->DidBeginFrame();
+void LayerTreeHost::DidBeginMainFrame() {
+ client_->DidBeginMainFrame();
}
void LayerTreeHost::UpdateClientAnimations(base::TimeTicks frame_begin_time) {
@@ -309,7 +291,8 @@ void LayerTreeHost::FinishCommitOnImplThread(LayerTreeHostImpl* host_impl) {
host_impl->set_max_memory_needed_bytes(
contents_texture_manager_->MaxMemoryNeededBytes());
- contents_texture_manager_->UpdateBackingsInDrawingImplTree();
+ contents_texture_manager_->UpdateBackingsState(
+ host_impl->resource_provider());
}
// In impl-side painting, synchronize to the pending tree so that it has
@@ -322,11 +305,17 @@ void LayerTreeHost::FinishCommitOnImplThread(LayerTreeHostImpl* host_impl) {
DCHECK(!host_impl->pending_tree());
host_impl->CreatePendingTree();
sync_tree = host_impl->pending_tree();
+ if (next_commit_forces_redraw_)
+ sync_tree->ForceRedrawNextActivation();
} else {
+ if (next_commit_forces_redraw_)
+ host_impl->SetFullRootLayerDamage();
contents_texture_manager_->ReduceMemory(host_impl->resource_provider());
sync_tree = host_impl->active_tree();
}
+ next_commit_forces_redraw_ = false;
+
sync_tree->set_source_frame_number(source_frame_number());
if (needs_full_tree_sync_)
@@ -384,8 +373,8 @@ void LayerTreeHost::FinishCommitOnImplThread(LayerTreeHostImpl* host_impl) {
min_page_scale_factor_,
max_page_scale_factor_);
sync_tree->SetPageScaleDelta(page_scale_delta / sent_page_scale_delta);
- sync_tree->SetLatencyInfo(latency_info_);
- latency_info_.Clear();
+
+ sync_tree->PassSwapPromises(&swap_promise_list_);
host_impl->SetViewportSize(device_viewport_size_);
host_impl->SetOverdrawBottomHeight(overdraw_bottom_height_);
@@ -425,8 +414,11 @@ void LayerTreeHost::FinishCommitOnImplThread(LayerTreeHostImpl* host_impl) {
// If we're not in impl-side painting, the tree is immediately
// considered active.
sync_tree->DidBecomeActive();
+ devtools_instrumentation::didActivateLayerTree(id_, source_frame_number_);
}
+ micro_benchmark_controller_.ScheduleImplBenchmarks(host_impl);
+
source_frame_number_++;
}
@@ -462,7 +454,10 @@ scoped_ptr<LayerTreeHostImpl> LayerTreeHost::CreateLayerTreeHostImpl(
LayerTreeHostImpl::Create(settings_,
client,
proxy_.get(),
- rendering_stats_instrumentation_.get());
+ rendering_stats_instrumentation_.get(),
+ shared_bitmap_manager_,
+ id_);
+ shared_bitmap_manager_ = NULL;
if (settings_.calculate_top_controls_position &&
host_impl->top_controls_manager()) {
top_controls_manager_weak_ptr_ =
@@ -525,11 +520,14 @@ const RendererCapabilities& LayerTreeHost::GetRendererCapabilities() const {
}
void LayerTreeHost::SetNeedsAnimate() {
- DCHECK(proxy_->HasImplThread());
proxy_->SetNeedsAnimate();
+ NotifySwapPromiseMonitorsOfSetNeedsCommit();
}
-void LayerTreeHost::SetNeedsUpdateLayers() { proxy_->SetNeedsUpdateLayers(); }
+void LayerTreeHost::SetNeedsUpdateLayers() {
+ proxy_->SetNeedsUpdateLayers();
+ NotifySwapPromiseMonitorsOfSetNeedsCommit();
+}
void LayerTreeHost::SetNeedsCommit() {
if (!prepaint_callback_.IsCancelled()) {
@@ -539,6 +537,7 @@ void LayerTreeHost::SetNeedsCommit() {
prepaint_callback_.Cancel();
}
proxy_->SetNeedsCommit();
+ NotifySwapPromiseMonitorsOfSetNeedsCommit();
}
void LayerTreeHost::SetNeedsFullTreeSync() {
@@ -552,18 +551,25 @@ void LayerTreeHost::SetNeedsRedraw() {
void LayerTreeHost::SetNeedsRedrawRect(gfx::Rect damage_rect) {
proxy_->SetNeedsRedraw(damage_rect);
- if (!proxy_->HasImplThread())
- client_->ScheduleComposite();
}
bool LayerTreeHost::CommitRequested() const {
return proxy_->CommitRequested();
}
+bool LayerTreeHost::BeginMainFrameRequested() const {
+ return proxy_->BeginMainFrameRequested();
+}
+
+
void LayerTreeHost::SetNextCommitWaitsForActivation() {
proxy_->SetNextCommitWaitsForActivation();
}
+void LayerTreeHost::SetNextCommitForcesRedraw() {
+ next_commit_forces_redraw_ = true;
+}
+
void LayerTreeHost::SetAnimationEvents(scoped_ptr<AnimationEventsVector> events,
base::Time wall_clock_time) {
DCHECK(proxy_->IsMainThread());
@@ -588,6 +594,10 @@ void LayerTreeHost::SetAnimationEvents(scoped_ptr<AnimationEventsVector> events,
wall_clock_time.ToDoubleT());
break;
+ case AnimationEvent::Aborted:
+ (*iter).second->NotifyAnimationAborted((*events)[event_index]);
+ break;
+
case AnimationEvent::PropertyUpdate:
(*iter).second->NotifyAnimationPropertyUpdate((*events)[event_index]);
break;
@@ -677,8 +687,9 @@ void LayerTreeHost::SetOverhangBitmap(const SkBitmap& bitmap) {
bitmap_copy.setImmutable();
}
- overhang_ui_resource_ = ScopedUIResource::Create(
- this, UIResourceBitmap(bitmap_copy, UIResourceBitmap::REPEAT));
+ UIResourceBitmap overhang_bitmap(bitmap_copy);
+ overhang_bitmap.SetWrapMode(UIResourceBitmap::REPEAT);
+ overhang_ui_resource_ = ScopedUIResource::Create(this, overhang_bitmap);
}
void LayerTreeHost::SetVisible(bool visible) {
@@ -690,10 +701,6 @@ void LayerTreeHost::SetVisible(bool visible) {
proxy_->SetVisible(visible);
}
-void LayerTreeHost::SetLatencyInfo(const ui::LatencyInfo& latency_info) {
- latency_info_.MergeWith(latency_info);
-}
-
void LayerTreeHost::StartPageScaleAnimation(gfx::Vector2d target_offset,
bool use_anchor,
float scale,
@@ -719,10 +726,6 @@ void LayerTreeHost::Composite(base::TimeTicks frame_begin_time) {
SetNeedsCommit();
}
-void LayerTreeHost::ScheduleComposite() {
- client_->ScheduleComposite();
-}
-
bool LayerTreeHost::InitializeOutputSurfaceIfNeeded() {
if (!output_surface_can_be_initialized_)
return false;
@@ -740,7 +743,11 @@ bool LayerTreeHost::UpdateLayers(ResourceUpdateQueue* queue) {
DCHECK(!root_layer()->parent());
- return UpdateLayers(root_layer(), queue);
+ bool result = UpdateLayers(root_layer(), queue);
+
+ micro_benchmark_controller_.DidUpdateLayers();
+
+ return result;
}
static Layer* FindFirstScrollableLayer(Layer* layer) {
@@ -777,10 +784,8 @@ bool LayerTreeHost::UsingSharedMemoryResources() {
bool LayerTreeHost::UpdateLayers(Layer* root_layer,
ResourceUpdateQueue* queue) {
- TRACE_EVENT1(benchmark_instrumentation::kCategory,
- benchmark_instrumentation::kLayerTreeHostUpdateLayers,
- benchmark_instrumentation::kSourceFrameNumber,
- source_frame_number());
+ TRACE_EVENT1("cc", "LayerTreeHost::UpdateLayers",
+ "source_frame_number", source_frame_number());
RenderSurfaceLayerList update_list;
{
@@ -797,6 +802,7 @@ bool LayerTreeHost::UpdateLayers(Layer* root_layer,
}
TRACE_EVENT0("cc", "LayerTreeHost::UpdateLayers::CalcDrawProps");
+ bool can_render_to_separate_surface = true;
LayerTreeHostCommon::CalcDrawPropsMainInputs inputs(
root_layer,
device_viewport_size(),
@@ -806,6 +812,7 @@ bool LayerTreeHost::UpdateLayers(Layer* root_layer,
page_scale_layer,
GetRendererCapabilities().max_texture_size,
settings_.can_use_lcd_text,
+ can_render_to_separate_surface,
settings_.layer_transforms_should_scale_layer_contents,
&update_list);
LayerTreeHostCommon::CalculateDrawProperties(&inputs);
@@ -888,11 +895,10 @@ void LayerTreeHost::SetPrioritiesForSurfaces(size_t surface_memory_bytes) {
void LayerTreeHost::SetPrioritiesForLayers(
const RenderSurfaceLayerList& update_list) {
- // Use BackToFront since it's cheap and this isn't order-dependent.
typedef LayerIterator<Layer,
RenderSurfaceLayerList,
RenderSurface,
- LayerIteratorActions::BackToFront> LayerIteratorType;
+ LayerIteratorActions::FrontToBack> LayerIteratorType;
PriorityCalculator calculator;
LayerIteratorType end = LayerIteratorType::End(&update_list);
@@ -973,10 +979,6 @@ void LayerTreeHost::PaintMasksForRenderSurface(Layer* render_surface_layer,
Layer* mask_layer = render_surface_layer->mask_layer();
if (mask_layer) {
- devtools_instrumentation::ScopedLayerTreeTask
- update_layer(devtools_instrumentation::kUpdateLayer,
- mask_layer->id(),
- id());
*did_paint_content |= mask_layer->Update(queue, NULL);
*need_more_updates |= mask_layer->NeedMoreUpdates();
}
@@ -985,10 +987,6 @@ void LayerTreeHost::PaintMasksForRenderSurface(Layer* render_surface_layer,
render_surface_layer->replica_layer() ?
render_surface_layer->replica_layer()->mask_layer() : NULL;
if (replica_mask_layer) {
- devtools_instrumentation::ScopedLayerTreeTask
- update_layer(devtools_instrumentation::kUpdateLayer,
- replica_mask_layer->id(),
- id());
*did_paint_content |= replica_mask_layer->Update(queue, NULL);
*need_more_updates |= replica_mask_layer->NeedMoreUpdates();
}
@@ -1025,15 +1023,12 @@ void LayerTreeHost::PaintLayerContents(
LayerIteratorType::Begin(&render_surface_layer_list);
it != end;
++it) {
- bool prevent_occlusion = it.target_render_surface_layer()->HasCopyRequest();
- occlusion_tracker.EnterLayer(it, prevent_occlusion);
+ occlusion_tracker.EnterLayer(it);
if (it.represents_target_render_surface()) {
PaintMasksForRenderSurface(
*it, queue, did_paint_content, need_more_updates);
- } else if (it.represents_itself()) {
- devtools_instrumentation::ScopedLayerTreeTask
- update_layer(devtools_instrumentation::kUpdateLayer, it->id(), id());
+ } else if (it.represents_itself() && it->DrawsContent()) {
DCHECK(!it->paint_properties().bounds.IsEmpty());
*did_paint_content |= it->Update(queue, &occlusion_tracker);
*need_more_updates |= it->NeedMoreUpdates();
@@ -1085,28 +1080,20 @@ void LayerTreeHost::ApplyScrollAndScale(const ScrollAndScaleSet& info) {
}
}
-void LayerTreeHost::StartRateLimiter(WebKit::WebGraphicsContext3D* context3d) {
+void LayerTreeHost::StartRateLimiter() {
if (animating_)
return;
- DCHECK(context3d);
- RateLimiterMap::iterator it = rate_limiters_.find(context3d);
- if (it != rate_limiters_.end()) {
- it->second->Start();
- } else {
- scoped_refptr<RateLimiter> rate_limiter =
- RateLimiter::Create(context3d, this, proxy_->MainThreadTaskRunner());
- rate_limiters_[context3d] = rate_limiter;
- rate_limiter->Start();
+ if (!rate_limit_timer_.IsRunning()) {
+ rate_limit_timer_.Start(FROM_HERE,
+ base::TimeDelta(),
+ this,
+ &LayerTreeHost::RateLimit);
}
}
-void LayerTreeHost::StopRateLimiter(WebKit::WebGraphicsContext3D* context3d) {
- RateLimiterMap::iterator it = rate_limiters_.find(context3d);
- if (it != rate_limiters_.end()) {
- it->second->Stop();
- rate_limiters_.erase(it);
- }
+void LayerTreeHost::StopRateLimiter() {
+ rate_limit_timer_.Stop();
}
void LayerTreeHost::RateLimit() {
@@ -1114,10 +1101,28 @@ void LayerTreeHost::RateLimit() {
// commands will wait for the compositing context, and therefore for the
// SwapBuffers.
proxy_->ForceSerializeOnSwapBuffers();
+ client_->RateLimitSharedMainThreadContext();
+}
+
+bool LayerTreeHost::AlwaysUsePartialTextureUpdates() {
+ if (!proxy_->GetRendererCapabilities().allow_partial_texture_updates)
+ return false;
+ return !proxy_->HasImplThread();
+}
+
+size_t LayerTreeHost::MaxPartialTextureUpdates() const {
+ size_t max_partial_texture_updates = 0;
+ if (proxy_->GetRendererCapabilities().allow_partial_texture_updates &&
+ !settings_.impl_side_painting) {
+ max_partial_texture_updates =
+ std::min(settings_.max_partial_texture_updates,
+ proxy_->MaxPartialTextureUpdates());
+ }
+ return max_partial_texture_updates;
}
bool LayerTreeHost::RequestPartialTextureUpdate() {
- if (partial_texture_update_requests_ >= settings_.max_partial_texture_updates)
+ if (partial_texture_update_requests_ >= MaxPartialTextureUpdates())
return false;
partial_texture_update_requests_++;
@@ -1155,7 +1160,6 @@ scoped_ptr<base::Value> LayerTreeHost::AsValue() const {
}
void LayerTreeHost::AnimateLayers(base::TimeTicks time) {
- rendering_stats_instrumentation_->IncrementAnimationFrameCount();
if (!settings_.accelerated_animation_enabled ||
animation_registrar_->active_animation_controllers().empty())
return;
@@ -1240,4 +1244,39 @@ void LayerTreeHost::RegisterViewportLayers(
outer_viewport_scroll_layer_ = outer_viewport_scroll_layer;
}
+bool LayerTreeHost::ScheduleMicroBenchmark(
+ const std::string& benchmark_name,
+ scoped_ptr<base::Value> value,
+ const MicroBenchmark::DoneCallback& callback) {
+ return micro_benchmark_controller_.ScheduleRun(
+ benchmark_name, value.Pass(), callback);
+}
+
+void LayerTreeHost::InsertSwapPromiseMonitor(SwapPromiseMonitor* monitor) {
+ swap_promise_monitor_.insert(monitor);
+}
+
+void LayerTreeHost::RemoveSwapPromiseMonitor(SwapPromiseMonitor* monitor) {
+ swap_promise_monitor_.erase(monitor);
+}
+
+void LayerTreeHost::NotifySwapPromiseMonitorsOfSetNeedsCommit() {
+ std::set<SwapPromiseMonitor*>::iterator it = swap_promise_monitor_.begin();
+ for (; it != swap_promise_monitor_.end(); it++)
+ (*it)->OnSetNeedsCommitOnMain();
+}
+
+void LayerTreeHost::QueueSwapPromise(scoped_ptr<SwapPromise> swap_promise) {
+ DCHECK(swap_promise);
+ if (swap_promise_list_.size() > kMaxQueuedSwapPromiseNumber)
+ BreakSwapPromises(SwapPromise::SWAP_PROMISE_LIST_OVERFLOW);
+ swap_promise_list_.push_back(swap_promise.Pass());
+}
+
+void LayerTreeHost::BreakSwapPromises(SwapPromise::DidNotSwapReason reason) {
+ for (size_t i = 0; i < swap_promise_list_.size(); i++)
+ swap_promise_list_[i]->DidNotSwap(reason);
+ swap_promise_list_.clear();
+}
+
} // namespace cc
diff --git a/chromium/cc/trees/layer_tree_host.h b/chromium/cc/trees/layer_tree_host.h
index 72a5628a9ad..8b9c1cf3226 100644
--- a/chromium/cc/trees/layer_tree_host.h
+++ b/chromium/cc/trees/layer_tree_host.h
@@ -7,6 +7,8 @@
#include <limits>
#include <list>
+#include <set>
+#include <string>
#include <vector>
#include "base/basictypes.h"
@@ -16,9 +18,14 @@
#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"
+#include "cc/base/swap_promise.h"
+#include "cc/base/swap_promise_monitor.h"
+#include "cc/debug/micro_benchmark.h"
+#include "cc/debug/micro_benchmark_controller.h"
#include "cc/input/input_handler.h"
#include "cc/input/scrollbar.h"
#include "cc/input/top_controls_state.h"
@@ -26,31 +33,14 @@
#include "cc/output/output_surface.h"
#include "cc/resources/resource_format.h"
#include "cc/resources/scoped_ui_resource.h"
-#include "cc/resources/ui_resource_bitmap.h"
-#include "cc/resources/ui_resource_client.h"
-#include "cc/scheduler/rate_limiter.h"
#include "cc/trees/layer_tree_host_client.h"
#include "cc/trees/layer_tree_host_common.h"
#include "cc/trees/layer_tree_settings.h"
#include "cc/trees/occlusion_tracker.h"
#include "cc/trees/proxy.h"
#include "third_party/skia/include/core/SkColor.h"
-#include "ui/events/latency_info.h"
#include "ui/gfx/rect.h"
-namespace WebKit { class WebGraphicsContext3D; }
-
-#if defined(COMPILER_GCC)
-namespace BASE_HASH_NAMESPACE {
-template <>
-struct hash<WebKit::WebGraphicsContext3D*> {
- size_t operator()(WebKit::WebGraphicsContext3D* ptr) const {
- return hash<size_t>()(reinterpret_cast<size_t>(ptr));
- }
-};
-} // namespace BASE_HASH_NAMESPACE
-#endif // COMPILER
-
namespace cc {
class AnimationRegistrar;
@@ -58,13 +48,16 @@ class HeadsUpDisplayLayer;
class Layer;
class LayerTreeHostImpl;
class LayerTreeHostImplClient;
-class PrioritizedResourceManager;
+class LayerTreeHostSingleThreadClient;
class PrioritizedResource;
+class PrioritizedResourceManager;
class Region;
class RenderingStatsInstrumentation;
class ResourceProvider;
class ResourceUpdateQueue;
+class SharedBitmapManager;
class TopControlsManager;
+class UIResourceRequest;
struct RenderingStats;
struct ScrollAndScaleSet;
@@ -76,7 +69,6 @@ struct CC_EXPORT RendererCapabilities {
ResourceFormat best_texture_format;
bool using_partial_swap;
- bool using_set_visibility;
bool using_egl_image;
bool allow_partial_texture_updates;
bool using_offscreen_context3d;
@@ -87,58 +79,34 @@ struct CC_EXPORT RendererCapabilities {
bool using_discard_framebuffer;
};
-class CC_EXPORT UIResourceRequest {
- public:
- enum UIResourceRequestType {
- UIResourceCreate,
- UIResourceDelete,
- UIResourceInvalidRequest
- };
-
- UIResourceRequest(UIResourceRequestType type, UIResourceId id);
- UIResourceRequest(UIResourceRequestType type,
- UIResourceId id,
- const UIResourceBitmap& bitmap);
- UIResourceRequest(const UIResourceRequest& request);
-
- ~UIResourceRequest();
-
- UIResourceRequestType GetType() const { return type_; }
- UIResourceId GetId() const { return id_; }
- UIResourceBitmap GetBitmap() const {
- DCHECK(bitmap_);
- return *bitmap_.get();
- }
-
- UIResourceRequest& operator=(const UIResourceRequest& request);
-
- private:
- UIResourceRequestType type_;
- UIResourceId id_;
- scoped_ptr<UIResourceBitmap> bitmap_;
-};
-
-class CC_EXPORT LayerTreeHost : NON_EXPORTED_BASE(public RateLimiterClient) {
+class CC_EXPORT LayerTreeHost {
public:
- static scoped_ptr<LayerTreeHost> Create(
+ // The SharedBitmapManager will be used on the compositor thread.
+ static scoped_ptr<LayerTreeHost> CreateThreaded(
LayerTreeHostClient* client,
+ SharedBitmapManager* manager,
const LayerTreeSettings& settings,
scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner);
+
+ static scoped_ptr<LayerTreeHost> CreateSingleThreaded(
+ LayerTreeHostClient* client,
+ LayerTreeHostSingleThreadClient* single_thread_client,
+ SharedBitmapManager* manager,
+ const LayerTreeSettings& settings);
virtual ~LayerTreeHost();
void SetLayerTreeHostClientReady();
- // Returns true if any LayerTreeHost is alive.
- static bool AnyLayerTreeHostInstanceExists();
-
void set_needs_filter_context() { needs_filter_context_ = true; }
bool needs_offscreen_context() const {
return needs_filter_context_;
}
// LayerTreeHost interface to Proxy.
- void WillBeginFrame() { client_->WillBeginFrame(); }
- void DidBeginFrame();
+ void WillBeginMainFrame() {
+ client_->WillBeginMainFrame(source_frame_number_);
+ }
+ void DidBeginMainFrame();
void UpdateClientAnimations(base::TimeTicks monotonic_frame_begin_time);
void AnimateLayers(base::TimeTicks monotonic_frame_begin_time);
void DidStopFlinging();
@@ -175,9 +143,6 @@ class CC_EXPORT LayerTreeHost : NON_EXPORTED_BASE(public RateLimiterClient) {
void Composite(base::TimeTicks frame_begin_time);
- // Only used when compositing on the main thread.
- void ScheduleComposite();
-
// Composites and attempts to read back the result into the provided
// buffer. If it wasn't possible, e.g. due to context lost, will return
// false.
@@ -209,15 +174,19 @@ class CC_EXPORT LayerTreeHost : NON_EXPORTED_BASE(public RateLimiterClient) {
void SetNeedsRedraw();
void SetNeedsRedrawRect(gfx::Rect damage_rect);
bool CommitRequested() const;
+ bool BeginMainFrameRequested() const;
void SetNextCommitWaitsForActivation();
+ void SetNextCommitForcesRedraw();
+
void SetAnimationEvents(scoped_ptr<AnimationEventsVector> events,
base::Time wall_clock_time);
void SetRootLayer(scoped_refptr<Layer> root_layer);
Layer* root_layer() { return root_layer_.get(); }
const Layer* root_layer() const { return root_layer_.get(); }
+ const Layer* page_scale_layer() const { return page_scale_layer_.get(); }
void RegisterViewportLayers(
scoped_refptr<Layer> page_scale_layer,
scoped_refptr<Layer> inner_viewport_scroll_layer,
@@ -264,18 +233,15 @@ class CC_EXPORT LayerTreeHost : NON_EXPORTED_BASE(public RateLimiterClient) {
void ApplyScrollAndScale(const ScrollAndScaleSet& info);
void SetImplTransform(const gfx::Transform& transform);
- void SetLatencyInfo(const ui::LatencyInfo& latency_info);
- virtual void StartRateLimiter(WebKit::WebGraphicsContext3D* context3d);
- virtual void StopRateLimiter(WebKit::WebGraphicsContext3D* context3d);
+ // Virtual for tests.
+ virtual void StartRateLimiter();
+ virtual void StopRateLimiter();
- // RateLimiterClient implementation.
- virtual void RateLimit() OVERRIDE;
+ void RateLimit();
- bool buffered_updates() const {
- return settings_.max_partial_texture_updates !=
- std::numeric_limits<size_t>::max();
- }
+ bool AlwaysUsePartialTextureUpdates();
+ size_t MaxPartialTextureUpdates() const;
bool RequestPartialTextureUpdate();
void SetDeviceScaleFactor(float device_scale_factor);
@@ -314,12 +280,39 @@ class CC_EXPORT LayerTreeHost : NON_EXPORTED_BASE(public RateLimiterClient) {
virtual gfx::Size GetUIResourceSize(UIResourceId id) const;
bool UsingSharedMemoryResources();
- int id() const { return tree_id_; }
+ int id() const { return id_; }
+
+ bool ScheduleMicroBenchmark(const std::string& benchmark_name,
+ scoped_ptr<base::Value> value,
+ const MicroBenchmark::DoneCallback& callback);
+
+ // When a SwapPromiseMonitor is created on the main thread, it calls
+ // InsertSwapPromiseMonitor() to register itself with LayerTreeHost.
+ // When the monitor is destroyed, it calls RemoveSwapPromiseMonitor()
+ // to unregister itself.
+ void InsertSwapPromiseMonitor(SwapPromiseMonitor* monitor);
+ void RemoveSwapPromiseMonitor(SwapPromiseMonitor* monitor);
+
+ // Call this function when you expect there to be a swap buffer.
+ // See swap_promise.h for how to use SwapPromise.
+ void QueueSwapPromise(scoped_ptr<SwapPromise> swap_promise);
+
+ void BreakSwapPromises(SwapPromise::DidNotSwapReason reason);
protected:
- LayerTreeHost(LayerTreeHostClient* client, const LayerTreeSettings& settings);
- bool Initialize(scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner);
+ LayerTreeHost(LayerTreeHostClient* client,
+ SharedBitmapManager* manager,
+ const LayerTreeSettings& settings);
+ bool InitializeThreaded(
+ scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner);
+ bool InitializeSingleThreaded(
+ LayerTreeHostSingleThreadClient* single_thread_client);
bool InitializeForTesting(scoped_ptr<Proxy> proxy_for_testing);
+ void SetOutputSurfaceLostForTesting(bool is_lost) {
+ output_surface_lost_ = is_lost;
+ }
+
+ MicroBenchmarkController micro_benchmark_controller_;
private:
bool InitializeProxy(scoped_ptr<Proxy> proxy);
@@ -364,6 +357,8 @@ class CC_EXPORT LayerTreeHost : NON_EXPORTED_BASE(public RateLimiterClient) {
void CalculateLCDTextMetricsCallback(Layer* layer);
+ void NotifySwapPromiseMonitorsOfSetNeedsCommit();
+
bool animating_;
bool needs_full_tree_sync_;
bool needs_filter_context_;
@@ -389,7 +384,7 @@ class CC_EXPORT LayerTreeHost : NON_EXPORTED_BASE(public RateLimiterClient) {
base::WeakPtr<InputHandler> input_handler_weak_ptr_;
base::WeakPtr<TopControlsManager> top_controls_manager_weak_ptr_;
- LayerTreeSettings settings_;
+ const LayerTreeSettings settings_;
LayerTreeDebugState debug_state_;
gfx::Size device_viewport_size_;
@@ -398,9 +393,7 @@ class CC_EXPORT LayerTreeHost : NON_EXPORTED_BASE(public RateLimiterClient) {
bool visible_;
- typedef base::hash_map<WebKit::WebGraphicsContext3D*,
- scoped_refptr<RateLimiter> > RateLimiterMap;
- RateLimiterMap rate_limiters_;
+ base::OneShotTimer<LayerTreeHost> rate_limit_timer_;
float page_scale_factor_;
float min_page_scale_factor_;
@@ -430,8 +423,6 @@ class CC_EXPORT LayerTreeHost : NON_EXPORTED_BASE(public RateLimiterClient) {
bool in_paint_layer_contents_;
- ui::LatencyInfo latency_info_;
-
static const int kTotalFramesToUseForLCDTextMetrics = 50;
int total_frames_used_for_lcd_text_metrics_;
@@ -446,12 +437,18 @@ class CC_EXPORT LayerTreeHost : NON_EXPORTED_BASE(public RateLimiterClient) {
int64 total_num_cc_layers_will_use_lcd_text;
};
LCDTextMetrics lcd_text_metrics_;
- int tree_id_;
+ int id_;
+ bool next_commit_forces_redraw_;
scoped_refptr<Layer> page_scale_layer_;
scoped_refptr<Layer> inner_viewport_scroll_layer_;
scoped_refptr<Layer> outer_viewport_scroll_layer_;
+ SharedBitmapManager* shared_bitmap_manager_;
+
+ ScopedPtrVector<SwapPromise> swap_promise_list_;
+ std::set<SwapPromiseMonitor*> swap_promise_monitor_;
+
DISALLOW_COPY_AND_ASSIGN(LayerTreeHost);
};
diff --git a/chromium/cc/trees/layer_tree_host_client.h b/chromium/cc/trees/layer_tree_host_client.h
index 9e11f7cbd5d..2e3023a7f79 100644
--- a/chromium/cc/trees/layer_tree_host_client.h
+++ b/chromium/cc/trees/layer_tree_host_client.h
@@ -19,10 +19,10 @@ class OutputSurface;
class LayerTreeHostClient {
public:
- virtual void WillBeginFrame() = 0;
+ virtual void WillBeginMainFrame(int frame_id) = 0;
// Marks finishing compositing-related tasks on the main thread. In threaded
// mode, this corresponds to DidCommit().
- virtual void DidBeginFrame() = 0;
+ virtual void DidBeginMainFrame() = 0;
virtual void Animate(double frame_begin_time) = 0;
virtual void Layout() = 0;
virtual void ApplyScrollAndScale(gfx::Vector2d scroll_delta,
@@ -36,15 +36,16 @@ class LayerTreeHostClient {
virtual void DidCommitAndDrawFrame() = 0;
virtual void DidCompleteSwapBuffers() = 0;
- // Used only in the single-threaded path.
- virtual void ScheduleComposite() = 0;
+ // If the client provides an OutputSurface bound to a 3d context for direct
+ // rendering, this must return a provider that provides contexts usable from
+ // the same thread as the OutputSurface's context.
+ virtual scoped_refptr<ContextProvider> OffscreenContextProvider() = 0;
- // These must always return a valid ContextProvider. But the provider does not
- // need to be capable of creating contexts.
- virtual scoped_refptr<cc::ContextProvider>
- OffscreenContextProviderForMainThread() = 0;
- virtual scoped_refptr<cc::ContextProvider>
- OffscreenContextProviderForCompositorThread() = 0;
+ // 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() {}
// This hook is for testing.
virtual void DidFailToInitializeOutputSurface() {}
diff --git a/chromium/cc/trees/layer_tree_host_common.cc b/chromium/cc/trees/layer_tree_host_common.cc
index 8017fa9a933..33236cf52e4 100644
--- a/chromium/cc/trees/layer_tree_host_common.cc
+++ b/chromium/cc/trees/layer_tree_host_common.cc
@@ -123,7 +123,7 @@ 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, typename RenderSurfaceType>
+template <typename LayerType>
static gfx::Vector2dF ComputeChangeOfBasisTranslation(
const LayerType& ancestor_layer,
const LayerType& descendant_layer) {
@@ -151,14 +151,13 @@ enum TranslateRectDirection {
TranslateRectDirectionToDescendant
};
-template <typename LayerType, typename RenderSurfaceType>
+template <typename LayerType>
static gfx::Rect TranslateRectToTargetSpace(const LayerType& ancestor_layer,
const LayerType& descendant_layer,
gfx::Rect rect,
TranslateRectDirection direction) {
- gfx::Vector2dF translation =
- ComputeChangeOfBasisTranslation<LayerType, RenderSurfaceType>(
- ancestor_layer, descendant_layer);
+ gfx::Vector2dF translation = ComputeChangeOfBasisTranslation<LayerType>(
+ ancestor_layer, descendant_layer);
if (direction == TranslateRectDirectionToDescendant)
translation.Scale(-1.f);
return gfx::ToEnclosingRect(
@@ -167,7 +166,7 @@ static gfx::Rect TranslateRectToTargetSpace(const LayerType& ancestor_layer,
// 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, typename RenderSurfaceType>
+template <typename LayerType>
static void UpdateClipRectsForClipChild(
const LayerType* layer,
gfx::Rect* clip_rect_in_parent_target_space,
@@ -175,7 +174,11 @@ static void UpdateClipRectsForClipChild(
// 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->clip_parent();
+ const LayerType* clip_parent = layer->scroll_parent();
+
+ if (!clip_parent)
+ clip_parent = layer->clip_parent();
+
if (!clip_parent || clip_parent == layer->parent())
return;
@@ -192,12 +195,23 @@ static void UpdateClipRectsForClipChild(
// wanted to. But more importantly, this matches the expectations of
// CalculateDrawPropertiesInternal. If we, say, create a render surface, these
// clip rects will want to be in its target space, not ours.
- *clip_rect_in_parent_target_space =
- TranslateRectToTargetSpace<LayerType, RenderSurfaceType>(
- *clip_parent,
- *layer->parent(),
- *clip_rect_in_parent_target_space,
- TranslateRectDirectionToDescendant);
+ if (clip_parent == layer->clip_parent()) {
+ *clip_rect_in_parent_target_space = TranslateRectToTargetSpace<LayerType>(
+ *clip_parent,
+ *layer->parent(),
+ *clip_rect_in_parent_target_space,
+ TranslateRectDirectionToDescendant);
+ } else {
+ // If we're being clipped by our scroll parent, we must translate through
+ // 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>(*layer->parent(),
+ *clip_parent,
+ *clip_rect_in_parent_target_space,
+ TranslateRectDirectionToAncestor);
+ }
}
// We collect an accumulated drawable content rect per render surface.
@@ -223,7 +237,7 @@ struct AccumulatedSurfaceState {
LayerType* render_target;
};
-template <typename LayerType, typename RenderSurfaceType>
+template <typename LayerType>
void UpdateAccumulatedSurfaceState(
LayerType* layer,
gfx::Rect drawable_content_rect,
@@ -257,7 +271,7 @@ 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, RenderSurfaceType>(
+ clip_rect = TranslateRectToTargetSpace<LayerType>(
*layer->clip_parent(),
*layer,
clip_rect,
@@ -423,10 +437,10 @@ static bool LayerShouldBeSkipped(LayerType* layer,
bool layer_is_visible) {
// Layers can be skipped if any of these conditions are met.
// - is not visible due to it or one of its ancestors being hidden.
- // - does not draw content.
- // - is transparent
// - has empty bounds
// - the layer is not double-sided, but its back face is visible.
+ // - is transparent
+ // - does not draw content and does not participate in hit testing.
//
// Some additional conditions need to be computed at a later point after the
// recursion is finished.
@@ -440,7 +454,7 @@ static bool LayerShouldBeSkipped(LayerType* layer,
if (!layer_is_visible)
return true;
- if (!layer->DrawsContent() || layer->bounds().IsEmpty())
+ if (layer->bounds().IsEmpty())
return true;
LayerType* backface_test_layer = layer;
@@ -457,6 +471,13 @@ static bool LayerShouldBeSkipped(LayerType* layer,
IsLayerBackFaceVisible(backface_test_layer))
return true;
+ // The layer is visible to events. If it's subject to hit testing, then
+ // we can't skip it.
+ bool can_accept_input = !layer->touch_event_handler_region().IsEmpty() ||
+ layer->have_wheel_event_handlers();
+ if (!layer->DrawsContent() && !can_accept_input)
+ return true;
+
return false;
}
@@ -480,6 +501,7 @@ static inline bool SubtreeShouldBeSkipped(LayerImpl* layer,
// The opacity of a layer always applies to its children (either implicitly
// via a render surface or explicitly if the parent preserves 3D), so the
// entire subtree can be skipped if this layer is fully transparent.
+ // TODO(sad): Don't skip layers used for hit testing crbug.com/295295.
return !layer->opacity();
}
@@ -500,26 +522,11 @@ static inline bool SubtreeShouldBeSkipped(Layer* layer,
// 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.
+ // TODO(sad): Don't skip layers used for hit testing crbug.com/295295.
return !layer->opacity() && !layer->OpacityIsAnimating() &&
!layer->OpacityCanAnimateOnImplThread();
}
-// Called on each layer that could be drawn after all information from
-// CalcDrawProperties has been updated on that layer. May have some false
-// positives (e.g. layers get this called on them but don't actually get drawn).
-static inline void UpdateTilePrioritiesForLayer(LayerImpl* layer) {
- layer->UpdateTilePriorities();
-
- // Mask layers don't get this call, so explicitly update them so they can
- // kick off tile rasterization.
- if (layer->mask_layer())
- layer->mask_layer()->UpdateTilePriorities();
- if (layer->replica_layer() && layer->replica_layer()->mask_layer())
- layer->replica_layer()->mask_layer()->UpdateTilePriorities();
-}
-
-static inline void UpdateTilePrioritiesForLayer(Layer* layer) {}
-
static inline void SavePaintPropertiesLayer(LayerImpl* layer) {}
static inline void SavePaintPropertiesLayer(Layer* layer) {
@@ -560,8 +567,7 @@ static bool SubtreeShouldRenderToSeparateSurface(
}
// If the layer uses a CSS filter.
- if (!layer->filters().IsEmpty() || !layer->background_filters().IsEmpty() ||
- layer->filter()) {
+ if (!layer->filters().IsEmpty() || !layer->background_filters().IsEmpty()) {
DCHECK(!is_root);
return true;
}
@@ -581,12 +587,25 @@ static bool SubtreeShouldRenderToSeparateSurface(
return true;
}
+ // If the layer has blending.
+ // TODO(rosca): this is temporary, until blending is implemented for other
+ // types of quads than RenderPassDrawQuad. Layers having descendants that draw
+ // content will still create a separate rendering surface.
+ if (!layer->uses_default_blend_mode()) {
+ TRACE_EVENT_INSTANT0(
+ "cc",
+ "LayerTreeHostCommon::SubtreeShouldRenderToSeparateSurface blending",
+ TRACE_EVENT_SCOPE_THREAD);
+ DCHECK(!is_root);
+ return true;
+ }
+
// If the layer clips its descendants but it is not axis-aligned with respect
// to its parent.
bool layer_clips_external_content =
LayerClipsSubtree(layer) || layer->HasDelegatedContent();
if (layer_clips_external_content && !axis_aligned_with_respect_to_parent &&
- !layer->draw_properties().descendants_can_clip_selves) {
+ num_descendants_that_draw_content > 0) {
TRACE_EVENT_INSTANT0(
"cc",
"LayerTreeHostCommon::SubtreeShouldRenderToSeparateSurface clipping",
@@ -623,6 +642,19 @@ static bool SubtreeShouldRenderToSeparateSurface(
// be used as a contributing surface in order to apply correctly.
//
+ // If the layer has isolation.
+ // TODO(rosca): to be optimized - create separate rendering surface only when
+ // the blending descendants might have access to the content behind this layer
+ // (layer has transparent background or descendants overflow).
+ // https://code.google.com/p/chromium/issues/detail?id=301738
+ if (layer->is_root_for_isolated_group()) {
+ TRACE_EVENT_INSTANT0(
+ "cc",
+ "LayerTreeHostCommon::SubtreeShouldRenderToSeparateSurface isolation",
+ TRACE_EVENT_SCOPE_THREAD);
+ return true;
+ }
+
// If we force it.
if (layer->force_render_surface())
return true;
@@ -815,19 +847,29 @@ gfx::Transform ComputeScrollCompensationMatrixForChildren(
// render_surfaces.
//
+ // Scroll compensation restarts from identity under two possible conditions:
+ // - the current layer is a container for fixed-position descendants
+ // - the current layer is fixed-position itself, so any fixed-position
+ // descendants are positioned with respect to this layer. Thus, any
+ // fixed position descendants only need to compensate for scrollDeltas
+ // that occur below this layer.
+ bool current_layer_resets_scroll_compensation_for_descendants =
+ layer->IsContainerForFixedPositionLayers() ||
+ layer->position_constraint().is_fixed_position();
+
// Avoid the overheads (including stack allocation and matrix
// initialization/copy) if we know that the scroll compensation doesn't need
// to be reset or adjusted.
- if (!layer->IsContainerForFixedPositionLayers() &&
+ if (!current_layer_resets_scroll_compensation_for_descendants &&
scroll_delta.IsZero() && !layer->render_surface())
return current_scroll_compensation_matrix;
// Start as identity matrix.
gfx::Transform next_scroll_compensation_matrix;
- // If this layer is not a container, then it inherits the existing scroll
- // compensations.
- if (!layer->IsContainerForFixedPositionLayers())
+ // If this layer does not reset scroll compensation, then it inherits the
+ // existing scroll compensations.
+ if (!current_layer_resets_scroll_compensation_for_descendants)
next_scroll_compensation_matrix = current_scroll_compensation_matrix;
// If the current layer has a non-zero scroll_delta, then we should compute
@@ -980,10 +1022,10 @@ static inline RenderSurfaceImpl* CreateOrReuseRenderSurface(LayerImpl* layer) {
return layer->render_surface();
}
-template <typename LayerType, typename LayerList>
+template <typename LayerType>
static inline void RemoveSurfaceForEarlyExit(
LayerType* layer_to_remove,
- LayerList* render_surface_layer_list) {
+ typename LayerType::RenderSurfaceListType* 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
@@ -1024,7 +1066,6 @@ static void PreCalculateMetaInformation(
PreCalculateMetaInformationRecursiveData* recursive_data) {
bool has_delegated_content = layer->HasDelegatedContent();
int num_descendants_that_draw_content = 0;
- bool descendants_can_clip_selves = true;
if (has_delegated_content) {
// Layers with delegated content need to be treated as if they have as
@@ -1032,9 +1073,11 @@ static void PreCalculateMetaInformation(
// Since we don't know this number right now, we choose one that acts like
// infinity for our purposes.
num_descendants_that_draw_content = 1000;
- descendants_can_clip_selves = false;
}
+ layer->draw_properties().sorted_for_recursion = false;
+ layer->draw_properties().has_child_with_a_scroll_parent = false;
+
if (layer->clip_parent())
recursive_data->num_unclipped_descendants++;
@@ -1045,21 +1088,12 @@ static void PreCalculateMetaInformation(
PreCalculateMetaInformationRecursiveData data_for_child;
PreCalculateMetaInformation(child_layer, &data_for_child);
- if (!has_delegated_content) {
- bool sublayer_transform_prevents_clip =
- !layer->sublayer_transform().IsPositiveScaleOrTranslation();
-
- num_descendants_that_draw_content += child_layer->DrawsContent() ? 1 : 0;
- num_descendants_that_draw_content +=
- child_layer->draw_properties().num_descendants_that_draw_content;
-
- if ((child_layer->DrawsContent() && !child_layer->CanClipSelf()) ||
- !child_layer->draw_properties().descendants_can_clip_selves ||
- sublayer_transform_prevents_clip ||
- !child_layer->transform().IsPositiveScaleOrTranslation())
- descendants_can_clip_selves = false;
- }
+ num_descendants_that_draw_content += child_layer->DrawsContent() ? 1 : 0;
+ num_descendants_that_draw_content +=
+ child_layer->draw_properties().num_descendants_that_draw_content;
+ if (child_layer->scroll_parent())
+ layer->draw_properties().has_child_with_a_scroll_parent = true;
recursive_data->Merge(data_for_child);
}
@@ -1076,17 +1110,13 @@ static void PreCalculateMetaInformation(
num_descendants_that_draw_content;
layer->draw_properties().num_unclipped_descendants =
recursive_data->num_unclipped_descendants;
- layer->draw_properties().descendants_can_clip_selves =
- descendants_can_clip_selves;
layer->draw_properties().layer_or_descendant_has_copy_request =
recursive_data->layer_or_descendant_has_copy_request;
}
static void RoundTranslationComponents(gfx::Transform* transform) {
- transform->matrix().
- setDouble(0, 3, MathUtil::Round(transform->matrix().getDouble(0, 3)));
- transform->matrix().
- setDouble(1, 3, MathUtil::Round(transform->matrix().getDouble(1, 3)));
+ transform->matrix().set(0, 3, MathUtil::Round(transform->matrix().get(0, 3)));
+ transform->matrix().set(1, 3, MathUtil::Round(transform->matrix().get(1, 3)));
}
template <typename LayerType>
@@ -1095,11 +1125,12 @@ struct SubtreeGlobals {
int max_texture_size;
float device_scale_factor;
float page_scale_factor;
- LayerType* page_scale_application_layer;
+ const LayerType* page_scale_application_layer;
bool can_adjust_raster_scales;
+ bool can_render_to_separate_surface;
};
-template<typename LayerType, typename RenderSurfaceType>
+template<typename LayerType>
struct DataForRecursion {
// The accumulated sequence of transforms a layer will use to determine its
// own draw transform.
@@ -1132,23 +1163,140 @@ struct DataForRecursion {
gfx::Rect clip_rect_of_target_surface_in_target_space;
bool ancestor_clips_subtree;
- RenderSurfaceType* nearest_ancestor_surface_that_moves_pixels;
+ typename LayerType::RenderSurfaceType*
+ nearest_occlusion_immune_ancestor_surface;
bool in_subtree_of_page_scale_application_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()) {
+ if (ancestor->parent() == &parent)
+ return ancestor;
+ }
+ NOTREACHED();
+ return 0;
+}
+
+template <typename LayerType>
+static void AddScrollParentChain(std::vector<LayerType*>* out,
+ const LayerType& parent,
+ LayerType* 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
+ // an ordering of parent's children that ensures that scroll parents are
+ // visited before their descendants.
+ // Take for example this layer tree:
+ //
+ // + stacking_context
+ // + scroll_child (1)
+ // + scroll_parent_graphics_layer (*)
+ // | + scroll_parent_scrolling_layer
+ // | + scroll_parent_scrolling_content_layer (2)
+ // + scroll_grandparent_graphics_layer (**)
+ // + scroll_grandparent_scrolling_layer
+ // + scroll_grandparent_scrolling_content_layer (3)
+ //
+ // The scroll child is (1), its scroll parent is (2) and its scroll
+ // grandparent is (3). Note, this doesn't mean that (2)'s scroll parent is
+ // (3), it means that (*)'s scroll parent is (3). We don't want our list to
+ // look like [ (3), (2), (1) ], even though that does have the ancestor chain
+ // in the right order. Instead, we want [ (**), (*), (1) ]. That is, only want
+ // (1)'s siblings in the list, but we want them to appear in such an order
+ // that the scroll ancestors get visited in the correct order.
+ //
+ // 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);
+ if (child->draw_properties().sorted_for_recursion)
+ return;
+
+ if (LayerType* scroll_parent = child->scroll_parent())
+ AddScrollParentChain(out, parent, scroll_parent);
+
+ out->push_back(child);
+ child->draw_properties().sorted_for_recursion = true;
+}
+
+template <typename LayerType>
+static bool SortChildrenForRecursion(std::vector<LayerType*>* out,
+ const LayerType& parent) {
+ out->reserve(parent.children().size());
+ bool order_changed = false;
+ for (size_t i = 0; i < parent.children().size(); ++i) {
+ LayerType* current =
+ LayerTreeHostCommon::get_child_as_raw_ptr(parent.children(), i);
+
+ if (current->draw_properties().sorted_for_recursion) {
+ order_changed = true;
+ continue;
+ }
+
+ AddScrollParentChain(out, parent, current);
+ }
+
+ DCHECK_EQ(parent.children().size(), out->size());
+ 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;
+}
+
+template <typename LayerType,
+ typename GetIndexAndCountType>
+static void SortLayerListContributions(
+ const LayerType& parent,
+ typename LayerType::RenderSurfaceListType* 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_child_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,
- typename LayerListType,
- typename RenderSurfaceType>
+template <typename LayerType>
static void CalculateDrawPropertiesInternal(
LayerType* layer,
const SubtreeGlobals<LayerType>& globals,
- const DataForRecursion<LayerType, RenderSurfaceType>& data_from_ancestor,
- LayerListType* render_surface_layer_list,
- LayerListType* layer_list,
+ const DataForRecursion<LayerType>& data_from_ancestor,
+ typename LayerType::RenderSurfaceListType* render_surface_layer_list,
+ typename LayerType::RenderSurfaceListType* layer_list,
std::vector<AccumulatedSurfaceState<LayerType> >*
accumulated_surface_state) {
// This function computes the new matrix transformations recursively for this
@@ -1278,9 +1426,10 @@ static void CalculateDrawPropertiesInternal(
DCHECK(globals.page_scale_application_layer ||
(globals.page_scale_factor == 1.f));
- DataForRecursion<LayerType, RenderSurfaceType> data_for_children;
- RenderSurfaceType* nearest_ancestor_surface_that_moves_pixels =
- data_from_ancestor.nearest_ancestor_surface_that_moves_pixels;
+ DataForRecursion<LayerType> data_for_children;
+ typename LayerType::RenderSurfaceType*
+ nearest_occlusion_immune_ancestor_surface =
+ data_from_ancestor.nearest_occlusion_immune_ancestor_surface;
data_for_children.in_subtree_of_page_scale_application_layer =
data_from_ancestor.in_subtree_of_page_scale_application_layer;
data_for_children.subtree_can_use_lcd_text =
@@ -1313,15 +1462,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, RenderSurfaceType>(
+ UpdateClipRectsForClipChild<LayerType>(
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, RenderSurfaceType>& layer_draw_properties =
- layer->draw_properties();
+ DrawProperties<LayerType>& layer_draw_properties = layer->draw_properties();
gfx::Rect clip_rect_in_target_space;
bool layer_or_ancestor_clips_descendants = false;
@@ -1464,8 +1612,14 @@ static void CalculateDrawPropertiesInternal(
? combined_transform_scales
: gfx::Vector2dF(layer_scale_factors, layer_scale_factors);
- if (SubtreeShouldRenderToSeparateSurface(
- layer, combined_transform.Preserves2dAxisAlignment())) {
+ bool render_to_separate_surface;
+ if (globals.can_render_to_separate_surface) {
+ render_to_separate_surface = SubtreeShouldRenderToSeparateSurface(
+ layer, combined_transform.Preserves2dAxisAlignment());
+ } else {
+ render_to_separate_surface = IsRootLayer(layer);
+ }
+ if (render_to_separate_surface) {
// Check back-face visibility before continuing with this surface and its
// subtree
if (!layer->double_sided() && TransformToParentIsKnown(layer) &&
@@ -1474,7 +1628,8 @@ static void CalculateDrawPropertiesInternal(
return;
}
- RenderSurfaceType* render_surface = CreateOrReuseRenderSurface(layer);
+ typename LayerType::RenderSurfaceType* render_surface =
+ CreateOrReuseRenderSurface(layer);
if (IsRootLayer(layer)) {
// The root layer's render surface size is predetermined and so the root
@@ -1543,7 +1698,7 @@ static void CalculateDrawPropertiesInternal(
render_surface->draw_transform());
if (layer->mask_layer()) {
- DrawProperties<LayerType, RenderSurfaceType>& mask_layer_draw_properties =
+ DrawProperties<LayerType>& mask_layer_draw_properties =
layer->mask_layer()->draw_properties();
mask_layer_draw_properties.render_target = layer;
mask_layer_draw_properties.visible_content_rect =
@@ -1551,21 +1706,28 @@ static void CalculateDrawPropertiesInternal(
}
if (layer->replica_layer() && layer->replica_layer()->mask_layer()) {
- DrawProperties<LayerType, RenderSurfaceType>&
- replica_mask_draw_properties =
+ DrawProperties<LayerType>& replica_mask_draw_properties =
layer->replica_layer()->mask_layer()->draw_properties();
replica_mask_draw_properties.render_target = layer;
replica_mask_draw_properties.visible_content_rect =
gfx::Rect(layer->content_bounds());
}
+ // 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->filters().HasFilterThatMovesPixels() || layer->filter())
- nearest_ancestor_surface_that_moves_pixels = render_surface;
-
- render_surface->SetNearestAncestorThatMovesPixels(
- nearest_ancestor_surface_that_moves_pixels);
+ 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;
@@ -1663,21 +1825,6 @@ static void CalculateDrawPropertiesInternal(
layer_draw_properties.render_target = layer->parent()->render_target();
}
- // Mark whether a layer could be drawn directly to the back buffer, for
- // example when it could use LCD text even though it's in a non-contents
- // opaque layer. This means that it can't be drawn to an intermediate
- // render target and also that no blending is applied to the layer as a whole
- // (meaning that its contents don't have to be pre-composited into a bitmap or
- // a render target).
- //
- // Ignoring animations is an optimization,
- // as it means that we're going to need some retained resources for this
- // layer in the near future even if its opacity is 1 now.
- layer_draw_properties.can_draw_directly_to_backbuffer =
- IsRootLayer(layer_draw_properties.render_target) &&
- layer->draw_properties().opacity == 1.f &&
- !animating_opacity_to_screen;
-
if (adjust_text_aa)
layer_draw_properties.can_use_lcd_text = layer_can_use_lcd_text;
@@ -1710,7 +1857,7 @@ static void CalculateDrawPropertiesInternal(
layer_draw_properties.clip_rect = rect_in_target_space;
}
- LayerListType& descendants =
+ typename LayerType::RenderSurfaceListType& descendants =
(layer->render_surface() ? layer->render_surface()->layer_list()
: *layer_list);
@@ -1721,6 +1868,12 @@ static void CalculateDrawPropertiesInternal(
if (!LayerShouldBeSkipped(layer, layer_is_visible))
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.page_scale_application_layer) {
data_for_children.parent_matrix.Scale(
@@ -1760,29 +1913,64 @@ 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_ancestor_surface_that_moves_pixels =
- nearest_ancestor_surface_that_moves_pixels;
+ data_for_children.nearest_occlusion_immune_ancestor_surface =
+ nearest_occlusion_immune_ancestor_surface;
data_for_children.subtree_is_visible_from_ancestor = layer_is_visible;
}
+ std::vector<LayerType*> sorted_children;
+ bool child_order_changed = false;
+ if (layer_draw_properties.has_child_with_a_scroll_parent)
+ child_order_changed = 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 =
- LayerTreeHostCommon::get_child_as_raw_ptr(layer->children(), i);
- gfx::Rect drawable_content_rect_of_child_subtree;
- gfx::Transform identity_matrix;
- CalculateDrawPropertiesInternal<LayerType,
- LayerListType,
- RenderSurfaceType>(
- child,
- globals,
- data_for_children,
- render_surface_layer_list,
- &descendants,
- accumulated_surface_state);
+ layer_draw_properties.has_child_with_a_scroll_parent
+ ? sorted_children[i]
+ : LayerTreeHostCommon::get_child_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);
if (child->render_surface() &&
!child->render_surface()->content_rect().IsEmpty()) {
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;
+ }
+
+ // Add the unsorted layer list contributions, if necessary.
+ if (child_order_changed) {
+ SortLayerListContributions(
+ *layer,
+ 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
@@ -1800,19 +1988,16 @@ static void CalculateDrawPropertiesInternal(
return;
}
- if (layer->DrawsContent()) {
- gfx::Rect local_drawable_content_rect = rect_in_target_space;
- if (layer_or_ancestor_clips_descendants)
- local_drawable_content_rect.Intersect(clip_rect_in_target_space);
- local_drawable_content_rect_of_subtree.Union(local_drawable_content_rect);
- }
-
// Compute the layer's drawable content rect (the rect is in target surface
// space).
layer_draw_properties.drawable_content_rect = rect_in_target_space;
if (layer_or_ancestor_clips_descendants) {
- layer_draw_properties.drawable_content_rect.
- Intersect(clip_rect_in_target_space);
+ layer_draw_properties.drawable_content_rect.Intersect(
+ clip_rect_in_target_space);
+ }
+ if (layer->DrawsContent()) {
+ local_drawable_content_rect_of_subtree.Union(
+ layer_draw_properties.drawable_content_rect);
}
// Compute the layer's visible content rect (the rect is in content space).
@@ -1826,8 +2011,9 @@ static void CalculateDrawPropertiesInternal(
DCHECK(layer->render_surface());
layer->render_surface()->SetContentRect(
ancestor_clip_rect_in_target_space);
- } else if (layer->render_surface() && !IsRootLayer(layer)) {
- RenderSurfaceType* render_surface = layer->render_surface();
+ } else if (layer->render_surface()) {
+ typename LayerType::RenderSurfaceType* 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
@@ -1859,6 +2045,16 @@ static void CalculateDrawPropertiesInternal(
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.
+ // Otherwise, this layer will use an incomplete backdrop, limited to its
+ // render target and the blending result will be incorrect.
+ DCHECK(layer->uses_default_blend_mode() || IsRootLayer(layer) ||
+ !layer->parent()->render_target() ||
+ IsRootLayer(layer->parent()->render_target()) ||
+ layer->parent()->render_target()->is_root_for_isolated_group());
+
render_surface->SetContentRect(clipped_content_rect);
// The owning layer's screen_space_transform has a scale from content to
@@ -1905,7 +2101,6 @@ static void CalculateDrawPropertiesInternal(
}
}
- UpdateTilePrioritiesForLayer(layer);
SavePaintPropertiesLayer(layer);
// If neither this layer nor any of its children were added, early out.
@@ -1925,7 +2120,7 @@ static void CalculateDrawPropertiesInternal(
globals.layer_sorter);
}
- UpdateAccumulatedSurfaceState<LayerType, RenderSurfaceType>(
+ UpdateAccumulatedSurfaceState<LayerType>(
layer, local_drawable_content_rect_of_subtree, accumulated_surface_state);
if (layer->HasContributingDelegatedRenderPasses()) {
@@ -1955,9 +2150,11 @@ void LayerTreeHostCommon::CalculateDrawProperties(
globals.device_scale_factor = inputs->device_scale_factor;
globals.page_scale_factor = inputs->page_scale_factor;
globals.page_scale_application_layer = inputs->page_scale_application_layer;
+ globals.can_render_to_separate_surface =
+ inputs->can_render_to_separate_surface;
globals.can_adjust_raster_scales = inputs->can_adjust_raster_scales;
- DataForRecursion<Layer, RenderSurface> data_for_recursion;
+ DataForRecursion<Layer> data_for_recursion;
data_for_recursion.parent_matrix = scaled_device_transform;
data_for_recursion.full_hierarchy_matrix = identity_matrix;
data_for_recursion.scroll_compensation_matrix = identity_matrix;
@@ -1966,7 +2163,7 @@ void LayerTreeHostCommon::CalculateDrawProperties(
data_for_recursion.clip_rect_of_target_surface_in_target_space =
device_viewport_rect;
data_for_recursion.ancestor_clips_subtree = true;
- data_for_recursion.nearest_ancestor_surface_that_moves_pixels = NULL;
+ data_for_recursion.nearest_occlusion_immune_ancestor_surface = NULL;
data_for_recursion.in_subtree_of_page_scale_application_layer = false;
data_for_recursion.subtree_can_use_lcd_text = inputs->can_use_lcd_text;
data_for_recursion.subtree_is_visible_from_ancestor = true;
@@ -1974,13 +2171,12 @@ void LayerTreeHostCommon::CalculateDrawProperties(
PreCalculateMetaInformationRecursiveData recursive_data;
PreCalculateMetaInformation(inputs->root_layer, &recursive_data);
std::vector<AccumulatedSurfaceState<Layer> > accumulated_surface_state;
- CalculateDrawPropertiesInternal<Layer, RenderSurfaceLayerList, RenderSurface>(
- inputs->root_layer,
- globals,
- data_for_recursion,
- inputs->render_surface_layer_list,
- &dummy_layer_list,
- &accumulated_surface_state);
+ CalculateDrawPropertiesInternal<Layer>(inputs->root_layer,
+ globals,
+ data_for_recursion,
+ inputs->render_surface_layer_list,
+ &dummy_layer_list,
+ &accumulated_surface_state);
// The dummy layer list should not have been used.
DCHECK_EQ(0u, dummy_layer_list.size());
@@ -2012,9 +2208,11 @@ void LayerTreeHostCommon::CalculateDrawProperties(
globals.device_scale_factor = inputs->device_scale_factor;
globals.page_scale_factor = inputs->page_scale_factor;
globals.page_scale_application_layer = inputs->page_scale_application_layer;
+ globals.can_render_to_separate_surface =
+ inputs->can_render_to_separate_surface;
globals.can_adjust_raster_scales = inputs->can_adjust_raster_scales;
- DataForRecursion<LayerImpl, RenderSurfaceImpl> data_for_recursion;
+ DataForRecursion<LayerImpl> data_for_recursion;
data_for_recursion.parent_matrix = scaled_device_transform;
data_for_recursion.full_hierarchy_matrix = identity_matrix;
data_for_recursion.scroll_compensation_matrix = identity_matrix;
@@ -2023,7 +2221,7 @@ void LayerTreeHostCommon::CalculateDrawProperties(
data_for_recursion.clip_rect_of_target_surface_in_target_space =
device_viewport_rect;
data_for_recursion.ancestor_clips_subtree = true;
- data_for_recursion.nearest_ancestor_surface_that_moves_pixels = NULL;
+ data_for_recursion.nearest_occlusion_immune_ancestor_surface = NULL;
data_for_recursion.in_subtree_of_page_scale_application_layer = false;
data_for_recursion.subtree_can_use_lcd_text = inputs->can_use_lcd_text;
data_for_recursion.subtree_is_visible_from_ancestor = true;
@@ -2032,13 +2230,12 @@ void LayerTreeHostCommon::CalculateDrawProperties(
PreCalculateMetaInformation(inputs->root_layer, &recursive_data);
std::vector<AccumulatedSurfaceState<LayerImpl> >
accumulated_surface_state;
- CalculateDrawPropertiesInternal<LayerImpl, LayerImplList, RenderSurfaceImpl>(
- inputs->root_layer,
- globals,
- data_for_recursion,
- inputs->render_surface_layer_list,
- &dummy_layer_list,
- &accumulated_surface_state);
+ CalculateDrawPropertiesInternal<LayerImpl>(inputs->root_layer,
+ globals,
+ data_for_recursion,
+ inputs->render_surface_layer_list,
+ &dummy_layer_list,
+ &accumulated_surface_state);
// The dummy layer list should not have been used.
DCHECK_EQ(0u, dummy_layer_list.size());
@@ -2186,34 +2383,21 @@ LayerImpl* LayerTreeHostCommon::FindLayerThatIsHitByPoint(
LayerImpl* LayerTreeHostCommon::FindLayerThatIsHitByPointInTouchHandlerRegion(
gfx::PointF screen_space_point,
const LayerImplList& render_surface_layer_list) {
- LayerImpl* found_layer = NULL;
-
- typedef LayerIterator<LayerImpl,
- LayerImplList,
- RenderSurfaceImpl,
- LayerIteratorActions::FrontToBack> LayerIteratorType;
- LayerIteratorType end = LayerIteratorType::End(&render_surface_layer_list);
-
- for (LayerIteratorType
- it = LayerIteratorType::Begin(&render_surface_layer_list);
- it != end;
- ++it) {
- // We don't want to consider render_surfaces for hit testing.
- if (!it.represents_itself())
- continue;
-
- LayerImpl* current_layer = (*it);
-
- if (!LayerHasTouchEventHandlersAt(screen_space_point, current_layer))
- continue;
-
- found_layer = current_layer;
- break;
+ // First find out which layer was hit from the saved list of visible layers
+ // in the most recent frame.
+ LayerImpl* layer_impl = LayerTreeHostCommon::FindLayerThatIsHitByPoint(
+ screen_space_point,
+ render_surface_layer_list);
+
+ // Walk up the hierarchy and look for a layer with a touch event handler
+ // region that the given point hits.
+ // This walk may not be necessary anymore: http://crbug.com/310817
+ for (; layer_impl; layer_impl = layer_impl->parent()) {
+ if (LayerTreeHostCommon::LayerHasTouchEventHandlersAt(screen_space_point,
+ layer_impl))
+ break;
}
-
- // This can potentially return NULL, which means the screen_space_point did
- // not successfully hit test any layers, not even the root layer.
- return found_layer;
+ return layer_impl;
}
bool LayerTreeHostCommon::LayerHasTouchEventHandlersAt(
diff --git a/chromium/cc/trees/layer_tree_host_common.h b/chromium/cc/trees/layer_tree_host_common.h
index 05affee8f31..727244864ee 100644
--- a/chromium/cc/trees/layer_tree_host_common.h
+++ b/chromium/cc/trees/layer_tree_host_common.h
@@ -36,9 +36,10 @@ class CC_EXPORT LayerTreeHostCommon {
const gfx::Transform& device_transform,
float device_scale_factor,
float page_scale_factor,
- LayerType* page_scale_application_layer,
+ const LayerType* page_scale_application_layer,
int max_texture_size,
bool can_use_lcd_text,
+ bool can_render_to_separate_surface,
bool can_adjust_raster_scales,
RenderSurfaceLayerListType* render_surface_layer_list)
: root_layer(root_layer),
@@ -49,6 +50,7 @@ class CC_EXPORT LayerTreeHostCommon {
page_scale_application_layer(page_scale_application_layer),
max_texture_size(max_texture_size),
can_use_lcd_text(can_use_lcd_text),
+ can_render_to_separate_surface(can_render_to_separate_surface),
can_adjust_raster_scales(can_adjust_raster_scales),
render_surface_layer_list(render_surface_layer_list) {}
@@ -57,9 +59,10 @@ class CC_EXPORT LayerTreeHostCommon {
const gfx::Transform& device_transform;
float device_scale_factor;
float page_scale_factor;
- LayerType* page_scale_application_layer;
+ const LayerType* page_scale_application_layer;
int max_texture_size;
bool can_use_lcd_text;
+ bool can_render_to_separate_surface;
bool can_adjust_raster_scales;
RenderSurfaceLayerListType* render_surface_layer_list;
};
@@ -220,6 +223,7 @@ LayerTreeHostCommon::CalcDrawPropsInputsForTesting<LayerType,
NULL,
std::numeric_limits<int>::max() / 2,
false,
+ true,
false,
render_surface_layer_list) {
DCHECK(root_layer);
@@ -242,6 +246,7 @@ LayerTreeHostCommon::CalcDrawPropsInputsForTesting<LayerType,
NULL,
std::numeric_limits<int>::max() / 2,
false,
+ true,
false,
render_surface_layer_list) {
DCHECK(root_layer);
diff --git a/chromium/cc/trees/layer_tree_host_common_perftest.cc b/chromium/cc/trees/layer_tree_host_common_perftest.cc
new file mode 100644
index 00000000000..7b63b2a0c51
--- /dev/null
+++ b/chromium/cc/trees/layer_tree_host_common_perftest.cc
@@ -0,0 +1,198 @@
+// 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/trees/layer_tree_host_common.h"
+
+#include <sstream>
+
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/path_service.h"
+#include "base/strings/string_piece.h"
+#include "base/threading/thread.h"
+#include "base/time/time.h"
+#include "cc/layers/layer.h"
+#include "cc/test/fake_content_layer_client.h"
+#include "cc/test/fake_layer_tree_host_client.h"
+#include "cc/test/lap_timer.h"
+#include "cc/test/layer_tree_json_parser.h"
+#include "cc/test/layer_tree_test.h"
+#include "cc/test/paths.h"
+#include "cc/trees/layer_tree_impl.h"
+#include "testing/perf/perf_test.h"
+
+namespace cc {
+namespace {
+
+static const int kTimeLimitMillis = 2000;
+static const int kWarmupRuns = 5;
+static const int kTimeCheckInterval = 10;
+
+class LayerTreeHostCommonPerfTest : public LayerTreeTest {
+ public:
+ LayerTreeHostCommonPerfTest()
+ : timer_(kWarmupRuns,
+ base::TimeDelta::FromMilliseconds(kTimeLimitMillis),
+ kTimeCheckInterval) {}
+
+ void ReadTestFile(const std::string& name) {
+ base::FilePath test_data_dir;
+ ASSERT_TRUE(PathService::Get(CCPaths::DIR_TEST_DATA, &test_data_dir));
+ base::FilePath json_file = test_data_dir.AppendASCII(name + ".json");
+ ASSERT_TRUE(base::ReadFileToString(json_file, &json_));
+ }
+
+ virtual void SetupTree() OVERRIDE {
+ gfx::Size viewport = gfx::Size(720, 1038);
+ layer_tree_host()->SetViewportSize(viewport);
+ scoped_refptr<Layer> root =
+ ParseTreeFromJson(json_, &content_layer_client_);
+ ASSERT_TRUE(root.get());
+ layer_tree_host()->SetRootLayer(root);
+ }
+
+ void SetTestName(const std::string& name) { test_name_ = name; }
+
+ virtual void AfterTest() OVERRIDE {
+ CHECK(!test_name_.empty()) << "Must SetTestName() before TearDown().";
+ perf_test::PrintResult("calc_draw_props_time",
+ "",
+ test_name_,
+ 1000 * timer_.MsPerLap(),
+ "us",
+ true);
+ }
+
+ protected:
+ FakeContentLayerClient content_layer_client_;
+ LapTimer timer_;
+ std::string test_name_;
+ std::string json_;
+};
+
+class CalcDrawPropsMainTest : public LayerTreeHostCommonPerfTest {
+ public:
+ void RunCalcDrawProps() {
+ RunTest(false, false, false);
+ }
+
+ virtual void BeginTest() OVERRIDE {
+ timer_.Reset();
+
+ do {
+ bool can_render_to_separate_surface = true;
+ int max_texture_size = 8096;
+ RenderSurfaceLayerList update_list;
+ LayerTreeHostCommon::CalcDrawPropsMainInputs inputs(
+ layer_tree_host()->root_layer(),
+ layer_tree_host()->device_viewport_size(),
+ gfx::Transform(),
+ layer_tree_host()->device_scale_factor(),
+ layer_tree_host()->page_scale_factor(),
+ layer_tree_host()->page_scale_layer(),
+ max_texture_size,
+ layer_tree_host()->settings().can_use_lcd_text,
+ can_render_to_separate_surface,
+ layer_tree_host()
+ ->settings()
+ .layer_transforms_should_scale_layer_contents,
+ &update_list);
+ LayerTreeHostCommon::CalculateDrawProperties(&inputs);
+
+ timer_.NextLap();
+ } while (!timer_.HasTimeLimitExpired());
+
+ EndTest();
+ }
+};
+
+class CalcDrawPropsImplTest : public LayerTreeHostCommonPerfTest {
+ public:
+ void RunCalcDrawProps() {
+ RunTestWithImplSidePainting();
+ }
+
+ virtual void BeginTest() OVERRIDE {
+ PostSetNeedsCommitToMainThread();
+ }
+
+ virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
+ timer_.Reset();
+ LayerTreeImpl* active_tree = host_impl->active_tree();
+
+ do {
+ bool can_render_to_separate_surface = true;
+ int max_texture_size = 8096;
+ LayerImplList update_list;
+ LayerTreeHostCommon::CalcDrawPropsImplInputs inputs(
+ active_tree->root_layer(),
+ active_tree->DrawViewportSize(),
+ host_impl->DrawTransform(),
+ active_tree->device_scale_factor(),
+ active_tree->total_page_scale_factor(),
+ active_tree->RootContainerLayer(),
+ max_texture_size,
+ host_impl->settings().can_use_lcd_text,
+ can_render_to_separate_surface,
+ host_impl->settings().layer_transforms_should_scale_layer_contents,
+ &update_list);
+ LayerTreeHostCommon::CalculateDrawProperties(&inputs);
+
+ timer_.NextLap();
+ } while (!timer_.HasTimeLimitExpired());
+
+ EndTest();
+ }
+};
+
+TEST_F(CalcDrawPropsMainTest, TenTen) {
+ SetTestName("10_10");
+ ReadTestFile("10_10_layer_tree");
+ RunCalcDrawProps();
+}
+
+TEST_F(CalcDrawPropsMainTest, HeavyPage) {
+ SetTestName("heavy_page");
+ ReadTestFile("heavy_layer_tree");
+ RunCalcDrawProps();
+}
+
+TEST_F(CalcDrawPropsMainTest, TouchRegionLight) {
+ SetTestName("touch_region_light");
+ ReadTestFile("touch_region_light");
+ RunCalcDrawProps();
+}
+
+TEST_F(CalcDrawPropsMainTest, TouchRegionHeavy) {
+ SetTestName("touch_region_heavy");
+ ReadTestFile("touch_region_heavy");
+ RunCalcDrawProps();
+}
+
+TEST_F(CalcDrawPropsImplTest, TenTen) {
+ SetTestName("10_10");
+ ReadTestFile("10_10_layer_tree");
+ RunCalcDrawProps();
+}
+
+TEST_F(CalcDrawPropsImplTest, HeavyPage) {
+ SetTestName("heavy_page");
+ ReadTestFile("heavy_layer_tree");
+ RunCalcDrawProps();
+}
+
+TEST_F(CalcDrawPropsImplTest, TouchRegionLight) {
+ SetTestName("touch_region_light");
+ ReadTestFile("touch_region_light");
+ RunCalcDrawProps();
+}
+
+TEST_F(CalcDrawPropsImplTest, TouchRegionHeavy) {
+ SetTestName("touch_region_heavy");
+ ReadTestFile("touch_region_heavy");
+ RunCalcDrawProps();
+}
+
+} // namespace
+} // namespace cc
diff --git a/chromium/cc/trees/layer_tree_host_common_unittest.cc b/chromium/cc/trees/layer_tree_host_common_unittest.cc
index a5546192365..58d82ceda4a 100644
--- a/chromium/cc/trees/layer_tree_host_common_unittest.cc
+++ b/chromium/cc/trees/layer_tree_host_common_unittest.cc
@@ -4,12 +4,15 @@
#include "cc/trees/layer_tree_host_common.h"
+#include <set>
+
#include "cc/animation/layer_animation_controller.h"
#include "cc/base/math_util.h"
#include "cc/layers/content_layer.h"
#include "cc/layers/content_layer_client.h"
#include "cc/layers/heads_up_display_layer_impl.h"
#include "cc/layers/layer.h"
+#include "cc/layers/layer_client.h"
#include "cc/layers/layer_impl.h"
#include "cc/layers/render_surface.h"
#include "cc/layers/render_surface_impl.h"
@@ -186,23 +189,8 @@ class LayerWithForcedDrawsContent : public Layer {
virtual ~LayerWithForcedDrawsContent() {}
};
-class LayerCanClipSelf : public Layer {
- public:
- LayerCanClipSelf() : Layer() {}
-
- virtual bool DrawsContent() const OVERRIDE;
- virtual bool CanClipSelf() const OVERRIDE;
-
- private:
- virtual ~LayerCanClipSelf() {}
-};
-
bool LayerWithForcedDrawsContent::DrawsContent() const { return true; }
-bool LayerCanClipSelf::DrawsContent() const { return true; }
-
-bool LayerCanClipSelf::CanClipSelf() const { return true; }
-
class MockContentLayerClient : public ContentLayerClient {
public:
MockContentLayerClient() {}
@@ -343,7 +331,7 @@ TEST_F(LayerTreeHostCommonTest, TransformsForSingleLayer) {
// Case 4: A change in actual position affects both the draw transform and
// screen space transform.
gfx::Transform position_transform;
- position_transform.Translate(0.0, 1.2);
+ position_transform.Translate(0.f, 1.2f);
SetLayerPropertiesForTesting(layer.get(),
identity_matrix,
identity_matrix,
@@ -551,7 +539,7 @@ TEST_F(LayerTreeHostCommonTest, TransformsForSimpleHierarchy) {
// Case 2: parent's position affects child and grand_child.
gfx::Transform parent_position_transform;
- parent_position_transform.Translate(0.0, 1.2);
+ parent_position_transform.Translate(0.f, 1.2f);
SetLayerPropertiesForTesting(parent.get(),
identity_matrix,
identity_matrix,
@@ -629,7 +617,7 @@ TEST_F(LayerTreeHostCommonTest, TransformsForSimpleHierarchy) {
// does not preserve3D. When it gives its hierarchy to the grand_child, it
// should be flattened to 2D.
gfx::Transform parent_sublayer_matrix;
- parent_sublayer_matrix.Scale3d(10.0, 10.0, 3.3);
+ parent_sublayer_matrix.Scale3d(10.f, 10.f, 3.3f);
// Sublayer matrix is applied to the anchor point of the parent layer.
parent_composite_transform =
parent_translation_to_anchor * parent_layer_transform *
@@ -730,11 +718,11 @@ TEST_F(LayerTreeHostCommonTest, TransformsForSingleRenderSurface) {
child->SetForceRenderSurface(true);
gfx::Transform parent_layer_transform;
- parent_layer_transform.Scale3d(1.0, 0.9, 1.0);
+ parent_layer_transform.Scale3d(1.f, 0.9f, 1.f);
gfx::Transform parent_translation_to_anchor;
parent_translation_to_anchor.Translate(25.0, 30.0);
gfx::Transform parent_sublayer_matrix;
- parent_sublayer_matrix.Scale3d(0.9, 1.0, 3.3);
+ parent_sublayer_matrix.Scale3d(0.9f, 1.f, 3.3f);
gfx::Transform parent_composite_transform =
parent_translation_to_anchor * parent_layer_transform *
@@ -850,147 +838,6 @@ TEST_F(LayerTreeHostCommonTest, SublayerTransformWithAnchorPoint) {
child->draw_transform());
}
-TEST_F(LayerTreeHostCommonTest, SeparateRenderTargetRequirementWithClipping) {
- scoped_refptr<Layer> root = Layer::Create();
- scoped_refptr<Layer> parent = Layer::Create();
- scoped_refptr<Layer> child = Layer::Create();
- scoped_refptr<Layer> grand_child = make_scoped_refptr(new LayerCanClipSelf());
- root->AddChild(parent);
- parent->AddChild(child);
- child->AddChild(grand_child);
- parent->SetMasksToBounds(true);
- child->SetMasksToBounds(true);
-
- scoped_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create();
- host->SetRootLayer(root);
-
- gfx::Transform identity_matrix;
- gfx::Transform parent_layer_transform;
- gfx::Transform parent_sublayer_matrix;
- gfx::Transform child_layer_matrix;
-
- // No render surface should exist yet.
- EXPECT_FALSE(root->render_surface());
- EXPECT_FALSE(parent->render_surface());
- EXPECT_FALSE(child->render_surface());
- EXPECT_FALSE(grand_child->render_surface());
-
- // One-time setup of root layer
- parent_layer_transform.Scale3d(1.0, 0.9, 1.0);
- parent_sublayer_matrix.Scale3d(0.9, 1.0, 3.3);
- child_layer_matrix.Rotate(20.0);
-
- SetLayerPropertiesForTesting(root.get(),
- identity_matrix,
- identity_matrix,
- gfx::PointF(),
- gfx::PointF(),
- gfx::Size(1, 2),
- false);
- SetLayerPropertiesForTesting(parent.get(),
- parent_layer_transform,
- parent_sublayer_matrix,
- gfx::PointF(0.25f, 0.25f),
- gfx::PointF(),
- gfx::Size(100, 120),
- false);
- SetLayerPropertiesForTesting(child.get(),
- child_layer_matrix,
- identity_matrix,
- gfx::PointF(),
- gfx::PointF(),
- gfx::Size(16, 18),
- false);
- SetLayerPropertiesForTesting(grand_child.get(),
- identity_matrix,
- identity_matrix,
- gfx::PointF(),
- gfx::PointF(),
- gfx::Size(8, 10),
- false);
-
- ExecuteCalculateDrawProperties(root.get());
-
- // Render surfaces should have been created according to clipping rules now
- // (grandchild can clip self).
- EXPECT_TRUE(root->render_surface());
- EXPECT_FALSE(parent->render_surface());
- EXPECT_FALSE(child->render_surface());
- EXPECT_FALSE(grand_child->render_surface());
-}
-
-TEST_F(LayerTreeHostCommonTest,
- SeparateRenderTargetRequirementWithoutClipping) {
- scoped_refptr<Layer> root = Layer::Create();
- scoped_refptr<Layer> parent = Layer::Create();
- scoped_refptr<Layer> child = Layer::Create();
- // This layer cannot clip itself, a feature we are testing here.
- scoped_refptr<Layer> grand_child =
- make_scoped_refptr(new LayerWithForcedDrawsContent());
- root->AddChild(parent);
- parent->AddChild(child);
- child->AddChild(grand_child);
- parent->SetMasksToBounds(true);
- child->SetMasksToBounds(true);
-
- scoped_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create();
- host->SetRootLayer(root);
-
- gfx::Transform identity_matrix;
- gfx::Transform parent_layer_transform;
- gfx::Transform parent_sublayer_matrix;
- gfx::Transform child_layer_matrix;
-
- // No render surface should exist yet.
- EXPECT_FALSE(root->render_surface());
- EXPECT_FALSE(parent->render_surface());
- EXPECT_FALSE(child->render_surface());
- EXPECT_FALSE(grand_child->render_surface());
-
- // One-time setup of root layer
- parent_layer_transform.Scale3d(1.0, 0.9, 1.0);
- parent_sublayer_matrix.Scale3d(0.9, 1.0, 3.3);
- child_layer_matrix.Rotate(20.0);
-
- SetLayerPropertiesForTesting(root.get(),
- identity_matrix,
- identity_matrix,
- gfx::PointF(),
- gfx::PointF(),
- gfx::Size(1, 2),
- false);
- SetLayerPropertiesForTesting(parent.get(),
- parent_layer_transform,
- parent_sublayer_matrix,
- gfx::PointF(0.25f, 0.25f),
- gfx::PointF(),
- gfx::Size(100, 120),
- false);
- SetLayerPropertiesForTesting(child.get(),
- child_layer_matrix,
- identity_matrix,
- gfx::PointF(),
- gfx::PointF(),
- gfx::Size(16, 18),
- false);
- SetLayerPropertiesForTesting(grand_child.get(),
- identity_matrix,
- identity_matrix,
- gfx::PointF(),
- gfx::PointF(),
- gfx::Size(8, 10),
- false);
-
- ExecuteCalculateDrawProperties(root.get());
-
- // Render surfaces should have been created according to clipping rules now
- // (grandchild can't clip self).
- EXPECT_TRUE(root->render_surface());
- EXPECT_FALSE(parent->render_surface());
- EXPECT_TRUE(child->render_surface());
- EXPECT_FALSE(grand_child->render_surface());
-}
-
TEST_F(LayerTreeHostCommonTest, TransformsForReplica) {
scoped_refptr<Layer> root = Layer::Create();
scoped_refptr<Layer> parent = Layer::Create();
@@ -1024,7 +871,7 @@ TEST_F(LayerTreeHostCommonTest, TransformsForReplica) {
gfx::Transform parent_translation_to_anchor;
parent_translation_to_anchor.Translate(2.5, 3.0);
gfx::Transform parent_sublayer_matrix;
- parent_sublayer_matrix.Scale3d(10.0, 10.0, 3.3);
+ parent_sublayer_matrix.Scale3d(10.f, 10.f, 3.3f);
gfx::Transform parent_composite_transform =
parent_translation_to_anchor * parent_layer_transform *
Inverse(parent_translation_to_anchor) * parent_translation_to_anchor *
@@ -5454,6 +5301,121 @@ TEST_F(LayerTreeHostCommonTest, HitTestingForMultipleLayerLists) {
EXPECT_EQ(4, result_layer->id());
}
+TEST_F(LayerTreeHostCommonTest, HitTestingForEmptyLayers) {
+ FakeImplProxy proxy;
+ FakeLayerTreeHostImpl host_impl(&proxy);
+
+ // Layer 1 - root
+ scoped_ptr<LayerImpl> root =
+ LayerImpl::Create(host_impl.active_tree(), 1);
+ gfx::Transform identity_matrix;
+ gfx::PointF anchor;
+ gfx::PointF position;
+ gfx::Size bounds(100, 100);
+ SetLayerPropertiesForTesting(root.get(),
+ identity_matrix,
+ identity_matrix,
+ anchor,
+ position,
+ bounds,
+ false);
+ root->SetDrawsContent(true);
+
+ {
+ // Layer 2 - empty: drawsContent=false
+ gfx::PointF position(10.f, 10.f);
+ gfx::Size bounds(30, 30);
+ scoped_ptr<LayerImpl> empty_layer =
+ LayerImpl::Create(host_impl.active_tree(), 2);
+ SetLayerPropertiesForTesting(empty_layer.get(),
+ identity_matrix,
+ identity_matrix,
+ anchor,
+ position,
+ bounds,
+ false);
+
+ empty_layer->SetDrawsContent(false);
+ root->AddChild(empty_layer.Pass());
+ }
+
+ {
+ // Layer 3 - empty, but has touch handler
+ gfx::PointF position(10.f, 60.f);
+ gfx::Size bounds(30, 30);
+ scoped_ptr<LayerImpl> test_layer =
+ LayerImpl::Create(host_impl.active_tree(), 3);
+ SetLayerPropertiesForTesting(test_layer.get(),
+ identity_matrix,
+ identity_matrix,
+ anchor,
+ position,
+ bounds,
+ false);
+
+ test_layer->SetDrawsContent(false);
+ Region touch_handler_region(gfx::Rect(10, 10, 10, 10));
+ test_layer->SetTouchEventHandlerRegion(touch_handler_region);
+ root->AddChild(test_layer.Pass());
+ }
+
+ {
+ // Layer 4 - empty, but has mousewheel handler
+ gfx::PointF position(60.f, 60.f);
+ gfx::Size bounds(30, 30);
+ scoped_ptr<LayerImpl> test_layer =
+ LayerImpl::Create(host_impl.active_tree(), 4);
+ SetLayerPropertiesForTesting(test_layer.get(),
+ identity_matrix,
+ identity_matrix,
+ anchor,
+ position,
+ bounds,
+ false);
+
+ test_layer->SetDrawsContent(false);
+ test_layer->SetHaveWheelEventHandlers(true);
+ root->AddChild(test_layer.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);
+
+ // Verify that the root layer and empty layers with touch/wheel handlers
+ // (but not the empty layer without a touch handler) are in the RSSL.
+ ASSERT_EQ(1u, render_surface_layer_list.size());
+ EXPECT_EQ(1, render_surface_layer_list[0]->id());
+ ASSERT_EQ(3u, root->render_surface()->layer_list().size());
+ EXPECT_EQ(1, root->render_surface()->layer_list().at(0)->id());
+ EXPECT_EQ(3, root->render_surface()->layer_list().at(1)->id());
+ EXPECT_EQ(4, root->render_surface()->layer_list().at(2)->id());
+
+ // Hit testing for a point inside the empty no-handlers layer should return
+ // the root layer.
+ gfx::Point test_point = gfx::Point(15, 15);
+ LayerImpl* result_layer = LayerTreeHostCommon::FindLayerThatIsHitByPoint(
+ test_point, render_surface_layer_list);
+ ASSERT_TRUE(result_layer);
+ EXPECT_EQ(1, result_layer->id());
+
+ // Hit testing for a point inside the touch handler layer should return it.
+ test_point = gfx::Point(15, 75);
+ result_layer = LayerTreeHostCommon::FindLayerThatIsHitByPoint(
+ test_point, render_surface_layer_list);
+ ASSERT_TRUE(result_layer);
+ EXPECT_EQ(3, result_layer->id());
+
+ // Hit testing for a point inside the mousewheel layer should return it.
+ test_point = gfx::Point(75, 75);
+ result_layer = LayerTreeHostCommon::FindLayerThatIsHitByPoint(
+ test_point, render_surface_layer_list);
+ ASSERT_TRUE(result_layer);
+ EXPECT_EQ(4, result_layer->id());
+}
+
TEST_F(LayerTreeHostCommonTest,
HitCheckingTouchHandlerRegionsForEmptyLayerList) {
// Hit checking on an empty render_surface_layer_list should return a null
@@ -6063,6 +6025,90 @@ TEST_F(LayerTreeHostCommonTest,
EXPECT_EQ(456, result_layer->id());
}
+TEST_F(LayerTreeHostCommonTest,
+ HitCheckingTouchHandlerOverlappingRegions) {
+ gfx::Transform identity_matrix;
+ gfx::PointF anchor;
+
+ FakeImplProxy proxy;
+ FakeLayerTreeHostImpl host_impl(&proxy);
+ scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl.active_tree(), 1);
+ SetLayerPropertiesForTesting(root.get(),
+ identity_matrix,
+ identity_matrix,
+ anchor,
+ gfx::PointF(),
+ gfx::Size(100, 100),
+ false);
+ {
+ scoped_ptr<LayerImpl> touch_layer =
+ LayerImpl::Create(host_impl.active_tree(), 123);
+ // this layer is positioned, and hit testing should correctly know where the
+ // layer is located.
+ gfx::PointF position;
+ gfx::Size bounds(50, 50);
+ SetLayerPropertiesForTesting(touch_layer.get(),
+ identity_matrix,
+ identity_matrix,
+ anchor,
+ position,
+ bounds,
+ false);
+ touch_layer->SetDrawsContent(true);
+ touch_layer->SetTouchEventHandlerRegion(gfx::Rect(0, 0, 50, 50));
+ root->AddChild(touch_layer.Pass());
+ }
+
+ {
+ scoped_ptr<LayerImpl> notouch_layer =
+ LayerImpl::Create(host_impl.active_tree(), 1234);
+ // this layer is positioned, and hit testing should correctly know where the
+ // layer is located.
+ gfx::PointF position(0, 25);
+ gfx::Size bounds(50, 50);
+ SetLayerPropertiesForTesting(notouch_layer.get(),
+ identity_matrix,
+ identity_matrix,
+ anchor,
+ position,
+ bounds,
+ false);
+ notouch_layer->SetDrawsContent(true);
+ root->AddChild(notouch_layer.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);
+
+ // Sanity check the scenario we just created.
+ ASSERT_EQ(1u, render_surface_layer_list.size());
+ ASSERT_EQ(2u, root->render_surface()->layer_list().size());
+ ASSERT_EQ(123, root->render_surface()->layer_list().at(0)->id());
+ ASSERT_EQ(1234, root->render_surface()->layer_list().at(1)->id());
+
+ gfx::Point test_point(35, 35);
+ LayerImpl* result_layer =
+ LayerTreeHostCommon::FindLayerThatIsHitByPointInTouchHandlerRegion(
+ test_point, render_surface_layer_list);
+ EXPECT_FALSE(result_layer);
+
+ test_point = gfx::Point(35, 15);
+ result_layer =
+ LayerTreeHostCommon::FindLayerThatIsHitByPointInTouchHandlerRegion(
+ test_point, render_surface_layer_list);
+ ASSERT_TRUE(result_layer);
+ EXPECT_EQ(123, result_layer->id());
+
+ test_point = gfx::Point(35, 65);
+ result_layer =
+ LayerTreeHostCommon::FindLayerThatIsHitByPointInTouchHandlerRegion(
+ test_point, render_surface_layer_list);
+ EXPECT_FALSE(result_layer);
+}
+
class NoScaleContentLayer : public ContentLayer {
public:
static scoped_refptr<NoScaleContentLayer> Create(ContentLayerClient* client) {
@@ -6245,7 +6291,7 @@ TEST_F(LayerTreeHostCommonTest, SurfaceLayerTransformsInHighDPI) {
perspective_matrix.ApplyPerspectiveDepth(2.0);
gfx::Transform scale_small_matrix;
- scale_small_matrix.Scale(1.0 / 10.0, 1.0 / 12.0);
+ scale_small_matrix.Scale(SK_MScalar1 / 10.f, SK_MScalar1 / 12.f);
scoped_refptr<Layer> root = Layer::Create();
@@ -8883,6 +8929,84 @@ TEST_F(LayerTreeHostCommonTest,
EXPECT_EQ(0, render_surface2->num_unclipped_descendants());
}
+TEST_F(LayerTreeHostCommonTest, CanRenderToSeparateSurface) {
+ FakeImplProxy proxy;
+ FakeLayerTreeHostImpl host_impl(&proxy);
+ scoped_ptr<LayerImpl> root =
+ LayerImpl::Create(host_impl.active_tree(), 12345);
+ scoped_ptr<LayerImpl> child1 =
+ LayerImpl::Create(host_impl.active_tree(), 123456);
+ scoped_ptr<LayerImpl> child2 =
+ LayerImpl::Create(host_impl.active_tree(), 1234567);
+ scoped_ptr<LayerImpl> child3 =
+ LayerImpl::Create(host_impl.active_tree(), 12345678);
+
+ gfx::Transform identity_matrix;
+ gfx::PointF anchor;
+ gfx::PointF position;
+ gfx::Size bounds(100, 100);
+ SetLayerPropertiesForTesting(root.get(),
+ identity_matrix,
+ identity_matrix,
+ anchor,
+ position,
+ bounds,
+ false);
+ root->SetDrawsContent(true);
+
+ // This layer structure normally forces render surface due to preserves3d
+ // behavior.
+ bool preserves3d = true;
+ SetLayerPropertiesForTesting(child1.get(),
+ identity_matrix,
+ identity_matrix,
+ anchor,
+ position,
+ bounds,
+ preserves3d);
+ child1->SetDrawsContent(true);
+ SetLayerPropertiesForTesting(child2.get(),
+ identity_matrix,
+ identity_matrix,
+ anchor,
+ position,
+ bounds,
+ false);
+ child2->SetDrawsContent(true);
+ SetLayerPropertiesForTesting(child3.get(),
+ identity_matrix,
+ identity_matrix,
+ anchor,
+ position,
+ bounds,
+ false);
+ child3->SetDrawsContent(true);
+
+ child2->AddChild(child3.Pass());
+ child1->AddChild(child2.Pass());
+ root->AddChild(child1.Pass());
+
+ {
+ LayerImplList render_surface_layer_list;
+ LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs(
+ root.get(), root->bounds(), &render_surface_layer_list);
+ inputs.can_render_to_separate_surface = true;
+ LayerTreeHostCommon::CalculateDrawProperties(&inputs);
+
+ EXPECT_EQ(2u, render_surface_layer_list.size());
+ }
+
+ {
+ LayerImplList render_surface_layer_list;
+ LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs(
+ root.get(), root->bounds(), &render_surface_layer_list);
+ inputs.can_render_to_separate_surface = false;
+ LayerTreeHostCommon::CalculateDrawProperties(&inputs);
+
+ EXPECT_EQ(1u, render_surface_layer_list.size());
+ }
+}
+
TEST_F(LayerTreeHostCommonTest, DoNotIncludeBackfaceInvisibleSurfaces) {
scoped_refptr<Layer> root = Layer::Create();
scoped_refptr<Layer> render_surface = Layer::Create();
@@ -8945,6 +9069,569 @@ TEST_F(LayerTreeHostCommonTest, DoNotIncludeBackfaceInvisibleSurfaces) {
->render_surface()->layer_list().size());
}
+TEST_F(LayerTreeHostCommonTest, ClippedByScrollParent) {
+ // Checks that the simple case (being clipped by a scroll parent that would
+ // have been processed before you anyhow) results in the right clips.
+ //
+ // + root
+ // + scroll_parent_border
+ // | + scroll_parent_clip
+ // | + scroll_parent
+ // + scroll_child
+ //
+ scoped_refptr<Layer> root = Layer::Create();
+ scoped_refptr<Layer> scroll_parent_border = Layer::Create();
+ scoped_refptr<Layer> scroll_parent_clip = Layer::Create();
+ scoped_refptr<LayerWithForcedDrawsContent> scroll_parent =
+ make_scoped_refptr(new LayerWithForcedDrawsContent);
+ scoped_refptr<LayerWithForcedDrawsContent> scroll_child =
+ make_scoped_refptr(new LayerWithForcedDrawsContent);
+
+ root->AddChild(scroll_child);
+
+ root->AddChild(scroll_parent_border);
+ scroll_parent_border->AddChild(scroll_parent_clip);
+ scroll_parent_clip->AddChild(scroll_parent);
+
+ scroll_parent_clip->SetMasksToBounds(true);
+
+ scroll_child->SetScrollParent(scroll_parent.get());
+
+ gfx::Transform identity_transform;
+ SetLayerPropertiesForTesting(root.get(),
+ identity_transform,
+ identity_transform,
+ gfx::PointF(),
+ gfx::PointF(),
+ gfx::Size(50, 50),
+ false);
+ SetLayerPropertiesForTesting(scroll_parent_border.get(),
+ identity_transform,
+ identity_transform,
+ gfx::PointF(),
+ gfx::PointF(),
+ gfx::Size(40, 40),
+ false);
+ SetLayerPropertiesForTesting(scroll_parent_clip.get(),
+ identity_transform,
+ identity_transform,
+ gfx::PointF(),
+ gfx::PointF(),
+ gfx::Size(30, 30),
+ false);
+ SetLayerPropertiesForTesting(scroll_parent.get(),
+ identity_transform,
+ identity_transform,
+ gfx::PointF(),
+ gfx::PointF(),
+ gfx::Size(50, 50),
+ false);
+ SetLayerPropertiesForTesting(scroll_child.get(),
+ identity_transform,
+ identity_transform,
+ gfx::PointF(),
+ gfx::PointF(),
+ gfx::Size(50, 50),
+ false);
+
+ scoped_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create();
+ host->SetRootLayer(root);
+
+ ExecuteCalculateDrawProperties(root.get());
+
+ EXPECT_TRUE(root->render_surface());
+
+ EXPECT_EQ(gfx::Rect(0, 0, 30, 30).ToString(),
+ scroll_child->clip_rect().ToString());
+ EXPECT_TRUE(scroll_child->is_clipped());
+}
+
+TEST_F(LayerTreeHostCommonTest, ClippedByOutOfOrderScrollParent) {
+ // Checks that clipping by a scroll parent that follows you in paint order
+ // still results in correct clipping.
+ //
+ // + root
+ // + scroll_child
+ // + scroll_parent_border
+ // + scroll_parent_clip
+ // + scroll_parent
+ //
+ scoped_refptr<Layer> root = Layer::Create();
+ scoped_refptr<Layer> scroll_parent_border = Layer::Create();
+ scoped_refptr<Layer> scroll_parent_clip = Layer::Create();
+ scoped_refptr<LayerWithForcedDrawsContent> scroll_parent =
+ make_scoped_refptr(new LayerWithForcedDrawsContent);
+ scoped_refptr<LayerWithForcedDrawsContent> scroll_child =
+ make_scoped_refptr(new LayerWithForcedDrawsContent);
+
+ root->AddChild(scroll_parent_border);
+ scroll_parent_border->AddChild(scroll_parent_clip);
+ scroll_parent_clip->AddChild(scroll_parent);
+
+ root->AddChild(scroll_child);
+
+ scroll_parent_clip->SetMasksToBounds(true);
+
+ scroll_child->SetScrollParent(scroll_parent.get());
+
+ gfx::Transform identity_transform;
+ SetLayerPropertiesForTesting(root.get(),
+ identity_transform,
+ identity_transform,
+ gfx::PointF(),
+ gfx::PointF(),
+ gfx::Size(50, 50),
+ false);
+ SetLayerPropertiesForTesting(scroll_parent_border.get(),
+ identity_transform,
+ identity_transform,
+ gfx::PointF(),
+ gfx::PointF(),
+ gfx::Size(40, 40),
+ false);
+ SetLayerPropertiesForTesting(scroll_parent_clip.get(),
+ identity_transform,
+ identity_transform,
+ gfx::PointF(),
+ gfx::PointF(),
+ gfx::Size(30, 30),
+ false);
+ SetLayerPropertiesForTesting(scroll_parent.get(),
+ identity_transform,
+ identity_transform,
+ gfx::PointF(),
+ gfx::PointF(),
+ gfx::Size(50, 50),
+ false);
+ SetLayerPropertiesForTesting(scroll_child.get(),
+ identity_transform,
+ identity_transform,
+ gfx::PointF(),
+ gfx::PointF(),
+ gfx::Size(50, 50),
+ false);
+
+ scoped_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create();
+ host->SetRootLayer(root);
+
+ ExecuteCalculateDrawProperties(root.get());
+
+ EXPECT_TRUE(root->render_surface());
+
+ EXPECT_EQ(gfx::Rect(0, 0, 30, 30).ToString(),
+ scroll_child->clip_rect().ToString());
+ EXPECT_TRUE(scroll_child->is_clipped());
+}
+
+TEST_F(LayerTreeHostCommonTest, ClippedByOutOfOrderScrollGrandparent) {
+ // Checks that clipping by a scroll parent and scroll grandparent that follow
+ // you in paint order still results in correct clipping.
+ //
+ // + root
+ // + scroll_child
+ // + scroll_parent_border
+ // | + scroll_parent_clip
+ // | + scroll_parent
+ // + scroll_grandparent_border
+ // + scroll_grandparent_clip
+ // + scroll_grandparent
+ //
+ scoped_refptr<Layer> root = Layer::Create();
+ scoped_refptr<Layer> scroll_parent_border = Layer::Create();
+ scoped_refptr<Layer> scroll_parent_clip = Layer::Create();
+ scoped_refptr<LayerWithForcedDrawsContent> scroll_parent =
+ make_scoped_refptr(new LayerWithForcedDrawsContent);
+
+ scoped_refptr<Layer> scroll_grandparent_border = Layer::Create();
+ scoped_refptr<Layer> scroll_grandparent_clip = Layer::Create();
+ scoped_refptr<LayerWithForcedDrawsContent> scroll_grandparent =
+ make_scoped_refptr(new LayerWithForcedDrawsContent);
+
+ scoped_refptr<LayerWithForcedDrawsContent> scroll_child =
+ make_scoped_refptr(new LayerWithForcedDrawsContent);
+
+ root->AddChild(scroll_child);
+
+ root->AddChild(scroll_parent_border);
+ scroll_parent_border->AddChild(scroll_parent_clip);
+ scroll_parent_clip->AddChild(scroll_parent);
+
+ root->AddChild(scroll_grandparent_border);
+ scroll_grandparent_border->AddChild(scroll_grandparent_clip);
+ scroll_grandparent_clip->AddChild(scroll_grandparent);
+
+ scroll_parent_clip->SetMasksToBounds(true);
+ scroll_grandparent_clip->SetMasksToBounds(true);
+
+ scroll_child->SetScrollParent(scroll_parent.get());
+ scroll_parent_border->SetScrollParent(scroll_grandparent.get());
+
+ gfx::Transform identity_transform;
+ SetLayerPropertiesForTesting(root.get(),
+ identity_transform,
+ identity_transform,
+ gfx::PointF(),
+ gfx::PointF(),
+ gfx::Size(50, 50),
+ false);
+ SetLayerPropertiesForTesting(scroll_grandparent_border.get(),
+ identity_transform,
+ identity_transform,
+ gfx::PointF(),
+ gfx::PointF(),
+ gfx::Size(40, 40),
+ false);
+ SetLayerPropertiesForTesting(scroll_grandparent_clip.get(),
+ identity_transform,
+ identity_transform,
+ gfx::PointF(),
+ gfx::PointF(),
+ gfx::Size(20, 20),
+ false);
+ SetLayerPropertiesForTesting(scroll_grandparent.get(),
+ identity_transform,
+ identity_transform,
+ gfx::PointF(),
+ gfx::PointF(),
+ gfx::Size(50, 50),
+ false);
+ SetLayerPropertiesForTesting(scroll_parent_border.get(),
+ identity_transform,
+ identity_transform,
+ gfx::PointF(),
+ gfx::PointF(),
+ gfx::Size(40, 40),
+ false);
+ SetLayerPropertiesForTesting(scroll_parent_clip.get(),
+ identity_transform,
+ identity_transform,
+ gfx::PointF(),
+ gfx::PointF(),
+ gfx::Size(30, 30),
+ false);
+ SetLayerPropertiesForTesting(scroll_parent.get(),
+ identity_transform,
+ identity_transform,
+ gfx::PointF(),
+ gfx::PointF(),
+ gfx::Size(50, 50),
+ false);
+ SetLayerPropertiesForTesting(scroll_child.get(),
+ identity_transform,
+ identity_transform,
+ gfx::PointF(),
+ gfx::PointF(),
+ gfx::Size(50, 50),
+ false);
+
+ scoped_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create();
+ host->SetRootLayer(root);
+
+ ExecuteCalculateDrawProperties(root.get());
+
+ EXPECT_TRUE(root->render_surface());
+
+ EXPECT_EQ(gfx::Rect(0, 0, 20, 20).ToString(),
+ scroll_child->clip_rect().ToString());
+ EXPECT_TRUE(scroll_child->is_clipped());
+
+ // Despite the fact that we visited the above layers out of order to get the
+ // correct clip, the layer lists should be unaffected.
+ EXPECT_EQ(3u, root->render_surface()->layer_list().size());
+ EXPECT_EQ(scroll_child.get(),
+ root->render_surface()->layer_list().at(0));
+ EXPECT_EQ(scroll_parent.get(),
+ root->render_surface()->layer_list().at(1));
+ EXPECT_EQ(scroll_grandparent.get(),
+ root->render_surface()->layer_list().at(2));
+}
+
+TEST_F(LayerTreeHostCommonTest, OutOfOrderClippingRequiresRSLLSorting) {
+ // Ensures that even if we visit layers out of order, we still produce a
+ // correctly ordered render surface layer list.
+ // + root
+ // + scroll_child
+ // + scroll_parent_border
+ // + scroll_parent_clip
+ // + scroll_parent
+ // + render_surface1
+ // + scroll_grandparent_border
+ // + scroll_grandparent_clip
+ // + scroll_grandparent
+ // + render_surface2
+ //
+ scoped_refptr<LayerWithForcedDrawsContent> root =
+ make_scoped_refptr(new LayerWithForcedDrawsContent);
+
+ scoped_refptr<Layer> scroll_parent_border = Layer::Create();
+ scoped_refptr<Layer> scroll_parent_clip = Layer::Create();
+ scoped_refptr<LayerWithForcedDrawsContent> scroll_parent =
+ make_scoped_refptr(new LayerWithForcedDrawsContent);
+ scoped_refptr<LayerWithForcedDrawsContent> render_surface1 =
+ make_scoped_refptr(new LayerWithForcedDrawsContent);
+
+ scoped_refptr<Layer> scroll_grandparent_border = Layer::Create();
+ scoped_refptr<Layer> scroll_grandparent_clip = Layer::Create();
+ scoped_refptr<LayerWithForcedDrawsContent> scroll_grandparent =
+ make_scoped_refptr(new LayerWithForcedDrawsContent);
+ scoped_refptr<LayerWithForcedDrawsContent> render_surface2 =
+ make_scoped_refptr(new LayerWithForcedDrawsContent);
+
+ scoped_refptr<LayerWithForcedDrawsContent> scroll_child =
+ make_scoped_refptr(new LayerWithForcedDrawsContent);
+
+ root->AddChild(scroll_child);
+
+ root->AddChild(scroll_parent_border);
+ scroll_parent_border->AddChild(scroll_parent_clip);
+ scroll_parent_clip->AddChild(scroll_parent);
+ scroll_parent->AddChild(render_surface2);
+
+ root->AddChild(scroll_grandparent_border);
+ scroll_grandparent_border->AddChild(scroll_grandparent_clip);
+ scroll_grandparent_clip->AddChild(scroll_grandparent);
+ scroll_grandparent->AddChild(render_surface1);
+
+ scroll_parent_clip->SetMasksToBounds(true);
+ scroll_grandparent_clip->SetMasksToBounds(true);
+
+ scroll_child->SetScrollParent(scroll_parent.get());
+ scroll_parent_border->SetScrollParent(scroll_grandparent.get());
+
+ render_surface1->SetForceRenderSurface(true);
+ render_surface2->SetForceRenderSurface(true);
+
+ gfx::Transform identity_transform;
+ SetLayerPropertiesForTesting(root.get(),
+ identity_transform,
+ identity_transform,
+ gfx::PointF(),
+ gfx::PointF(),
+ gfx::Size(50, 50),
+ false);
+ SetLayerPropertiesForTesting(scroll_grandparent_border.get(),
+ identity_transform,
+ identity_transform,
+ gfx::PointF(),
+ gfx::PointF(),
+ gfx::Size(40, 40),
+ false);
+ SetLayerPropertiesForTesting(scroll_grandparent_clip.get(),
+ identity_transform,
+ identity_transform,
+ gfx::PointF(),
+ gfx::PointF(),
+ gfx::Size(20, 20),
+ false);
+ SetLayerPropertiesForTesting(scroll_grandparent.get(),
+ identity_transform,
+ identity_transform,
+ gfx::PointF(),
+ gfx::PointF(),
+ gfx::Size(50, 50),
+ false);
+ SetLayerPropertiesForTesting(render_surface1.get(),
+ identity_transform,
+ identity_transform,
+ gfx::PointF(),
+ gfx::PointF(),
+ gfx::Size(50, 50),
+ false);
+ SetLayerPropertiesForTesting(scroll_parent_border.get(),
+ identity_transform,
+ identity_transform,
+ gfx::PointF(),
+ gfx::PointF(),
+ gfx::Size(40, 40),
+ false);
+ SetLayerPropertiesForTesting(scroll_parent_clip.get(),
+ identity_transform,
+ identity_transform,
+ gfx::PointF(),
+ gfx::PointF(),
+ gfx::Size(30, 30),
+ false);
+ SetLayerPropertiesForTesting(scroll_parent.get(),
+ identity_transform,
+ identity_transform,
+ gfx::PointF(),
+ gfx::PointF(),
+ gfx::Size(50, 50),
+ false);
+ SetLayerPropertiesForTesting(render_surface2.get(),
+ identity_transform,
+ identity_transform,
+ gfx::PointF(),
+ gfx::PointF(),
+ gfx::Size(50, 50),
+ false);
+ SetLayerPropertiesForTesting(scroll_child.get(),
+ identity_transform,
+ identity_transform,
+ gfx::PointF(),
+ gfx::PointF(),
+ gfx::Size(50, 50),
+ false);
+
+ scoped_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create();
+ host->SetRootLayer(root);
+
+ RenderSurfaceLayerList render_surface_layer_list;
+ LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
+ root.get(),
+ root->bounds(),
+ identity_transform,
+ &render_surface_layer_list);
+
+ LayerTreeHostCommon::CalculateDrawProperties(&inputs);
+
+ EXPECT_TRUE(root->render_surface());
+
+ EXPECT_EQ(gfx::Rect(0, 0, 20, 20).ToString(),
+ scroll_child->clip_rect().ToString());
+ EXPECT_TRUE(scroll_child->is_clipped());
+
+ // Despite the fact that we had to process the layers out of order to get the
+ // right clip, our render_surface_layer_list's order should be unaffected.
+ EXPECT_EQ(3u, render_surface_layer_list.size());
+ EXPECT_EQ(root.get(), render_surface_layer_list.at(0));
+ EXPECT_EQ(render_surface2.get(), render_surface_layer_list.at(1));
+ EXPECT_EQ(render_surface1.get(), render_surface_layer_list.at(2));
+ EXPECT_TRUE(render_surface_layer_list.at(0)->render_surface());
+ EXPECT_TRUE(render_surface_layer_list.at(1)->render_surface());
+ EXPECT_TRUE(render_surface_layer_list.at(2)->render_surface());
+}
+
+TEST_F(LayerTreeHostCommonTest, DoNotClobberSorting) {
+ // We rearrange layer list contributions if we have to visit children out of
+ // order, but it should be a 'stable' rearrangement. That is, the layer list
+ // additions for a single layer should not be reordered, though their position
+ // wrt to the contributions due to a sibling may vary.
+ //
+ // + root
+ // + scroll_child
+ // + top_content
+ // + bottom_content
+ // + scroll_parent_border
+ // + scroll_parent_clip
+ // + scroll_parent
+ //
+ FakeImplProxy proxy;
+ FakeLayerTreeHostImpl host_impl(&proxy);
+ host_impl.CreatePendingTree();
+ scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl.active_tree(), 1);
+ scoped_ptr<LayerImpl> scroll_parent_border =
+ LayerImpl::Create(host_impl.active_tree(), 2);
+ scoped_ptr<LayerImpl> scroll_parent_clip =
+ LayerImpl::Create(host_impl.active_tree(), 3);
+ scoped_ptr<LayerImpl> scroll_parent =
+ LayerImpl::Create(host_impl.active_tree(), 4);
+ scoped_ptr<LayerImpl> scroll_child =
+ LayerImpl::Create(host_impl.active_tree(), 5);
+ scoped_ptr<LayerImpl> bottom_content =
+ LayerImpl::Create(host_impl.active_tree(), 6);
+ scoped_ptr<LayerImpl> top_content =
+ LayerImpl::Create(host_impl.active_tree(), 7);
+
+ scroll_parent_clip->SetMasksToBounds(true);
+
+ scroll_child->SetScrollParent(scroll_parent.get());
+ scoped_ptr<std::set<LayerImpl*> > scroll_children(new std::set<LayerImpl*>);
+ scroll_children->insert(scroll_child.get());
+ scroll_parent->SetScrollChildren(scroll_children.release());
+
+ scroll_child->SetDrawsContent(true);
+ scroll_parent->SetDrawsContent(true);
+ top_content->SetDrawsContent(true);
+ bottom_content->SetDrawsContent(true);
+
+ gfx::Transform identity_transform;
+ gfx::Transform top_transform;
+ top_transform.Translate3d(0.0, 0.0, 5.0);
+ gfx::Transform bottom_transform;
+ bottom_transform.Translate3d(0.0, 0.0, 3.0);
+
+ SetLayerPropertiesForTesting(root.get(),
+ identity_transform,
+ identity_transform,
+ gfx::PointF(),
+ gfx::PointF(),
+ gfx::Size(50, 50),
+ false);
+ SetLayerPropertiesForTesting(scroll_parent_border.get(),
+ identity_transform,
+ identity_transform,
+ gfx::PointF(),
+ gfx::PointF(),
+ gfx::Size(40, 40),
+ false);
+ SetLayerPropertiesForTesting(scroll_parent_clip.get(),
+ identity_transform,
+ identity_transform,
+ gfx::PointF(),
+ gfx::PointF(),
+ gfx::Size(30, 30),
+ false);
+ SetLayerPropertiesForTesting(scroll_parent.get(),
+ identity_transform,
+ identity_transform,
+ gfx::PointF(),
+ gfx::PointF(),
+ gfx::Size(50, 50),
+ false);
+ SetLayerPropertiesForTesting(scroll_child.get(),
+ identity_transform,
+ identity_transform,
+ gfx::PointF(),
+ gfx::PointF(),
+ gfx::Size(50, 50),
+ false);
+ SetLayerPropertiesForTesting(top_content.get(),
+ top_transform,
+ top_transform,
+ gfx::PointF(),
+ gfx::PointF(),
+ gfx::Size(50, 50),
+ false);
+ SetLayerPropertiesForTesting(bottom_content.get(),
+ bottom_transform,
+ bottom_transform,
+ gfx::PointF(),
+ gfx::PointF(),
+ gfx::Size(50, 50),
+ false);
+
+ scroll_child->SetPreserves3d(true);
+
+ scroll_child->AddChild(top_content.Pass());
+ scroll_child->AddChild(bottom_content.Pass());
+ root->AddChild(scroll_child.Pass());
+
+ scroll_parent_clip->AddChild(scroll_parent.Pass());
+ scroll_parent_border->AddChild(scroll_parent_clip.Pass());
+ root->AddChild(scroll_parent_border.Pass());
+
+ LayerImplList render_surface_layer_list;
+ LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs(
+ root.get(), root->bounds(), &render_surface_layer_list);
+
+ LayerTreeHostCommon::CalculateDrawProperties(&inputs);
+
+ EXPECT_TRUE(root->render_surface());
+
+ // If we don't sort by depth and let the layers get added in the order they
+ // would normally be visited in, then layers 6 and 7 will be out of order. In
+ // other words, although we've had to shift 5, 6, and 7 to appear before 4
+ // in the list (because of the scroll parent relationship), this should not
+ // have an effect on the the order of 5, 6, and 7 (which had been reordered
+ // due to layer sorting).
+ EXPECT_EQ(4u, root->render_surface()->layer_list().size());
+ EXPECT_EQ(5, root->render_surface()->layer_list().at(0)->id());
+ EXPECT_EQ(6, root->render_surface()->layer_list().at(1)->id());
+ EXPECT_EQ(7, root->render_surface()->layer_list().at(2)->id());
+ EXPECT_EQ(4, root->render_surface()->layer_list().at(3)->id());
+}
+
TEST_F(LayerTreeHostCommonTest, ScrollCompensationWithRounding) {
// This test verifies that a scrolling layer that gets snapped to
// integer coordinates doesn't move a fixed position child.
diff --git a/chromium/cc/trees/layer_tree_host_impl.cc b/chromium/cc/trees/layer_tree_host_impl.cc
index a854dff2894..e4d1b735765 100644
--- a/chromium/cc/trees/layer_tree_host_impl.cc
+++ b/chromium/cc/trees/layer_tree_host_impl.cc
@@ -15,9 +15,12 @@
#include "base/strings/stringprintf.h"
#include "cc/animation/scrollbar_animation_controller.h"
#include "cc/animation/timing_function.h"
+#include "cc/base/latency_info_swap_promise_monitor.h"
#include "cc/base/math_util.h"
#include "cc/base/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/overdraw_metrics.h"
#include "cc/debug/paint_time_counter.h"
@@ -31,6 +34,7 @@
#include "cc/layers/layer_iterator.h"
#include "cc/layers/painted_scrollbar_layer_impl.h"
#include "cc/layers/render_surface_impl.h"
+#include "cc/layers/scrollbar_layer_impl_base.h"
#include "cc/output/compositor_frame_metadata.h"
#include "cc/output/copy_output_request.h"
#include "cc/output/delegating_renderer.h"
@@ -54,6 +58,8 @@
#include "cc/trees/quad_culler.h"
#include "cc/trees/single_thread_proxy.h"
#include "cc/trees/tree_synchronizer.h"
+#include "gpu/GLES2/gl2extchromium.h"
+#include "ui/gfx/frame_time.h"
#include "ui/gfx/size_conversions.h"
#include "ui/gfx/vector2d_conversions.h"
@@ -73,24 +79,47 @@ void DidVisibilityChange(cc::LayerTreeHostImpl* id, bool visible) {
}
size_t GetMaxTransferBufferUsageBytes(cc::ContextProvider* context_provider) {
- if (context_provider) {
- // 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;
- // Assuming a two frame deep pipeline between CPU and GPU and we are
- // drawing 60 frames per second which would require us to draw one
- // frame in 16 milliseconds.
- const size_t kMaxTransferBufferUsageBytes = 16 * 2 * kMaxBytesUploadedPerMs;
- return std::min(
- context_provider->ContextCapabilities().max_transfer_buffer_usage_bytes,
- kMaxTransferBufferUsageBytes);
- } else {
- // Software compositing should not use this value in production. Just use a
- // default value when testing uploads with the software compositor.
+ // Software compositing should not use this value in production. Just use a
+ // default value when testing uploads with the software compositor.
+ if (!context_provider)
return std::numeric_limits<size_t>::max();
- }
+
+ // 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;
+ // Assuming a two frame deep pipeline between CPU and GPU and we are
+ // drawing 60 frames per second which would require us to draw one
+ // frame in 16 milliseconds.
+ const size_t kMaxTransferBufferUsageBytes = 16 * 2 * kMaxBytesUploadedPerMs;
+ return std::min(
+ context_provider->ContextCapabilities().max_transfer_buffer_usage_bytes,
+ kMaxTransferBufferUsageBytes);
+}
+
+size_t GetMaxRasterTasksUsageBytes(cc::ContextProvider* context_provider) {
+ // Transfer-buffer/raster-tasks limits are different but related. We make
+ // equal here, as this is ideal when using transfer buffers. When not using
+ // transfer buffers we should still limit raster to something similar, to
+ // preserve caching behavior (and limit memory waste when priorities change).
+ return GetMaxTransferBufferUsageBytes(context_provider);
+}
+
+GLenum GetMapImageTextureTarget(cc::ContextProvider* context_provider) {
+ if (!context_provider)
+ return GL_TEXTURE_2D;
+
+ // TODO(reveman): Determine if GL_TEXTURE_EXTERNAL_OES works well on
+ // Android before we enable this. crbug.com/322780
+#if !defined(OS_ANDROID)
+ if (context_provider->ContextCapabilities().egl_image_external)
+ return GL_TEXTURE_EXTERNAL_OES;
+ if (context_provider->ContextCapabilities().texture_rectangle)
+ return GL_TEXTURE_RECTANGLE_ARB;
+#endif
+
+ return GL_TEXTURE_2D;
}
} // namespace
@@ -178,36 +207,38 @@ scoped_ptr<LayerTreeHostImpl> LayerTreeHostImpl::Create(
const LayerTreeSettings& settings,
LayerTreeHostImplClient* client,
Proxy* proxy,
- RenderingStatsInstrumentation* rendering_stats_instrumentation) {
- return make_scoped_ptr(
- new LayerTreeHostImpl(settings,
- client,
- proxy,
- rendering_stats_instrumentation));
+ RenderingStatsInstrumentation* rendering_stats_instrumentation,
+ SharedBitmapManager* manager,
+ int id) {
+ return make_scoped_ptr(new LayerTreeHostImpl(
+ settings, client, proxy, rendering_stats_instrumentation, manager, id));
}
LayerTreeHostImpl::LayerTreeHostImpl(
const LayerTreeSettings& settings,
LayerTreeHostImplClient* client,
Proxy* proxy,
- RenderingStatsInstrumentation* rendering_stats_instrumentation)
+ RenderingStatsInstrumentation* rendering_stats_instrumentation,
+ SharedBitmapManager* manager,
+ int id)
: client_(client),
proxy_(proxy),
input_handler_client_(NULL),
did_lock_scrolling_layer_(false),
should_bubble_scrolls_(false),
+ last_scroll_did_bubble_(false),
wheel_scrolling_(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_(
PrioritizedResourceManager::DefaultMemoryAllocationLimit(),
- ManagedMemoryPolicy::CUTOFF_ALLOW_EVERYTHING,
- 0,
- ManagedMemoryPolicy::CUTOFF_ALLOW_NOTHING,
+ gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING,
ManagedMemoryPolicy::kDefaultNumResourcesLimit),
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()),
@@ -225,7 +256,13 @@ LayerTreeHostImpl::LayerTreeHostImpl(
external_stencil_test_enabled_(false),
animation_registrar_(AnimationRegistrar::Create()),
rendering_stats_instrumentation_(rendering_stats_instrumentation),
- need_to_update_visible_tiles_before_draw_(false) {
+ micro_benchmark_controller_(this),
+ need_to_update_visible_tiles_before_draw_(false),
+#ifndef NDEBUG
+ did_lose_called_(false),
+#endif
+ shared_bitmap_manager_(manager),
+ id_(id) {
DCHECK(proxy_->IsImplThread());
DidVisibilityChange(this, visible_);
@@ -266,6 +303,16 @@ LayerTreeHostImpl::~LayerTreeHostImpl() {
active_tree_.reset();
}
+void LayerTreeHostImpl::BeginMainFrameAborted(bool did_handle) {
+ // If the begin frame data was handled, then scroll and scale set was applied
+ // by the main thread, so the active tree needs to be updated as if these sent
+ // values were applied and committed.
+ if (did_handle) {
+ active_tree_->ApplySentScrollAndScaleDeltasFromAbortedCommit();
+ active_tree_->ResetContentsTexturesPurged();
+ }
+}
+
void LayerTreeHostImpl::BeginCommit() {}
void LayerTreeHostImpl::CommitComplete() {
@@ -275,7 +322,7 @@ void LayerTreeHostImpl::CommitComplete() {
// Impl-side painting needs an update immediately post-commit to have the
// opportunity to create tilings. Other paths can call UpdateDrawProperties
// more lazily when needed prior to drawing.
- pending_tree()->ApplyScrollDeltasSinceBeginFrame();
+ pending_tree()->ApplyScrollDeltasSinceBeginMainFrame();
pending_tree_->set_needs_update_draw_properties();
pending_tree_->UpdateDrawProperties();
// Start working on newly created tiles immediately if needed.
@@ -290,6 +337,8 @@ void LayerTreeHostImpl::CommitComplete() {
}
client_->SendManagedMemoryStats();
+
+ micro_benchmark_controller_.DidCompleteCommit();
}
bool LayerTreeHostImpl::CanDraw() const {
@@ -363,7 +412,7 @@ void LayerTreeHostImpl::ManageTiles() {
return;
tile_priorities_dirty_ = false;
- tile_manager_->ManageTiles();
+ tile_manager_->ManageTiles(global_tile_state_);
size_t memory_required_bytes;
size_t memory_nice_to_have_bytes;
@@ -413,42 +462,36 @@ void LayerTreeHostImpl::StartPageScaleAnimation(gfx::Vector2d target_offset,
duration.InSecondsF());
}
- client_->SetNeedsRedrawOnImplThread();
+ SetNeedsRedraw();
client_->SetNeedsCommitOnImplThread();
client_->RenewTreePriority();
}
void LayerTreeHostImpl::ScheduleAnimation() {
- client_->SetNeedsRedrawOnImplThread();
+ SetNeedsRedraw();
}
bool LayerTreeHostImpl::HaveTouchEventHandlersAt(gfx::Point viewport_point) {
+ if (!settings_.touch_hit_testing)
+ return true;
if (!EnsureRenderSurfaceLayerList())
return false;
gfx::PointF device_viewport_point =
gfx::ScalePoint(viewport_point, device_scale_factor_);
- // First find out which layer was hit from the saved list of visible layers
- // in the most recent frame.
- LayerImpl* layer_impl = LayerTreeHostCommon::FindLayerThatIsHitByPoint(
- device_viewport_point,
- active_tree_->RenderSurfaceLayerList());
-
- // Walk up the hierarchy and look for a layer with a touch event handler
- // region that the given point hits.
- for (; layer_impl; layer_impl = layer_impl->parent()) {
- if (LayerTreeHostCommon::LayerHasTouchEventHandlersAt(device_viewport_point,
- layer_impl))
- return true;
- }
-
- return false;
+ LayerImpl* layer_impl =
+ LayerTreeHostCommon::FindLayerThatIsHitByPointInTouchHandlerRegion(
+ device_viewport_point,
+ active_tree_->RenderSurfaceLayerList());
+ return layer_impl != NULL;
}
-void LayerTreeHostImpl::SetLatencyInfoForInputEvent(
- const ui::LatencyInfo& latency_info) {
- active_tree()->SetLatencyInfo(latency_info);
+scoped_ptr<SwapPromiseMonitor>
+LayerTreeHostImpl::CreateLatencyInfoSwapPromiseMonitor(
+ ui::LatencyInfo* latency) {
+ return scoped_ptr<SwapPromiseMonitor>(
+ new LatencyInfoSwapPromiseMonitor(latency, NULL, this));
}
void LayerTreeHostImpl::TrackDamageForAllSurfaces(
@@ -471,8 +514,7 @@ void LayerTreeHostImpl::TrackDamageForAllSurfaces(
render_surface->SurfacePropertyChangedOnlyFromDescendant(),
render_surface->content_rect(),
render_surface_layer->mask_layer(),
- render_surface_layer->filters(),
- render_surface_layer->filter().get());
+ render_surface_layer->filters());
}
}
@@ -507,7 +549,8 @@ static DrawMode GetDrawMode(OutputSurface* output_surface) {
} else if (output_surface->context_provider()) {
return DRAW_MODE_HARDWARE;
} else {
- DCHECK(output_surface->software_device());
+ DCHECK_EQ(!output_surface->software_device(),
+ output_surface->capabilities().delegated_rendering);
return DRAW_MODE_SOFTWARE;
}
}
@@ -557,8 +600,9 @@ static void AppendQuadsForRenderSurfaceLayer(
}
static void AppendQuadsToFillScreen(
- ResourceProvider::ResourceId resource_id,
- gfx::SizeF resource_scaled_size,
+ ResourceProvider::ResourceId overhang_resource_id,
+ gfx::SizeF overhang_resource_scaled_size,
+ gfx::Rect root_scroll_layer_rect,
RenderPass* target_render_pass,
LayerImpl* root_layer,
SkColor screen_background_color,
@@ -570,6 +614,16 @@ static void AppendQuadsToFillScreen(
if (fill_region.IsEmpty())
return;
+ // Divide the fill region into the part to be filled with the overhang
+ // resource and the part to be filled with the background color.
+ Region screen_background_color_region = fill_region;
+ Region overhang_region;
+ if (overhang_resource_id) {
+ overhang_region = fill_region;
+ overhang_region.Subtract(root_scroll_layer_rect);
+ screen_background_color_region.Intersect(root_scroll_layer_rect);
+ }
+
bool for_surface = false;
QuadCuller quad_culler(&target_render_pass->quad_list,
&target_render_pass->shared_quad_state_list,
@@ -592,7 +646,8 @@ static void AppendQuadsToFillScreen(
root_target_rect,
root_target_rect,
false,
- opacity);
+ opacity,
+ SkXfermode::kSrcOver_Mode);
AppendQuadsData append_quads_data;
@@ -600,38 +655,44 @@ static void AppendQuadsToFillScreen(
bool did_invert = root_layer->screen_space_transform().GetInverse(
&transform_to_layer_space);
DCHECK(did_invert);
- for (Region::Iterator fill_rects(fill_region);
+ for (Region::Iterator fill_rects(screen_background_color_region);
fill_rects.has_rect();
fill_rects.next()) {
// The root layer transform is composed of translations and scales only,
// no perspective, so mapping is sufficient (as opposed to projecting).
gfx::Rect layer_rect =
MathUtil::MapClippedRect(transform_to_layer_space, fill_rects.rect());
- if (resource_id) {
- scoped_ptr<TextureDrawQuad> tex_quad = TextureDrawQuad::Create();
- const float vertex_opacity[4] = {1.f, 1.f, 1.f, 1.f};
- tex_quad->SetNew(
- shared_quad_state,
- layer_rect,
- layer_rect,
- resource_id,
- false,
- gfx::PointF(layer_rect.x() / resource_scaled_size.width(),
- layer_rect.y() / resource_scaled_size.height()),
- gfx::PointF(layer_rect.right() / resource_scaled_size.width(),
- layer_rect.bottom() / resource_scaled_size.height()),
- screen_background_color,
- vertex_opacity,
- false);
- quad_culler.Append(tex_quad.PassAs<DrawQuad>(), &append_quads_data);
- } else {
- // Skip the quad culler and just append the quads directly to avoid
- // occlusion checks.
- scoped_ptr<SolidColorDrawQuad> quad = SolidColorDrawQuad::Create();
- quad->SetNew(
- shared_quad_state, layer_rect, screen_background_color, false);
- quad_culler.Append(quad.PassAs<DrawQuad>(), &append_quads_data);
- }
+ // Skip the quad culler and just append the quads directly to avoid
+ // occlusion checks.
+ scoped_ptr<SolidColorDrawQuad> quad = SolidColorDrawQuad::Create();
+ quad->SetNew(
+ shared_quad_state, layer_rect, screen_background_color, false);
+ quad_culler.Append(quad.PassAs<DrawQuad>(), &append_quads_data);
+ }
+ for (Region::Iterator fill_rects(overhang_region);
+ fill_rects.has_rect();
+ fill_rects.next()) {
+ DCHECK(overhang_resource_id);
+ gfx::Rect layer_rect =
+ MathUtil::MapClippedRect(transform_to_layer_space, fill_rects.rect());
+ scoped_ptr<TextureDrawQuad> tex_quad = TextureDrawQuad::Create();
+ const float vertex_opacity[4] = {1.f, 1.f, 1.f, 1.f};
+ tex_quad->SetNew(
+ shared_quad_state,
+ layer_rect,
+ layer_rect,
+ overhang_resource_id,
+ false,
+ gfx::PointF(layer_rect.x() / overhang_resource_scaled_size.width(),
+ layer_rect.y() / overhang_resource_scaled_size.height()),
+ gfx::PointF(layer_rect.right() /
+ overhang_resource_scaled_size.width(),
+ layer_rect.bottom() /
+ overhang_resource_scaled_size.height()),
+ screen_background_color,
+ vertex_opacity,
+ false);
+ quad_culler.Append(tex_quad.PassAs<DrawQuad>(), &append_quads_data);
}
}
@@ -737,8 +798,7 @@ bool LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) {
RenderPass* target_render_pass =
frame->render_passes_by_id[target_render_pass_id];
- bool prevent_occlusion = it.target_render_surface_layer()->HasCopyRequest();
- occlusion_tracker.EnterLayer(it, prevent_occlusion);
+ occlusion_tracker.EnterLayer(it);
AppendQuadsData append_quads_data(target_render_pass_id);
@@ -759,21 +819,15 @@ bool LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) {
contributing_render_pass,
occlusion_tracker,
&append_quads_data);
- } else if (it.represents_itself() &&
+ } else if (it.represents_itself() && it->DrawsContent() &&
!it->visible_content_rect().IsEmpty()) {
- bool has_occlusion_from_outside_target_surface;
bool impl_draw_transform_is_unknown = false;
- if (occlusion_tracker.Occluded(
+ bool occluded = occlusion_tracker.Occluded(
it->render_target(),
it->visible_content_rect(),
it->draw_transform(),
- impl_draw_transform_is_unknown,
- it->is_clipped(),
- it->clip_rect(),
- &has_occlusion_from_outside_target_surface)) {
- append_quads_data.had_occlusion_from_outside_target_surface |=
- has_occlusion_from_outside_target_surface;
- } else if (it->WillDraw(draw_mode, resource_provider_.get())) {
+ impl_draw_transform_is_unknown);
+ if (!occluded && it->WillDraw(draw_mode, resource_provider_.get())) {
DCHECK_EQ(active_tree_, it->layer_tree_impl());
frame->will_draw_layers.push_back(*it);
@@ -806,12 +860,7 @@ bool LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) {
++layers_drawn;
}
- if (append_quads_data.had_occlusion_from_outside_target_surface)
- target_render_pass->has_occlusion_from_outside_target_surface = true;
-
if (append_quads_data.num_missing_tiles) {
- rendering_stats_instrumentation_->AddMissingTiles(
- append_quads_data.num_missing_tiles);
bool layer_has_animating_transform =
it->screen_space_transform_is_animating() ||
it->draw_transform_is_animating();
@@ -829,8 +878,6 @@ bool LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) {
output_surface_->capabilities().draw_and_swap_full_viewport_every_frame)
draw_frame = true;
- rendering_stats_instrumentation_->AddLayersDrawn(layers_drawn);
-
#ifndef NDEBUG
for (size_t i = 0; i < frame->render_passes.size(); ++i) {
for (size_t j = 0; j < frame->render_passes[i]->quad_list.size(); ++j)
@@ -843,13 +890,14 @@ bool LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) {
if (!active_tree_->has_transparent_background()) {
frame->render_passes.back()->has_transparent_background = false;
- AppendQuadsToFillScreen(ResourceIdForUIResource(overhang_ui_resource_id_),
- gfx::ScaleSize(overhang_ui_resource_size_,
- device_scale_factor_),
- frame->render_passes.back(),
- active_tree_->root_layer(),
- active_tree_->background_color(),
- occlusion_tracker);
+ AppendQuadsToFillScreen(
+ ResourceIdForUIResource(overhang_ui_resource_id_),
+ gfx::ScaleSize(overhang_ui_resource_size_, device_scale_factor_),
+ active_tree_->RootScrollLayerDeviceViewportBounds(),
+ frame->render_passes.back(),
+ active_tree_->root_layer(),
+ active_tree_->background_color(),
+ occlusion_tracker);
}
if (draw_frame)
@@ -858,10 +906,7 @@ bool LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) {
DCHECK(!have_copy_request);
RemoveRenderPasses(CullRenderPassesWithNoQuads(), frame);
- if (!output_surface_->ForcedDrawToSoftwareDevice())
- renderer_->DecideRenderPassAllocationsForFrame(frame->render_passes);
- RemoveRenderPasses(CullRenderPassesWithCachedTextures(renderer_.get()),
- frame);
+ renderer_->DecideRenderPassAllocationsForFrame(frame->render_passes);
// Any copy requests left in the tree are not going to get serviced, and
// should be aborted.
@@ -875,6 +920,11 @@ bool LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) {
// If we're making a frame to draw, it better have at least one render pass.
DCHECK(!frame->render_passes.empty());
+
+ // Should only have one render pass in resourceless software mode.
+ if (output_surface_->ForcedDrawToSoftwareDevice())
+ DCHECK_EQ(1u, frame->render_passes.size());
+
return draw_frame;
}
@@ -906,6 +956,11 @@ void LayerTreeHostImpl::UpdateBackgroundAnimateTicking(
time_source_client_adapter_->SetActive(enabled);
}
+void LayerTreeHostImpl::DidAnimateScrollOffset() {
+ client_->SetNeedsCommitOnImplThread();
+ client_->RenewTreePriority();
+}
+
void LayerTreeHostImpl::SetViewportDamage(gfx::Rect damage_rect) {
viewport_damage_rect_.Union(damage_rect);
}
@@ -954,24 +1009,6 @@ static void RemoveRenderPassesRecursive(RenderPass::Id remove_render_pass_id,
}
}
-bool LayerTreeHostImpl::CullRenderPassesWithCachedTextures::
- ShouldRemoveRenderPass(const RenderPassDrawQuad& quad,
- const FrameData& frame) const {
- DCHECK(renderer_);
- bool quad_has_damage = !quad.contents_changed_since_last_frame.IsEmpty();
- bool quad_has_cached_resource =
- renderer_->HaveCachedResourcesForRenderPassId(quad.render_pass_id);
- if (quad_has_damage) {
- TRACE_EVENT0("cc", "CullRenderPassesWithCachedTextures have damage");
- return false;
- } else if (!quad_has_cached_resource) {
- TRACE_EVENT0("cc", "CullRenderPassesWithCachedTextures have no texture");
- return false;
- }
- TRACE_EVENT0("cc", "CullRenderPassesWithCachedTextures dropped!");
- return true;
-}
-
bool LayerTreeHostImpl::CullRenderPassesWithNoQuads::ShouldRemoveRenderPass(
const RenderPassDrawQuad& quad, const FrameData& frame) const {
const RenderPass* render_pass =
@@ -1000,9 +1037,6 @@ bool LayerTreeHostImpl::CullRenderPassesWithNoQuads::ShouldRemoveRenderPass(
// Defined for linking tests.
template CC_EXPORT void LayerTreeHostImpl::RemoveRenderPasses<
- LayerTreeHostImpl::CullRenderPassesWithCachedTextures>(
- CullRenderPassesWithCachedTextures culler, FrameData* frame);
-template CC_EXPORT void LayerTreeHostImpl::RemoveRenderPasses<
LayerTreeHostImpl::CullRenderPassesWithNoQuads>(
CullRenderPassesWithNoQuads culler, FrameData*);
@@ -1100,11 +1134,10 @@ void LayerTreeHostImpl::EnforceManagedMemoryPolicy(
const ManagedMemoryPolicy& policy) {
bool evicted_resources = client_->ReduceContentsTextureMemoryOnImplThread(
- visible_ ? policy.bytes_limit_when_visible
- : policy.bytes_limit_when_not_visible,
+ visible_ ? policy.bytes_limit_when_visible : 0,
ManagedMemoryPolicy::PriorityCutoffToValue(
visible_ ? policy.priority_cutoff_when_visible
- : policy.priority_cutoff_when_not_visible));
+ : gpu::MemoryAllocation::CUTOFF_ALLOW_NOTHING));
if (evicted_resources) {
active_tree_->SetContentsTexturesPurged();
if (pending_tree_)
@@ -1123,23 +1156,21 @@ void LayerTreeHostImpl::UpdateTileManagerMemoryPolicy(
if (!tile_manager_)
return;
- GlobalStateThatImpactsTilePriority new_state(tile_manager_->GlobalState());
- new_state.memory_limit_in_bytes = visible_ ?
- policy.bytes_limit_when_visible :
- policy.bytes_limit_when_not_visible;
// TODO(reveman): We should avoid keeping around unused resources if
// possible. crbug.com/224475
- new_state.unused_memory_limit_in_bytes = static_cast<size_t>(
- (static_cast<int64>(new_state.memory_limit_in_bytes) *
+ global_tile_state_.memory_limit_in_bytes =
+ visible_ ?
+ policy.bytes_limit_when_visible : 0;
+ global_tile_state_.unused_memory_limit_in_bytes = static_cast<size_t>(
+ (static_cast<int64>(global_tile_state_.memory_limit_in_bytes) *
settings_.max_unused_resource_memory_percentage) / 100);
- new_state.memory_limit_policy =
+ global_tile_state_.memory_limit_policy =
ManagedMemoryPolicy::PriorityCutoffToTileMemoryLimitPolicy(
visible_ ?
policy.priority_cutoff_when_visible :
- policy.priority_cutoff_when_not_visible);
- new_state.num_resources_limit = policy.num_resources_limit;
+ gpu::MemoryAllocation::CUTOFF_ALLOW_NOTHING);
+ global_tile_state_.num_resources_limit = policy.num_resources_limit;
- tile_manager_->SetGlobalState(new_state);
DidModifyTilePriorities();
}
@@ -1166,11 +1197,6 @@ void LayerTreeHostImpl::SetMemoryPolicy(const ManagedMemoryPolicy& policy) {
SetManagedMemoryPolicy(policy, zero_budget_);
}
-void LayerTreeHostImpl::SetDiscardBackBufferWhenNotVisible(bool discard) {
- DCHECK(renderer_);
- renderer_->SetDiscardBackBufferWhenNotVisible(discard);
-}
-
void LayerTreeHostImpl::SetTreeActivationCallback(
const base::Closure& callback) {
DCHECK(proxy_->IsImplThread());
@@ -1231,11 +1257,18 @@ void LayerTreeHostImpl::SetExternalDrawConstraints(
}
void LayerTreeHostImpl::SetNeedsRedrawRect(gfx::Rect damage_rect) {
+ if (damage_rect.IsEmpty())
+ return;
+ NotifySwapPromiseMonitorsOfSetNeedsRedraw();
client_->SetNeedsRedrawRectOnImplThread(damage_rect);
}
-void LayerTreeHostImpl::BeginFrame(const BeginFrameArgs& args) {
- client_->BeginFrameOnImplThread(args);
+void LayerTreeHostImpl::BeginImplFrame(const BeginFrameArgs& args) {
+ client_->BeginImplFrame(args);
+}
+
+void LayerTreeHostImpl::DidSwapBuffers() {
+ client_->DidSwapBuffersOnImplThread();
}
void LayerTreeHostImpl::OnSwapBuffersComplete() {
@@ -1261,7 +1294,6 @@ CompositorFrameMetadata LayerTreeHostImpl::MakeCompositorFrameMetadata() const {
metadata.root_layer_size = active_tree_->ScrollableSize();
metadata.min_page_scale_factor = active_tree_->min_page_scale_factor();
metadata.max_page_scale_factor = active_tree_->max_page_scale_factor();
- metadata.latency_info = active_tree_->GetLatencyInfo();
if (top_controls_manager_) {
metadata.location_bar_offset =
gfx::Vector2dF(0.f, top_controls_manager_->controls_top_offset());
@@ -1296,15 +1328,12 @@ void LayerTreeHostImpl::DrawLayers(FrameData* frame,
DCHECK(!frame->render_passes.empty());
- int old_dropped_frame_count = fps_counter_->dropped_frame_count();
fps_counter_->SaveTimeStamp(frame_begin_time,
!output_surface_->context_provider());
bool on_main_thread = false;
- rendering_stats_instrumentation_->IncrementScreenFrameCount(
+ rendering_stats_instrumentation_->IncrementFrameCount(
1, on_main_thread);
- rendering_stats_instrumentation_->IncrementDroppedFrameCount(
- fps_counter_->dropped_frame_count() - old_dropped_frame_count);
if (tile_manager_) {
memory_history_->SaveEntry(
@@ -1347,16 +1376,26 @@ void LayerTreeHostImpl::DrawLayers(FrameData* frame,
// Because the contents of the HUD depend on everything else in the frame, the
// contents of its texture are updated as the last thing before the frame is
// drawn.
- if (active_tree_->hud_layer())
- active_tree_->hud_layer()->UpdateHudTexture(resource_provider_.get());
+ if (active_tree_->hud_layer()) {
+ TRACE_EVENT0("cc", "DrawLayers.UpdateHudTexture");
+ active_tree_->hud_layer()->UpdateHudTexture(
+ GetDrawMode(output_surface_.get()), resource_provider_.get());
+ }
if (output_surface_->ForcedDrawToSoftwareDevice()) {
bool allow_partial_swap = false;
+ bool disable_picture_quad_image_filtering =
+ IsCurrentlyScrolling() || needs_animate_layers();
scoped_ptr<SoftwareRenderer> temp_software_renderer =
SoftwareRenderer::Create(this, &settings_, output_surface_.get(), NULL);
- temp_software_renderer->DrawFrame(
- &frame->render_passes, NULL, device_scale_factor_, allow_partial_swap);
+ temp_software_renderer->DrawFrame(&frame->render_passes,
+ NULL,
+ device_scale_factor_,
+ DeviceViewport(),
+ DeviceClip(),
+ allow_partial_swap,
+ disable_picture_quad_image_filtering);
} else {
// We don't track damage on the HUD layer (it interacts with damage tracking
// visualizations), so disable partial swaps to make the HUD layer display
@@ -1366,7 +1405,10 @@ void LayerTreeHostImpl::DrawLayers(FrameData* frame,
renderer_->DrawFrame(&frame->render_passes,
offscreen_context_provider_.get(),
device_scale_factor_,
- allow_partial_swap);
+ DeviceViewport(),
+ DeviceClip(),
+ allow_partial_swap,
+ false);
}
// The render passes should be consumed by the renderer.
DCHECK(frame->render_passes.empty());
@@ -1382,7 +1424,8 @@ void LayerTreeHostImpl::DrawLayers(FrameData* frame,
}
active_tree_->root_layer()->ResetAllChangeTrackingForSubtree();
- rendering_stats_instrumentation_->IssueTraceEventForImplThreadStats();
+ BenchmarkInstrumentation::IssueImplThreadRenderingStatsEvent(
+ rendering_stats_instrumentation_->impl_thread_rendering_stats());
rendering_stats_instrumentation_->AccumulateAndClearImplThreadStats();
}
@@ -1410,23 +1453,26 @@ const RendererCapabilities& LayerTreeHostImpl::GetRendererCapabilities() const {
}
bool LayerTreeHostImpl::SwapBuffers(const LayerTreeHostImpl::FrameData& frame) {
- if (frame.has_no_damage)
+ if (frame.has_no_damage) {
+ active_tree()->BreakSwapPromises(SwapPromise::SWAP_FAILS);
return false;
- renderer_->SwapBuffers();
- active_tree_->ClearLatencyInfo();
+ }
+ CompositorFrameMetadata metadata = MakeCompositorFrameMetadata();
+ active_tree()->FinishSwapPromises(&metadata);
+ renderer_->SwapBuffers(metadata);
return true;
}
-void LayerTreeHostImpl::SetNeedsBeginFrame(bool enable) {
+void LayerTreeHostImpl::SetNeedsBeginImplFrame(bool enable) {
if (output_surface_)
- output_surface_->SetNeedsBeginFrame(enable);
+ output_surface_->SetNeedsBeginImplFrame(enable);
}
gfx::SizeF LayerTreeHostImpl::UnscaledScrollableViewportSize() const {
- // The container layer bounds should be used if non-overlay scrollbars may
- // exist since it adjusts for them.
+ // Use the root container layer bounds if it clips to them, otherwise, the
+ // true viewport size should be used.
LayerImpl* container_layer = active_tree_->RootContainerLayer();
- if (!settings_.solid_color_scrollbars && container_layer) {
+ if (container_layer && container_layer->masks_to_bounds()) {
DCHECK(!top_controls_manager_);
DCHECK_EQ(0, overdraw_bottom_height_);
return container_layer->bounds();
@@ -1442,11 +1488,16 @@ gfx::SizeF LayerTreeHostImpl::UnscaledScrollableViewportSize() const {
}
void LayerTreeHostImpl::DidLoseOutputSurface() {
+ if (resource_provider_)
+ resource_provider_->DidLoseOutputSurface();
// TODO(jamesr): The renderer_ check is needed to make some of the
// LayerTreeHostContextTest tests pass, but shouldn't be necessary (or
// important) in production. We should adjust the test to not need this.
if (renderer_)
client_->DidLoseOutputSurfaceOnImplThread();
+#ifndef NDEBUG
+ did_lose_called_ = true;
+#endif
}
void LayerTreeHostImpl::Readback(void* pixels,
@@ -1471,12 +1522,17 @@ LayerImpl* LayerTreeHostImpl::CurrentlyScrollingLayer() const {
return active_tree_->CurrentlyScrollingLayer();
}
+bool LayerTreeHostImpl::IsCurrentlyScrolling() const {
+ return CurrentlyScrollingLayer() ||
+ (RootScrollLayer() && RootScrollLayer()->IsExternalFlingActive());
+}
+
// Content layers can be either directly scrollable or contained in an outer
// scrolling layer which applies the scroll transform. Given a content layer,
// this function returns the associated scroll layer if any.
static LayerImpl* FindScrollLayerForContentLayer(LayerImpl* layer_impl) {
if (!layer_impl)
- return 0;
+ return NULL;
if (layer_impl->scrollable())
return layer_impl;
@@ -1486,7 +1542,7 @@ static LayerImpl* FindScrollLayerForContentLayer(LayerImpl* layer_impl) {
layer_impl->parent()->scrollable())
return layer_impl->parent();
- return 0;
+ return NULL;
}
void LayerTreeHostImpl::CreatePendingTree() {
@@ -1496,9 +1552,7 @@ void LayerTreeHostImpl::CreatePendingTree() {
else
pending_tree_ = LayerTreeImpl::create(this);
client_->OnCanDrawStateChanged(CanDraw());
- TRACE_EVENT_ASYNC_BEGIN0("cc", "PendingTree", pending_tree_.get());
- TRACE_EVENT_ASYNC_STEP0("cc",
- "PendingTree", pending_tree_.get(), "waiting");
+ TRACE_EVENT_ASYNC_BEGIN0("cc", "PendingTree:waiting", pending_tree_.get());
}
void LayerTreeHostImpl::UpdateVisibleTiles() {
@@ -1509,7 +1563,7 @@ void LayerTreeHostImpl::UpdateVisibleTiles() {
void LayerTreeHostImpl::ActivatePendingTree() {
CHECK(pending_tree_);
- TRACE_EVENT_ASYNC_END0("cc", "PendingTree", pending_tree_.get());
+ TRACE_EVENT_ASYNC_END0("cc", "PendingTree:waiting", pending_tree_.get());
need_to_update_visible_tiles_before_draw_ = true;
@@ -1537,24 +1591,20 @@ void LayerTreeHostImpl::ActivatePendingTree() {
// next sync.
pending_tree_.swap(recycle_tree_);
+ active_tree_->DidBecomeActive();
active_tree_->SetRootLayerScrollOffsetDelegate(
root_layer_scroll_offset_delegate_);
- active_tree_->DidBecomeActive();
-
- // Reduce wasted memory now that unlinked resources are guaranteed not
- // to be used.
- client_->ReduceWastedContentsTextureMemoryOnImplThread();
client_->OnCanDrawStateChanged(CanDraw());
- client_->SetNeedsRedrawOnImplThread();
+ SetNeedsRedraw();
client_->RenewTreePriority();
if (debug_state_.continuous_painting) {
const RenderingStats& stats =
rendering_stats_instrumentation_->GetRenderingStats();
- paint_time_counter_->SavePaintTime(
- stats.main_stats.paint_time + stats.main_stats.record_time +
- stats.impl_stats.rasterize_time_for_now_bins_on_pending_tree);
+ paint_time_counter_->SavePaintTime(stats.main_stats.paint_time +
+ stats.main_stats.record_time +
+ stats.impl_stats.rasterize_time);
}
client_->DidActivatePendingTree();
@@ -1563,6 +1613,8 @@ void LayerTreeHostImpl::ActivatePendingTree() {
if (time_source_client_adapter_ && time_source_client_adapter_->Active())
DCHECK(active_tree_->root_layer());
+ devtools_instrumentation::didActivateLayerTree(id_,
+ active_tree_->source_frame_number());
}
void LayerTreeHostImpl::SetVisible(bool visible) {
@@ -1588,18 +1640,20 @@ void LayerTreeHostImpl::SetVisible(bool visible) {
renderer_->SetVisible(visible);
}
+void LayerTreeHostImpl::SetNeedsRedraw() {
+ NotifySwapPromiseMonitorsOfSetNeedsRedraw();
+ client_->SetNeedsRedrawOnImplThread();
+}
+
ManagedMemoryPolicy LayerTreeHostImpl::ActualManagedMemoryPolicy() const {
ManagedMemoryPolicy actual = cached_managed_memory_policy_;
if (debug_state_.rasterize_only_visible_content) {
- actual.priority_cutoff_when_not_visible =
- ManagedMemoryPolicy::CUTOFF_ALLOW_NOTHING;
actual.priority_cutoff_when_visible =
- ManagedMemoryPolicy::CUTOFF_ALLOW_REQUIRED_ONLY;
+ gpu::MemoryAllocation::CUTOFF_ALLOW_REQUIRED_ONLY;
}
if (zero_budget_) {
actual.bytes_limit_when_visible = 0;
- actual.bytes_limit_when_not_visible = 0;
}
return actual;
@@ -1639,8 +1693,7 @@ void LayerTreeHostImpl::CreateAndSetRenderer(
output_surface,
resource_provider,
texture_mailbox_deleter_.get(),
- settings_.highp_threshold_min,
- settings_.force_direct_layer_drawing);
+ settings_.highp_threshold_min);
} else if (output_surface->software_device()) {
renderer_ = SoftwareRenderer::Create(
this, &settings_, output_surface, resource_provider);
@@ -1671,7 +1724,9 @@ void LayerTreeHostImpl::CreateAndSetTileManager(
settings_.num_raster_threads,
rendering_stats_instrumentation_,
using_map_image,
- GetMaxTransferBufferUsageBytes(context_provider));
+ GetMaxTransferBufferUsageBytes(context_provider),
+ GetMaxRasterTasksUsageBytes(context_provider),
+ GetMapImageTextureTarget(context_provider));
UpdateTileManagerMemoryPolicy(ActualManagedMemoryPolicy());
need_to_update_visible_tiles_before_draw_ = false;
@@ -1683,12 +1738,14 @@ void LayerTreeHostImpl::EnforceZeroBudget(bool zero_budget) {
bool LayerTreeHostImpl::InitializeRenderer(
scoped_ptr<OutputSurface> output_surface) {
+#ifndef NDEBUG
+ DCHECK(!renderer_ || did_lose_called_);
+#endif
+
// 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
// before we destroy the old resource provider.
ReleaseTreeResources();
- if (resource_provider_)
- resource_provider_->DidLoseOutputSurface();
// Note: order is important here.
renderer_.reset();
@@ -1699,10 +1756,12 @@ bool LayerTreeHostImpl::InitializeRenderer(
if (!output_surface->BindToClient(this))
return false;
- scoped_ptr<ResourceProvider> resource_provider = ResourceProvider::Create(
- output_surface.get(),
- settings_.highp_threshold_min,
- settings_.use_rgba_4444_textures);
+ scoped_ptr<ResourceProvider> resource_provider =
+ ResourceProvider::Create(output_surface.get(),
+ shared_bitmap_manager_,
+ settings_.highp_threshold_min,
+ settings_.use_rgba_4444_textures,
+ settings_.texture_id_allocation_chunk_size);
if (!resource_provider)
return false;
@@ -1722,14 +1781,14 @@ bool LayerTreeHostImpl::InitializeRenderer(
GetRendererCapabilities().using_map_image);
}
- // Setup BeginFrameEmulation if it's not supported natively
- if (!settings_.begin_frame_scheduling_enabled) {
+ // Setup BeginImplFrameEmulation if it's not supported natively
+ if (!settings_.begin_impl_frame_scheduling_enabled) {
const base::TimeDelta display_refresh_interval =
base::TimeDelta::FromMicroseconds(
base::Time::kMicrosecondsPerSecond /
settings_.refresh_rate);
- output_surface->InitializeBeginFrameEmulation(
+ output_surface->InitializeBeginImplFrameEmulation(
proxy_->ImplThreadTaskRunner(),
settings_.throttle_frame_production,
display_refresh_interval);
@@ -1753,7 +1812,6 @@ bool LayerTreeHostImpl::DeferredInitialize(
scoped_refptr<ContextProvider> offscreen_context_provider) {
DCHECK(output_surface_->capabilities().deferred_gl_initialization);
DCHECK(settings_.impl_side_painting);
- DCHECK(settings_.solid_color_scrollbars);
DCHECK(output_surface_->context_provider());
ReleaseTreeResources();
@@ -1810,7 +1868,6 @@ bool LayerTreeHostImpl::DeferredInitialize(
void LayerTreeHostImpl::ReleaseGL() {
DCHECK(output_surface_->capabilities().deferred_gl_initialization);
DCHECK(settings_.impl_side_painting);
- DCHECK(settings_.solid_color_scrollbars);
DCHECK(output_surface_->context_provider());
ReleaseTreeResources();
@@ -1845,9 +1902,6 @@ void LayerTreeHostImpl::SetViewportSize(gfx::Size device_viewport_size) {
UpdateMaxScrollOffset();
- if (renderer_)
- renderer_->ViewportChanged();
-
client_->OnCanDrawStateChanged(CanDraw());
SetFullRootLayerDamage();
}
@@ -1873,9 +1927,6 @@ void LayerTreeHostImpl::SetDeviceScaleFactor(float device_scale_factor) {
return;
device_scale_factor_ = device_scale_factor;
- if (renderer_)
- renderer_->ViewportChanged();
-
UpdateMaxScrollOffset();
SetFullRootLayerDamage();
}
@@ -1907,7 +1958,7 @@ void LayerTreeHostImpl::UpdateMaxScrollOffset() {
}
void LayerTreeHostImpl::DidChangeTopControlsPosition() {
- client_->SetNeedsRedrawOnImplThread();
+ SetNeedsRedraw();
active_tree_->set_needs_update_draw_properties();
SetFullRootLayerDamage();
}
@@ -1928,26 +1979,10 @@ static LayerImpl* NextScrollLayer(LayerImpl* layer) {
return layer->parent();
}
-InputHandler::ScrollStatus LayerTreeHostImpl::ScrollBegin(
- gfx::Point viewport_point, InputHandler::ScrollInputType type) {
- TRACE_EVENT0("cc", "LayerTreeHostImpl::ScrollBegin");
-
- if (top_controls_manager_)
- top_controls_manager_->ScrollBegin();
-
- DCHECK(!CurrentlyScrollingLayer());
- ClearCurrentlyScrollingLayer();
-
- if (!EnsureRenderSurfaceLayerList())
- return ScrollIgnored;
-
- gfx::PointF device_viewport_point = gfx::ScalePoint(viewport_point,
- device_scale_factor_);
-
- // First find out which layer was hit from the saved list of visible layers
- // in the most recent frame.
- LayerImpl* layer_impl = LayerTreeHostCommon::FindLayerThatIsHitByPoint(
- device_viewport_point, active_tree_->RenderSurfaceLayerList());
+LayerImpl* LayerTreeHostImpl::FindScrollLayerForDeviceViewportPoint(
+ gfx::PointF device_viewport_point, InputHandler::ScrollInputType type,
+ LayerImpl* layer_impl, bool* scroll_on_main_thread) const {
+ DCHECK(scroll_on_main_thread);
// Walk up the hierarchy and look for a scrollable layer.
LayerImpl* potentially_scrolling_layer_impl = 0;
@@ -1956,9 +1991,8 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollBegin(
// thread.
ScrollStatus status = layer_impl->TryScroll(device_viewport_point, type);
if (status == ScrollOnMainThread) {
- rendering_stats_instrumentation_->IncrementMainThreadScrolls();
- UMA_HISTOGRAM_BOOLEAN("TryScroll.SlowScroll", true);
- return ScrollOnMainThread;
+ *scroll_on_main_thread = true;
+ return NULL;
}
LayerImpl* scroll_layer_impl = FindScrollLayerForContentLayer(layer_impl);
@@ -1966,12 +2000,10 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollBegin(
continue;
status = scroll_layer_impl->TryScroll(device_viewport_point, type);
-
// If any layer wants to divert the scroll event to the main thread, abort.
if (status == ScrollOnMainThread) {
- rendering_stats_instrumentation_->IncrementMainThreadScrolls();
- UMA_HISTOGRAM_BOOLEAN("TryScroll.SlowScroll", true);
- return ScrollOnMainThread;
+ *scroll_on_main_thread = true;
+ return NULL;
}
if (status == ScrollStarted && !potentially_scrolling_layer_impl)
@@ -1987,12 +2019,47 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollBegin(
potentially_scrolling_layer_impl = RootScrollLayer();
}
+ return potentially_scrolling_layer_impl;
+}
+
+InputHandler::ScrollStatus LayerTreeHostImpl::ScrollBegin(
+ gfx::Point viewport_point, InputHandler::ScrollInputType type) {
+ TRACE_EVENT0("cc", "LayerTreeHostImpl::ScrollBegin");
+
+ if (top_controls_manager_)
+ top_controls_manager_->ScrollBegin();
+
+ DCHECK(!CurrentlyScrollingLayer());
+ ClearCurrentlyScrollingLayer();
+
+ if (!EnsureRenderSurfaceLayerList())
+ return ScrollIgnored;
+
+ gfx::PointF device_viewport_point = gfx::ScalePoint(viewport_point,
+ device_scale_factor_);
+ LayerImpl* layer_impl = LayerTreeHostCommon::FindLayerThatIsHitByPoint(
+ device_viewport_point,
+ active_tree_->RenderSurfaceLayerList());
+ bool scroll_on_main_thread = false;
+ LayerImpl* potentially_scrolling_layer_impl =
+ FindScrollLayerForDeviceViewportPoint(device_viewport_point, type,
+ layer_impl, &scroll_on_main_thread);
+
+ if (scroll_on_main_thread) {
+ UMA_HISTOGRAM_BOOLEAN("TryScroll.SlowScroll", true);
+ return ScrollOnMainThread;
+ }
+
+ // If we want to send a DidOverscroll for this scroll it can't be ignored.
+ if (!potentially_scrolling_layer_impl && settings_.always_overscroll)
+ potentially_scrolling_layer_impl = RootScrollLayer();
+
if (potentially_scrolling_layer_impl) {
active_tree_->SetCurrentlyScrollingLayer(
potentially_scrolling_layer_impl);
should_bubble_scrolls_ = (type != NonBubblingGesture);
+ last_scroll_did_bubble_ = false;
wheel_scrolling_ = (type == Wheel);
- rendering_stats_instrumentation_->IncrementImplThreadScrolls();
client_->RenewTreePriority();
UMA_HISTOGRAM_BOOLEAN("TryScroll.SlowScroll", false);
return ScrollStarted;
@@ -2095,6 +2162,7 @@ bool LayerTreeHostImpl::ScrollBy(gfx::Point viewport_point,
bool did_scroll_y = false;
bool consume_by_top_controls = top_controls_manager_ &&
(CurrentlyScrollingLayer() == RootScrollLayer() || scroll_delta.y() < 0);
+ last_scroll_did_bubble_ = false;
for (LayerImpl* layer_impl = CurrentlyScrollingLayer();
layer_impl;
@@ -2135,10 +2203,15 @@ bool LayerTreeHostImpl::ScrollBy(gfx::Point viewport_point,
did_scroll_x |= did_move_layer_x;
did_scroll_y |= did_move_layer_y;
if (!did_move_layer_x && !did_move_layer_y) {
- if (should_bubble_scrolls_ || !did_lock_scrolling_layer_)
+ if (!did_lock_scrolling_layer_)
+ continue;
+
+ if (should_bubble_scrolls_) {
+ last_scroll_did_bubble_ = true;
continue;
- else
- break;
+ }
+
+ break;
}
if (layer_impl == RootScrollLayer())
@@ -2172,7 +2245,7 @@ bool LayerTreeHostImpl::ScrollBy(gfx::Point viewport_point,
bool did_scroll = did_scroll_x || did_scroll_y;
if (did_scroll) {
client_->SetNeedsCommitOnImplThread();
- client_->SetNeedsRedrawOnImplThread();
+ SetNeedsRedraw();
client_->RenewTreePriority();
}
@@ -2225,7 +2298,7 @@ bool LayerTreeHostImpl::ScrollVerticallyByPage(gfx::Point viewport_point,
if (!applied_delta.IsZero()) {
client_->SetNeedsCommitOnImplThread();
- client_->SetNeedsRedrawOnImplThread();
+ SetNeedsRedraw();
client_->RenewTreePriority();
return true;
}
@@ -2273,6 +2346,9 @@ InputHandler::ScrollStatus LayerTreeHostImpl::FlingScrollBegin() {
return ScrollIgnored;
}
+ if (!wheel_scrolling_)
+ should_bubble_scrolls_ = last_scroll_did_bubble_;
+
return ScrollStarted;
}
@@ -2280,11 +2356,104 @@ void LayerTreeHostImpl::NotifyCurrentFlingVelocity(gfx::Vector2dF velocity) {
current_fling_velocity_ = velocity;
}
+float LayerTreeHostImpl::DeviceSpaceDistanceToLayer(
+ gfx::PointF device_viewport_point,
+ LayerImpl* layer_impl) {
+ if (!layer_impl)
+ return std::numeric_limits<float>::max();
+
+ gfx::Rect layer_impl_bounds(
+ layer_impl->content_bounds());
+
+ gfx::RectF device_viewport_layer_impl_bounds = MathUtil::MapClippedRect(
+ layer_impl->screen_space_transform(),
+ layer_impl_bounds);
+
+ return device_viewport_layer_impl_bounds.ManhattanDistanceToPoint(
+ device_viewport_point);
+}
+
+void LayerTreeHostImpl::MouseMoveAt(gfx::Point viewport_point) {
+ if (!EnsureRenderSurfaceLayerList())
+ return;
+
+ gfx::PointF device_viewport_point = gfx::ScalePoint(viewport_point,
+ device_scale_factor_);
+
+ LayerImpl* layer_impl = LayerTreeHostCommon::FindLayerThatIsHitByPoint(
+ device_viewport_point,
+ active_tree_->RenderSurfaceLayerList());
+ if (HandleMouseOverScrollbar(layer_impl, device_viewport_point))
+ return;
+
+ if (scroll_layer_id_when_mouse_over_scrollbar_) {
+ LayerImpl* scroll_layer_impl = active_tree_->LayerById(
+ scroll_layer_id_when_mouse_over_scrollbar_);
+
+ ScrollbarAnimationController* animation_controller =
+ scroll_layer_impl->scrollbar_animation_controller();
+ if (animation_controller) {
+ animation_controller->DidMouseMoveOffScrollbar(
+ CurrentPhysicalTimeTicks());
+ StartScrollbarAnimation();
+ }
+ scroll_layer_id_when_mouse_over_scrollbar_ = 0;
+ }
+
+ bool scroll_on_main_thread = false;
+ LayerImpl* scroll_layer_impl = FindScrollLayerForDeviceViewportPoint(
+ device_viewport_point, InputHandler::Gesture, layer_impl,
+ &scroll_on_main_thread);
+ if (scroll_on_main_thread || !scroll_layer_impl)
+ return;
+
+ ScrollbarAnimationController* animation_controller =
+ scroll_layer_impl->scrollbar_animation_controller();
+ if (!animation_controller)
+ return;
+
+ float distance_to_scrollbar = std::min(
+ DeviceSpaceDistanceToLayer(device_viewport_point,
+ scroll_layer_impl->horizontal_scrollbar_layer()),
+ DeviceSpaceDistanceToLayer(device_viewport_point,
+ scroll_layer_impl->vertical_scrollbar_layer()));
+
+ bool should_animate = animation_controller->DidMouseMoveNear(
+ CurrentPhysicalTimeTicks(), distance_to_scrollbar / device_scale_factor_);
+ if (should_animate)
+ StartScrollbarAnimation();
+}
+
+bool LayerTreeHostImpl::HandleMouseOverScrollbar(LayerImpl* layer_impl,
+ gfx::PointF device_viewport_point) {
+ if (layer_impl && layer_impl->ToScrollbarLayer()) {
+ int scroll_layer_id = layer_impl->ToScrollbarLayer()->ScrollLayerId();
+ layer_impl = active_tree_->LayerById(scroll_layer_id);
+ if (layer_impl && layer_impl->scrollbar_animation_controller()) {
+ scroll_layer_id_when_mouse_over_scrollbar_ = scroll_layer_id;
+ bool should_animate =
+ layer_impl->scrollbar_animation_controller()->DidMouseMoveNear(
+ CurrentPhysicalTimeTicks(), 0);
+ if (should_animate)
+ StartScrollbarAnimation();
+ } else {
+ scroll_layer_id_when_mouse_over_scrollbar_ = 0;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
void LayerTreeHostImpl::PinchGestureBegin() {
pinch_gesture_active_ = true;
previous_pinch_anchor_ = gfx::Point();
client_->RenewTreePriority();
+ pinch_gesture_end_should_clear_scrolling_layer_ = !CurrentlyScrollingLayer();
active_tree_->SetCurrentlyScrollingLayer(RootScrollLayer());
+ if (top_controls_manager_)
+ top_controls_manager_->PinchBegin();
}
void LayerTreeHostImpl::PinchGestureUpdate(float magnify_delta,
@@ -2312,12 +2481,18 @@ void LayerTreeHostImpl::PinchGestureUpdate(float magnify_delta,
RootScrollLayer()->ScrollBy(move);
client_->SetNeedsCommitOnImplThread();
- client_->SetNeedsRedrawOnImplThread();
+ SetNeedsRedraw();
client_->RenewTreePriority();
}
void LayerTreeHostImpl::PinchGestureEnd() {
pinch_gesture_active_ = false;
+ if (pinch_gesture_end_should_clear_scrolling_layer_) {
+ pinch_gesture_end_should_clear_scrolling_layer_ = false;
+ ClearCurrentlyScrollingLayer();
+ }
+ if (top_controls_manager_)
+ top_controls_manager_->PinchEnd();
client_->SetNeedsCommitOnImplThread();
}
@@ -2372,7 +2547,7 @@ void LayerTreeHostImpl::AnimatePageScale(base::TimeTicks time) {
page_scale_animation_->ScrollOffsetAtTime(monotonic_time);
RootScrollLayer()->ScrollBy(next_scroll - scroll_total);
- client_->SetNeedsRedrawOnImplThread();
+ SetNeedsRedraw();
if (page_scale_animation_->IsAnimationCompleteAtTime(monotonic_time)) {
page_scale_animation_.reset();
@@ -2411,7 +2586,7 @@ void LayerTreeHostImpl::AnimateLayers(base::TimeTicks monotonic_time,
++iter)
(*iter).second->Animate(monotonic_seconds);
- client_->SetNeedsRedrawOnImplThread();
+ SetNeedsRedraw();
}
void LayerTreeHostImpl::UpdateAnimationState(bool start_ready_animations) {
@@ -2525,7 +2700,7 @@ void LayerTreeHostImpl::AnimateScrollbarsRecursive(LayerImpl* layer,
TRACE_EVENT_INSTANT0(
"cc", "LayerTreeHostImpl::SetNeedsRedraw due to AnimateScrollbars",
TRACE_EVENT_SCOPE_THREAD);
- client_->SetNeedsRedrawOnImplThread();
+ SetNeedsRedraw();
}
for (size_t i = 0; i < layer->children().size(); ++i)
@@ -2549,7 +2724,7 @@ void LayerTreeHostImpl::StartScrollbarAnimationRecursive(LayerImpl* layer,
if (delay > base::TimeDelta())
client_->RequestScrollbarAnimationOnImplThread(delay);
else if (scrollbar_controller->Animate(time))
- client_->SetNeedsRedrawOnImplThread();
+ SetNeedsRedraw();
}
for (size_t i = 0; i < layer->children().size(); ++i)
@@ -2560,12 +2735,9 @@ void LayerTreeHostImpl::SetTreePriority(TreePriority priority) {
if (!tile_manager_)
return;
- GlobalStateThatImpactsTilePriority new_state(tile_manager_->GlobalState());
- if (new_state.tree_priority == priority)
+ if (global_tile_state_.tree_priority == priority)
return;
-
- new_state.tree_priority = priority;
- tile_manager_->SetGlobalState(new_state);
+ global_tile_state_.tree_priority = priority;
DidModifyTilePriorities();
}
@@ -2594,7 +2766,7 @@ base::Time LayerTreeHostImpl::CurrentFrameTime() {
}
base::TimeTicks LayerTreeHostImpl::CurrentPhysicalTimeTicks() const {
- return base::TimeTicks::Now();
+ return gfx::FrameTime::Now();
}
scoped_ptr<base::Value> LayerTreeHostImpl::AsValueWithFrame(
@@ -2630,13 +2802,13 @@ void LayerTreeHostImpl::SetDebugState(
paint_time_counter_->ClearHistory();
debug_state_ = new_debug_state;
+ UpdateTileManagerMemoryPolicy(ActualManagedMemoryPolicy());
SetFullRootLayerDamage();
}
void LayerTreeHostImpl::CreateUIResource(UIResourceId uid,
const UIResourceBitmap& bitmap) {
DCHECK_GT(uid, 0);
- DCHECK_EQ(bitmap.GetFormat(), UIResourceBitmap::RGBA8);
GLint wrap_mode = 0;
switch (bitmap.GetWrapMode()) {
@@ -2653,13 +2825,22 @@ void LayerTreeHostImpl::CreateUIResource(UIResourceId uid,
ResourceProvider::ResourceId id = ResourceIdForUIResource(uid);
if (id)
DeleteUIResource(uid);
+
+ ResourceFormat format = resource_provider_->best_texture_format();
+ if (bitmap.GetFormat() == UIResourceBitmap::ETC1)
+ format = ETC1;
id = resource_provider_->CreateResource(
bitmap.GetSize(),
wrap_mode,
ResourceProvider::TextureUsageAny,
- resource_provider_->best_texture_format());
+ format);
+
+ UIResourceData data;
+ data.resource_id = id;
+ data.size = bitmap.GetSize();
+ data.opaque = bitmap.GetOpaque();
- ui_resource_map_[uid] = id;
+ ui_resource_map_[uid] = data;
AutoLockUIResourceBitmap bitmap_lock(bitmap);
resource_provider_->SetPixels(id,
@@ -2687,7 +2868,7 @@ void LayerTreeHostImpl::EvictAllUIResources() {
iter != ui_resource_map_.end();
++iter) {
evicted_ui_resources_.insert(iter->first);
- resource_provider_->DeleteResource(iter->second);
+ resource_provider_->DeleteResource(iter->second.resource_id);
}
ui_resource_map_.clear();
@@ -2700,10 +2881,16 @@ ResourceProvider::ResourceId LayerTreeHostImpl::ResourceIdForUIResource(
UIResourceId uid) const {
UIResourceMap::const_iterator iter = ui_resource_map_.find(uid);
if (iter != ui_resource_map_.end())
- return iter->second;
+ return iter->second.resource_id;
return 0;
}
+bool LayerTreeHostImpl::IsUIResourceOpaque(UIResourceId uid) const {
+ UIResourceMap::const_iterator iter = ui_resource_map_.find(uid);
+ DCHECK(iter != ui_resource_map_.end());
+ return iter->second.opaque;
+}
+
bool LayerTreeHostImpl::EvictedUIResourcesExist() const {
return !evicted_ui_resources_.empty();
}
@@ -2718,4 +2905,23 @@ void LayerTreeHostImpl::MarkUIResourceNotEvicted(UIResourceId uid) {
client_->OnCanDrawStateChanged(CanDraw());
}
+void LayerTreeHostImpl::ScheduleMicroBenchmark(
+ scoped_ptr<MicroBenchmarkImpl> benchmark) {
+ micro_benchmark_controller_.ScheduleRun(benchmark.Pass());
+}
+
+void LayerTreeHostImpl::InsertSwapPromiseMonitor(SwapPromiseMonitor* monitor) {
+ swap_promise_monitor_.insert(monitor);
+}
+
+void LayerTreeHostImpl::RemoveSwapPromiseMonitor(SwapPromiseMonitor* monitor) {
+ swap_promise_monitor_.erase(monitor);
+}
+
+void LayerTreeHostImpl::NotifySwapPromiseMonitorsOfSetNeedsRedraw() {
+ std::set<SwapPromiseMonitor*>::iterator it = swap_promise_monitor_.begin();
+ for (; it != swap_promise_monitor_.end(); it++)
+ (*it)->OnSetNeedsRedrawOnImpl();
+}
+
} // namespace cc
diff --git a/chromium/cc/trees/layer_tree_host_impl.h b/chromium/cc/trees/layer_tree_host_impl.h
index 6d969012deb..531384f6fdb 100644
--- a/chromium/cc/trees/layer_tree_host_impl.h
+++ b/chromium/cc/trees/layer_tree_host_impl.h
@@ -17,6 +17,7 @@
#include "cc/animation/animation_events.h"
#include "cc/animation/animation_registrar.h"
#include "cc/base/cc_export.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"
@@ -47,6 +48,7 @@ class PaintTimeCounter;
class MemoryHistory;
class RenderingStatsInstrumentation;
class RenderPassDrawQuad;
+class ScrollbarLayerImplBase;
class TextureMailboxDeleter;
class TopControlsManager;
class UIResourceBitmap;
@@ -57,10 +59,13 @@ struct RendererCapabilities;
class LayerTreeHostImplClient {
public:
virtual void DidLoseOutputSurfaceOnImplThread() = 0;
+ virtual void DidSwapBuffersOnImplThread() = 0;
virtual void OnSwapBuffersCompleteOnImplThread() = 0;
- virtual void BeginFrameOnImplThread(const BeginFrameArgs& args) = 0;
+ virtual void BeginImplFrame(const BeginFrameArgs& args) = 0;
virtual void OnCanDrawStateChanged(bool can_draw) = 0;
virtual void NotifyReadyToActivate() = 0;
+ // Please call these 2 functions through
+ // LayerTreeHostImpl's SetNeedsRedraw() and SetNeedsRedrawRect().
virtual void SetNeedsRedrawOnImplThread() = 0;
virtual void SetNeedsRedrawRectOnImplThread(gfx::Rect damage_rect) = 0;
virtual void DidInitializeVisibleTileOnImplThread() = 0;
@@ -73,12 +78,12 @@ class LayerTreeHostImplClient {
virtual bool ReduceContentsTextureMemoryOnImplThread(
size_t limit_bytes,
int priority_cutoff) = 0;
- virtual void ReduceWastedContentsTextureMemoryOnImplThread() = 0;
virtual void SendManagedMemoryStats() = 0;
virtual bool IsInsideDraw() = 0;
virtual void RenewTreePriority() = 0;
virtual void RequestScrollbarAnimationOnImplThread(base::TimeDelta delay) = 0;
virtual void DidActivatePendingTree() = 0;
+ virtual void DidManageTiles() = 0;
protected:
virtual ~LayerTreeHostImplClient() {}
@@ -98,7 +103,9 @@ class CC_EXPORT LayerTreeHostImpl
const LayerTreeSettings& settings,
LayerTreeHostImplClient* client,
Proxy* proxy,
- RenderingStatsInstrumentation* rendering_stats_instrumentation);
+ RenderingStatsInstrumentation* rendering_stats_instrumentation,
+ SharedBitmapManager* manager,
+ int id);
virtual ~LayerTreeHostImpl();
// InputHandler implementation
@@ -116,6 +123,7 @@ class CC_EXPORT LayerTreeHostImpl
virtual void ScrollEnd() OVERRIDE;
virtual InputHandler::ScrollStatus FlingScrollBegin() OVERRIDE;
virtual void NotifyCurrentFlingVelocity(gfx::Vector2dF velocity) OVERRIDE;
+ virtual void MouseMoveAt(gfx::Point viewport_point) OVERRIDE;
virtual void PinchGestureBegin() OVERRIDE;
virtual void PinchGestureUpdate(float magnify_delta,
gfx::Point anchor) OVERRIDE;
@@ -126,8 +134,8 @@ class CC_EXPORT LayerTreeHostImpl
base::TimeDelta duration) OVERRIDE;
virtual void ScheduleAnimation() OVERRIDE;
virtual bool HaveTouchEventHandlersAt(gfx::Point viewport_port) OVERRIDE;
- virtual void SetLatencyInfoForInputEvent(const ui::LatencyInfo& latency_info)
- OVERRIDE;
+ virtual scoped_ptr<SwapPromiseMonitor> CreateLatencyInfoSwapPromiseMonitor(
+ ui::LatencyInfo* latency) OVERRIDE;
// TopControlsManagerClient implementation.
virtual void DidChangeTopControlsPosition() OVERRIDE;
@@ -153,6 +161,7 @@ class CC_EXPORT LayerTreeHostImpl
virtual void AppendRenderPass(scoped_ptr<RenderPass> render_pass) OVERRIDE;
};
+ virtual void BeginMainFrameAborted(bool did_handle);
virtual void BeginCommit();
virtual void CommitComplete();
virtual void Animate(base::TimeTicks monotonic_time,
@@ -160,6 +169,7 @@ class CC_EXPORT LayerTreeHostImpl
virtual void UpdateAnimationState(bool start_ready_animations);
void MainThreadHasStoppedFlinging();
void UpdateBackgroundAnimateTicking(bool should_background_tick);
+ void DidAnimateScrollOffset();
void SetViewportDamage(gfx::Rect damage_rect);
virtual void ManageTiles();
@@ -200,15 +210,8 @@ class CC_EXPORT LayerTreeHostImpl
// invariant relative to page scale).
gfx::SizeF UnscaledScrollableViewportSize() const;
- // RendererClient implementation
-
- // Viewport rectangle and clip in nonflipped window space. These rects
- // should only be used by Renderer subclasses to populate glViewport/glClip
- // and their software-mode equivalents.
- virtual gfx::Rect DeviceViewport() const OVERRIDE;
- virtual gfx::Rect DeviceClip() const OVERRIDE;
+ // RendererClient implementation.
virtual void SetFullRootLayerDamage() OVERRIDE;
- virtual CompositorFrameMetadata MakeCompositorFrameMetadata() const OVERRIDE;
// TileManagerClient implementation.
virtual void NotifyReadyToActivate() OVERRIDE;
@@ -218,17 +221,17 @@ class CC_EXPORT LayerTreeHostImpl
scoped_refptr<ContextProvider> offscreen_context_provider) OVERRIDE;
virtual void ReleaseGL() OVERRIDE;
virtual void SetNeedsRedrawRect(gfx::Rect rect) OVERRIDE;
- virtual void BeginFrame(const BeginFrameArgs& args) OVERRIDE;
+ virtual void BeginImplFrame(const BeginFrameArgs& args) OVERRIDE;
virtual void SetExternalDrawConstraints(
const gfx::Transform& transform,
gfx::Rect viewport,
gfx::Rect clip,
bool valid_for_tile_management) OVERRIDE;
virtual void DidLoseOutputSurface() OVERRIDE;
+ virtual void DidSwapBuffers() OVERRIDE;
virtual void OnSwapBuffersComplete() OVERRIDE;
virtual void ReclaimResources(const CompositorFrameAck* ack) OVERRIDE;
virtual void SetMemoryPolicy(const ManagedMemoryPolicy& policy) OVERRIDE;
- virtual void SetDiscardBackBufferWhenNotVisible(bool discard) OVERRIDE;
virtual void SetTreeActivationCallback(const base::Closure& callback)
OVERRIDE;
@@ -257,7 +260,7 @@ class CC_EXPORT LayerTreeHostImpl
const RendererCapabilities& GetRendererCapabilities() const;
virtual bool SwapBuffers(const FrameData& frame);
- void SetNeedsBeginFrame(bool enable);
+ void SetNeedsBeginImplFrame(bool enable);
void DidModifyTilePriorities();
void Readback(void* pixels, gfx::Rect rect_in_device_viewport);
@@ -276,11 +279,17 @@ class CC_EXPORT LayerTreeHostImpl
LayerImpl* RootScrollLayer() const;
LayerImpl* CurrentlyScrollingLayer() const;
+ int scroll_layer_id_when_mouse_over_scrollbar() {
+ return scroll_layer_id_when_mouse_over_scrollbar_;
+ }
+
+ bool IsCurrentlyScrolling() const;
+
virtual void SetVisible(bool visible);
bool visible() const { return visible_; }
void SetNeedsCommit() { client_->SetNeedsCommitOnImplThread(); }
- void SetNeedsRedraw() { client_->SetNeedsRedrawOnImplThread(); }
+ void SetNeedsRedraw();
ManagedMemoryPolicy ActualManagedMemoryPolicy() const;
@@ -343,26 +352,6 @@ class CC_EXPORT LayerTreeHostImpl
void SetDebugState(const LayerTreeDebugState& new_debug_state);
const LayerTreeDebugState& debug_state() const { return debug_state_; }
- class CC_EXPORT CullRenderPassesWithCachedTextures {
- public:
- bool ShouldRemoveRenderPass(const RenderPassDrawQuad& quad,
- const FrameData& frame) const;
-
- // Iterates from the root first, in order to remove the surfaces closest
- // to the root with cached textures, and all surfaces that draw into
- // them.
- size_t RenderPassListBegin(const RenderPassList& list) const {
- return list.size() - 1;
- }
- size_t RenderPassListEnd(const RenderPassList& list) const { return 0 - 1; }
- size_t RenderPassListNext(size_t it) const { return it - 1; }
-
- explicit CullRenderPassesWithCachedTextures(Renderer* renderer)
- : renderer_(renderer) {}
- private:
- Renderer* renderer_;
- };
-
class CC_EXPORT CullRenderPassesWithNoQuads {
public:
bool ShouldRemoveRenderPass(const RenderPassDrawQuad& quad,
@@ -413,12 +402,38 @@ class CC_EXPORT LayerTreeHostImpl
virtual ResourceProvider::ResourceId ResourceIdForUIResource(
UIResourceId uid) const;
+ virtual bool IsUIResourceOpaque(UIResourceId uid) const;
+
+ struct UIResourceData {
+ ResourceProvider::ResourceId resource_id;
+ gfx::Size size;
+ bool opaque;
+ };
+
+ void ScheduleMicroBenchmark(scoped_ptr<MicroBenchmarkImpl> benchmark);
+
+ CompositorFrameMetadata MakeCompositorFrameMetadata() const;
+ // Viewport rectangle and clip in nonflipped window space. These rects
+ // should only be used by Renderer subclasses to populate glViewport/glClip
+ // and their software-mode equivalents.
+ gfx::Rect DeviceViewport() const;
+ gfx::Rect DeviceClip() const;
+
+ // When a SwapPromiseMonitor is created on the impl thread, it calls
+ // InsertSwapPromiseMonitor() to register itself with LayerTreeHostImpl.
+ // When the monitor is destroyed, it calls RemoveSwapPromiseMonitor()
+ // to unregister itself.
+ void InsertSwapPromiseMonitor(SwapPromiseMonitor* monitor);
+ void RemoveSwapPromiseMonitor(SwapPromiseMonitor* monitor);
+
protected:
LayerTreeHostImpl(
const LayerTreeSettings& settings,
LayerTreeHostImplClient* client,
Proxy* proxy,
- RenderingStatsInstrumentation* rendering_stats_instrumentation);
+ RenderingStatsInstrumentation* rendering_stats_instrumentation,
+ SharedBitmapManager* manager,
+ int id);
// Virtual for testing.
virtual void AnimateLayers(base::TimeTicks monotonic_time,
@@ -474,11 +489,21 @@ class CC_EXPORT LayerTreeHostImpl
bool EnsureRenderSurfaceLayerList();
void ClearCurrentlyScrollingLayer();
+ bool HandleMouseOverScrollbar(LayerImpl* layer_impl,
+ gfx::PointF device_viewport_point);
+
void AnimateScrollbarsRecursive(LayerImpl* layer,
base::TimeTicks time);
void UpdateCurrentFrameTime(base::TimeTicks* ticks, base::Time* now) const;
+ LayerImpl* FindScrollLayerForDeviceViewportPoint(
+ gfx::PointF device_viewport_point,
+ InputHandler::ScrollInputType type,
+ LayerImpl* layer_hit_by_point,
+ bool* scroll_on_main_thread) const;
+ float DeviceSpaceDistanceToLayer(gfx::PointF device_viewport_point,
+ LayerImpl* layer_impl);
void StartScrollbarAnimationRecursive(LayerImpl* layer, base::TimeTicks time);
void SetManagedMemoryPolicy(const ManagedMemoryPolicy& policy,
bool zero_budget);
@@ -488,7 +513,9 @@ class CC_EXPORT LayerTreeHostImpl
void MarkUIResourceNotEvicted(UIResourceId uid);
- typedef base::hash_map<UIResourceId, ResourceProvider::ResourceId>
+ void NotifySwapPromiseMonitorsOfSetNeedsRedraw();
+
+ typedef base::hash_map<UIResourceId, UIResourceData>
UIResourceMap;
UIResourceMap ui_resource_map_;
@@ -506,6 +533,8 @@ class CC_EXPORT LayerTreeHostImpl
scoped_ptr<TileManager> tile_manager_;
scoped_ptr<Renderer> renderer_;
+ GlobalStateThatImpactsTilePriority global_tile_state_;
+
// Tree currently being drawn.
scoped_ptr<LayerTreeImpl> active_tree_;
@@ -520,7 +549,9 @@ class CC_EXPORT LayerTreeHostImpl
InputHandlerClient* input_handler_client_;
bool did_lock_scrolling_layer_;
bool should_bubble_scrolls_;
+ bool last_scroll_did_bubble_;
bool wheel_scrolling_;
+ int scroll_layer_id_when_mouse_over_scrollbar_;
bool tile_priorities_dirty_;
@@ -535,6 +566,7 @@ class CC_EXPORT LayerTreeHostImpl
gfx::Vector2dF current_fling_velocity_;
bool pinch_gesture_active_;
+ bool pinch_gesture_end_should_clear_scrolling_layer_;
gfx::Point previous_pinch_anchor_;
// This is set by AnimateLayers() and used by UpdateAnimationState()
@@ -606,12 +638,21 @@ class CC_EXPORT LayerTreeHostImpl
scoped_ptr<AnimationRegistrar> animation_registrar_;
RenderingStatsInstrumentation* rendering_stats_instrumentation_;
+ MicroBenchmarkControllerImpl micro_benchmark_controller_;
bool need_to_update_visible_tiles_before_draw_;
+#ifndef NDEBUG
+ bool did_lose_called_;
+#endif
// Optional callback to notify of new tree activations.
base::Closure tree_activation_callback_;
+ SharedBitmapManager* shared_bitmap_manager_;
+ int id_;
+
+ std::set<SwapPromiseMonitor*> swap_promise_monitor_;
+
DISALLOW_COPY_AND_ASSIGN(LayerTreeHostImpl);
};
diff --git a/chromium/cc/trees/layer_tree_host_impl_unittest.cc b/chromium/cc/trees/layer_tree_host_impl_unittest.cc
index 6bd815b9424..4630adc555d 100644
--- a/chromium/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/chromium/cc/trees/layer_tree_host_impl_unittest.cc
@@ -10,8 +10,9 @@
#include "base/command_line.h"
#include "base/containers/hash_tables.h"
#include "base/containers/scoped_ptr_hash_map.h"
+#include "cc/animation/scrollbar_animation_controller_thinning.h"
+#include "cc/base/latency_info_swap_promise.h"
#include "cc/base/math_util.h"
-#include "cc/debug/test_web_graphics_context_3d.h"
#include "cc/input/top_controls_manager.h"
#include "cc/layers/delegated_renderer_layer_impl.h"
#include "cc/layers/heads_up_display_layer_impl.h"
@@ -34,6 +35,7 @@
#include "cc/quads/solid_color_draw_quad.h"
#include "cc/quads/texture_draw_quad.h"
#include "cc/quads/tile_draw_quad.h"
+#include "cc/resources/etc1_pixel_ref.h"
#include "cc/resources/layer_tiling_data.h"
#include "cc/test/animation_test_common.h"
#include "cc/test/fake_layer_tree_host_impl.h"
@@ -47,11 +49,13 @@
#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/test_web_graphics_context_3d.h"
#include "cc/trees/layer_tree_impl.h"
#include "cc/trees/single_thread_proxy.h"
#include "media/base/media.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/frame_time.h"
#include "ui/gfx/rect_conversions.h"
#include "ui/gfx/size_conversions.h"
#include "ui/gfx/vector2d_conversions.h"
@@ -79,35 +83,30 @@ class LayerTreeHostImplTest : public testing::Test,
did_request_redraw_(false),
did_request_manage_tiles_(false),
did_upload_visible_tile_(false),
- did_lose_output_surface_(false),
reduce_memory_result_(true),
current_limit_bytes_(0),
current_priority_cutoff_value_(0) {
media::InitializeMediaLibraryForTesting();
}
- virtual void SetUp() OVERRIDE {
+ LayerTreeSettings DefaultSettings() {
LayerTreeSettings settings;
settings.minimum_occlusion_tracking_size = gfx::Size();
settings.impl_side_painting = true;
- settings.solid_color_scrollbars = true;
+ settings.texture_id_allocation_chunk_size = 1;
+ return settings;
+ }
- host_impl_ = LayerTreeHostImpl::Create(settings,
- this,
- &proxy_,
- &stats_instrumentation_);
- host_impl_->InitializeRenderer(CreateOutputSurface());
- host_impl_->SetViewportSize(gfx::Size(10, 10));
+ virtual void SetUp() OVERRIDE {
+ CreateHostImpl(DefaultSettings(), CreateOutputSurface());
}
virtual void TearDown() OVERRIDE {}
- virtual void DidLoseOutputSurfaceOnImplThread() OVERRIDE {
- did_lose_output_surface_ = true;
- }
+ virtual void DidLoseOutputSurfaceOnImplThread() OVERRIDE {}
+ virtual void DidSwapBuffersOnImplThread() OVERRIDE {}
virtual void OnSwapBuffersCompleteOnImplThread() OVERRIDE {}
- virtual void BeginFrameOnImplThread(const BeginFrameArgs& args)
- OVERRIDE {}
+ virtual void BeginImplFrame(const BeginFrameArgs& args) OVERRIDE {}
virtual void OnCanDrawStateChanged(bool can_draw) OVERRIDE {
on_can_draw_state_changed_called_ = true;
}
@@ -139,31 +138,25 @@ class LayerTreeHostImplTest : public testing::Test,
current_priority_cutoff_value_ = priority_cutoff;
return reduce_memory_result_;
}
- virtual void ReduceWastedContentsTextureMemoryOnImplThread() OVERRIDE {}
virtual void SendManagedMemoryStats() OVERRIDE {}
virtual bool IsInsideDraw() OVERRIDE { return false; }
virtual void RenewTreePriority() OVERRIDE {}
virtual void RequestScrollbarAnimationOnImplThread(base::TimeDelta delay)
OVERRIDE { requested_scrollbar_animation_delay_ = delay; }
virtual void DidActivatePendingTree() OVERRIDE {}
+ virtual void DidManageTiles() OVERRIDE {}
void set_reduce_memory_result(bool reduce_memory_result) {
reduce_memory_result_ = reduce_memory_result;
}
- void CreateLayerTreeHost(bool partial_swap,
- scoped_ptr<OutputSurface> output_surface) {
- LayerTreeSettings settings;
- settings.minimum_occlusion_tracking_size = gfx::Size();
- settings.partial_swap_enabled = partial_swap;
-
- host_impl_ = LayerTreeHostImpl::Create(settings,
- this,
- &proxy_,
- &stats_instrumentation_);
-
- host_impl_->InitializeRenderer(output_surface.Pass());
+ bool CreateHostImpl(const LayerTreeSettings& settings,
+ scoped_ptr<OutputSurface> output_surface) {
+ host_impl_ = LayerTreeHostImpl::Create(
+ settings, this, &proxy_, &stats_instrumentation_, NULL, 0);
+ bool init = host_impl_->InitializeRenderer(output_surface.Pass());
host_impl_->SetViewportSize(gfx::Size(10, 10));
+ return init;
}
void SetupRootLayerImpl(scoped_ptr<LayerImpl> root) {
@@ -194,7 +187,7 @@ class LayerTreeHostImplTest : public testing::Test,
times_encountered++;
}
- ASSERT_EQ(times_encountered, 1);
+ ASSERT_EQ(1, times_encountered);
}
static void ExpectNone(const ScrollAndScaleSet& scroll_info, int id) {
@@ -209,16 +202,17 @@ class LayerTreeHostImplTest : public testing::Test,
ASSERT_EQ(0, times_encountered);
}
- LayerImpl* SetupScrollAndContentsLayers(gfx::Size content_size) {
+ LayerImpl* CreateScrollAndContentsLayers(LayerTreeImpl* layer_tree_impl,
+ gfx::Size content_size) {
scoped_ptr<LayerImpl> root =
- LayerImpl::Create(host_impl_->active_tree(), 1);
+ LayerImpl::Create(layer_tree_impl, 1);
root->SetBounds(content_size);
root->SetContentBounds(content_size);
root->SetPosition(gfx::PointF());
root->SetAnchorPoint(gfx::PointF());
scoped_ptr<LayerImpl> scroll =
- LayerImpl::Create(host_impl_->active_tree(), 2);
+ LayerImpl::Create(layer_tree_impl, 2);
LayerImpl* scroll_layer = scroll.get();
scroll->SetScrollable(true);
scroll->SetScrollOffset(gfx::Vector2d());
@@ -230,7 +224,7 @@ class LayerTreeHostImplTest : public testing::Test,
scroll->SetAnchorPoint(gfx::PointF());
scoped_ptr<LayerImpl> contents =
- LayerImpl::Create(host_impl_->active_tree(), 3);
+ LayerImpl::Create(layer_tree_impl, 3);
contents->SetDrawsContent(true);
contents->SetBounds(content_size);
contents->SetContentBounds(content_size);
@@ -240,7 +234,13 @@ class LayerTreeHostImplTest : public testing::Test,
scroll->AddChild(contents.Pass());
root->AddChild(scroll.Pass());
- host_impl_->active_tree()->SetRootLayer(root.Pass());
+ layer_tree_impl->SetRootLayer(root.Pass());
+ return scroll_layer;
+ }
+
+ LayerImpl* SetupScrollAndContentsLayers(gfx::Size content_size) {
+ LayerImpl* scroll_layer = CreateScrollAndContentsLayers(
+ host_impl_->active_tree(), content_size);
host_impl_->active_tree()->DidBecomeActive();
return scroll_layer;
}
@@ -257,15 +257,10 @@ class LayerTreeHostImplTest : public testing::Test,
return layer.Pass();
}
- void InitializeRendererAndDrawFrame() {
- host_impl_->InitializeRenderer(CreateOutputSurface());
- DrawFrame();
- }
-
void DrawFrame() {
LayerTreeHostImpl::FrameData frame;
EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
@@ -319,7 +314,6 @@ class LayerTreeHostImplTest : public testing::Test,
set_reduce_memory_result(false);
host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
host_impl_->memory_allocation_limit_bytes() - 1));
- host_impl_->SetDiscardBackBufferWhenNotVisible(true);
EXPECT_TRUE(host_impl_->CanDraw());
EXPECT_FALSE(on_can_draw_state_changed_called_);
on_can_draw_state_changed_called_ = false;
@@ -328,7 +322,6 @@ class LayerTreeHostImplTest : public testing::Test,
set_reduce_memory_result(true);
host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
host_impl_->memory_allocation_limit_bytes() - 1));
- host_impl_->SetDiscardBackBufferWhenNotVisible(true);
if (always_draw) {
EXPECT_TRUE(host_impl_->CanDraw());
} else {
@@ -343,6 +336,8 @@ class LayerTreeHostImplTest : public testing::Test,
on_can_draw_state_changed_called_ = false;
}
+ void SetupMouseMoveAtWithDeviceScale(float device_scale_factor);
+
protected:
virtual scoped_ptr<OutputSurface> CreateOutputSurface() {
return CreateFakeOutputSurface();
@@ -366,7 +361,6 @@ class LayerTreeHostImplTest : public testing::Test,
bool did_request_redraw_;
bool did_request_manage_tiles_;
bool did_upload_visible_tile_;
- bool did_lose_output_surface_;
bool reduce_memory_result_;
base::TimeDelta requested_scrollbar_animation_delay_;
size_t current_limit_bytes_;
@@ -379,17 +373,9 @@ TEST_F(LayerTreeHostImplTest, NotifyIfCanDrawChanged) {
}
TEST_F(LayerTreeHostImplTest, CanDrawIncompleteFrames) {
- LayerTreeSettings settings;
- settings.impl_side_painting = true;
- host_impl_ = LayerTreeHostImpl::Create(
- settings, this, &proxy_, &stats_instrumentation_);
-
scoped_ptr<FakeOutputSurface> output_surface(
FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
-
- host_impl_->InitializeRenderer(
- output_surface.PassAs<OutputSurface>());
- host_impl_->SetViewportSize(gfx::Size(10, 10));
+ CreateHostImpl(DefaultSettings(), output_surface.PassAs<OutputSurface>());
bool always_draw = true;
CheckNotifyCalledIfCanDrawChanged(always_draw);
@@ -467,7 +453,7 @@ TEST_F(LayerTreeHostImplTest, ScrollDeltaRepeatedScrolls) {
TEST_F(LayerTreeHostImplTest, ScrollRootCallsCommitAndRedraw) {
SetupScrollAndContentsLayers(gfx::Size(100, 100));
host_impl_->SetViewportSize(gfx::Size(50, 50));
- InitializeRendererAndDrawFrame();
+ DrawFrame();
EXPECT_EQ(InputHandler::ScrollStarted,
host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
@@ -484,21 +470,16 @@ TEST_F(LayerTreeHostImplTest, ScrollWithoutRootLayer) {
}
TEST_F(LayerTreeHostImplTest, ScrollWithoutRenderer) {
- LayerTreeSettings settings;
- host_impl_ = LayerTreeHostImpl::Create(settings,
- this,
- &proxy_,
- &stats_instrumentation_);
scoped_ptr<TestWebGraphicsContext3D> context_owned =
TestWebGraphicsContext3D::Create();
- context_owned->set_times_make_current_succeeds(0);
+ context_owned->set_context_lost(true);
scoped_ptr<FakeOutputSurface> output_surface(FakeOutputSurface::Create3d(
context_owned.Pass()));
- // Initialization will fail here.
- host_impl_->InitializeRenderer(output_surface.PassAs<OutputSurface>());
- host_impl_->SetViewportSize(gfx::Size(10, 10));
+ // Initialization will fail.
+ EXPECT_FALSE(CreateHostImpl(DefaultSettings(),
+ output_surface.PassAs<OutputSurface>()));
SetupScrollAndContentsLayers(gfx::Size(100, 100));
@@ -511,7 +492,7 @@ TEST_F(LayerTreeHostImplTest, ScrollWithoutRenderer) {
TEST_F(LayerTreeHostImplTest, ReplaceTreeWhileScrolling) {
LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
host_impl_->SetViewportSize(gfx::Size(50, 50));
- InitializeRendererAndDrawFrame();
+ DrawFrame();
// We should not crash if the tree is replaced while we are scrolling.
EXPECT_EQ(InputHandler::ScrollStarted,
@@ -532,7 +513,7 @@ TEST_F(LayerTreeHostImplTest, ReplaceTreeWhileScrolling) {
TEST_F(LayerTreeHostImplTest, ClearRootRenderSurfaceAndScroll) {
SetupScrollAndContentsLayers(gfx::Size(100, 100));
host_impl_->SetViewportSize(gfx::Size(50, 50));
- InitializeRendererAndDrawFrame();
+ DrawFrame();
// We should be able to scroll even if the root layer loses its render surface
// after the most recent render.
@@ -546,7 +527,7 @@ TEST_F(LayerTreeHostImplTest, ClearRootRenderSurfaceAndScroll) {
TEST_F(LayerTreeHostImplTest, WheelEventHandlers) {
SetupScrollAndContentsLayers(gfx::Size(100, 100));
host_impl_->SetViewportSize(gfx::Size(50, 50));
- InitializeRendererAndDrawFrame();
+ DrawFrame();
LayerImpl* root = host_impl_->active_tree()->root_layer();
root->SetHaveWheelEventHandlers(true);
@@ -564,7 +545,7 @@ TEST_F(LayerTreeHostImplTest, WheelEventHandlers) {
TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchscreen) {
SetupScrollAndContentsLayers(gfx::Size(100, 100));
host_impl_->SetViewportSize(gfx::Size(50, 50));
- InitializeRendererAndDrawFrame();
+ DrawFrame();
// Ignore the fling since no layer is being scrolled
EXPECT_EQ(InputHandler::ScrollIgnored,
@@ -582,7 +563,7 @@ TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchscreen) {
TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchpad) {
SetupScrollAndContentsLayers(gfx::Size(100, 100));
host_impl_->SetViewportSize(gfx::Size(50, 50));
- InitializeRendererAndDrawFrame();
+ DrawFrame();
// Ignore the fling since no layer is being scrolled
EXPECT_EQ(InputHandler::ScrollIgnored,
@@ -600,7 +581,7 @@ TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchpad) {
TEST_F(LayerTreeHostImplTest, NoFlingWhenScrollingOnMain) {
SetupScrollAndContentsLayers(gfx::Size(100, 100));
host_impl_->SetViewportSize(gfx::Size(50, 50));
- InitializeRendererAndDrawFrame();
+ DrawFrame();
LayerImpl* root = host_impl_->active_tree()->root_layer();
root->SetShouldScrollOnMainThread(true);
@@ -617,7 +598,7 @@ TEST_F(LayerTreeHostImplTest, NoFlingWhenScrollingOnMain) {
TEST_F(LayerTreeHostImplTest, ShouldScrollOnMainThread) {
SetupScrollAndContentsLayers(gfx::Size(100, 100));
host_impl_->SetViewportSize(gfx::Size(50, 50));
- InitializeRendererAndDrawFrame();
+ DrawFrame();
LayerImpl* root = host_impl_->active_tree()->root_layer();
root->SetShouldScrollOnMainThread(true);
@@ -636,7 +617,7 @@ TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionBasic) {
root->SetContentsScale(2.f, 2.f);
root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
- InitializeRendererAndDrawFrame();
+ DrawFrame();
// All scroll types inside the non-fast scrollable region should fail.
EXPECT_EQ(InputHandler::ScrollOnMainThread,
@@ -668,7 +649,7 @@ TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionWithOffset) {
root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
root->SetPosition(gfx::PointF(-25.f, 0.f));
- InitializeRendererAndDrawFrame();
+ DrawFrame();
// This point would fall into the non-fast scrollable region except that we've
// moved the layer down by 25 pixels.
@@ -688,7 +669,7 @@ TEST_F(LayerTreeHostImplTest, ScrollByReturnsCorrectValue) {
SetupScrollAndContentsLayers(gfx::Size(200, 200));
host_impl_->SetViewportSize(gfx::Size(100, 100));
- InitializeRendererAndDrawFrame();
+ DrawFrame();
EXPECT_EQ(InputHandler::ScrollStarted,
host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
@@ -721,7 +702,7 @@ TEST_F(LayerTreeHostImplTest, ScrollVerticallyByPageReturnsCorrectValue) {
SetupScrollAndContentsLayers(gfx::Size(200, 2000));
host_impl_->SetViewportSize(gfx::Size(100, 1000));
- InitializeRendererAndDrawFrame();
+ DrawFrame();
EXPECT_EQ(InputHandler::ScrollStarted,
host_impl_->ScrollBegin(gfx::Point(),
@@ -750,11 +731,68 @@ TEST_F(LayerTreeHostImplTest, ScrollVerticallyByPageReturnsCorrectValue) {
gfx::Point(), SCROLL_BACKWARD));
}
+// The user-scrollability breaks for zoomed-in pages. So disable this.
+// http://crbug.com/322223
+TEST_F(LayerTreeHostImplTest, DISABLED_ScrollWithUserUnscrollableLayers) {
+ LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
+ host_impl_->SetViewportSize(gfx::Size(100, 100));
+
+ gfx::Size overflow_size(400, 400);
+ ASSERT_EQ(1u, scroll_layer->children().size());
+ LayerImpl* overflow = scroll_layer->children()[0];
+ overflow->SetBounds(overflow_size);
+ overflow->SetContentBounds(overflow_size);
+ overflow->SetScrollable(true);
+ overflow->SetMaxScrollOffset(gfx::Vector2d(overflow_size.width(),
+ overflow_size.height()));
+ overflow->SetScrollOffset(gfx::Vector2d());
+ overflow->SetPosition(gfx::PointF());
+ overflow->SetAnchorPoint(gfx::PointF());
+
+ DrawFrame();
+ gfx::Point scroll_position(10, 10);
+
+ EXPECT_EQ(InputHandler::ScrollStarted,
+ host_impl_->ScrollBegin(scroll_position, InputHandler::Wheel));
+ EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->TotalScrollOffset());
+ EXPECT_VECTOR_EQ(gfx::Vector2dF(), overflow->TotalScrollOffset());
+
+ gfx::Vector2dF scroll_delta(10, 10);
+ host_impl_->ScrollBy(scroll_position, scroll_delta);
+ host_impl_->ScrollEnd();
+ EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->TotalScrollOffset());
+ EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->TotalScrollOffset());
+
+ overflow->set_user_scrollable_horizontal(false);
+
+ EXPECT_EQ(InputHandler::ScrollStarted,
+ host_impl_->ScrollBegin(scroll_position, InputHandler::Wheel));
+ EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->TotalScrollOffset());
+ EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->TotalScrollOffset());
+
+ host_impl_->ScrollBy(scroll_position, scroll_delta);
+ host_impl_->ScrollEnd();
+ EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer->TotalScrollOffset());
+ EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->TotalScrollOffset());
+
+ overflow->set_user_scrollable_vertical(false);
+
+ EXPECT_EQ(InputHandler::ScrollStarted,
+ host_impl_->ScrollBegin(scroll_position, InputHandler::Wheel));
+ EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer->TotalScrollOffset());
+ EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->TotalScrollOffset());
+
+ host_impl_->ScrollBy(scroll_position, scroll_delta);
+ host_impl_->ScrollEnd();
+ EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 10), scroll_layer->TotalScrollOffset());
+ EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->TotalScrollOffset());
+}
+
TEST_F(LayerTreeHostImplTest,
ClearRootRenderSurfaceAndHitTestTouchHandlerRegion) {
SetupScrollAndContentsLayers(gfx::Size(100, 100));
host_impl_->SetViewportSize(gfx::Size(50, 50));
- InitializeRendererAndDrawFrame();
+ DrawFrame();
// We should be able to hit test for touch event handlers even if the root
// layer loses its render surface after the most recent render.
@@ -767,7 +805,7 @@ TEST_F(LayerTreeHostImplTest,
TEST_F(LayerTreeHostImplTest, ImplPinchZoom) {
LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
host_impl_->SetViewportSize(gfx::Size(50, 50));
- InitializeRendererAndDrawFrame();
+ DrawFrame();
EXPECT_EQ(scroll_layer, host_impl_->RootScrollLayer());
@@ -831,7 +869,7 @@ TEST_F(LayerTreeHostImplTest, ImplPinchZoom) {
TEST_F(LayerTreeHostImplTest, PinchGesture) {
SetupScrollAndContentsLayers(gfx::Size(100, 100));
host_impl_->SetViewportSize(gfx::Size(50, 50));
- InitializeRendererAndDrawFrame();
+ DrawFrame();
LayerImpl* scroll_layer = host_impl_->RootScrollLayer();
DCHECK(scroll_layer);
@@ -974,7 +1012,7 @@ TEST_F(LayerTreeHostImplTest, PinchGesture) {
TEST_F(LayerTreeHostImplTest, PageScaleAnimation) {
SetupScrollAndContentsLayers(gfx::Size(100, 100));
host_impl_->SetViewportSize(gfx::Size(50, 50));
- InitializeRendererAndDrawFrame();
+ DrawFrame();
LayerImpl* scroll_layer = host_impl_->RootScrollLayer();
DCHECK(scroll_layer);
@@ -1044,7 +1082,7 @@ TEST_F(LayerTreeHostImplTest, PageScaleAnimation) {
TEST_F(LayerTreeHostImplTest, PageScaleAnimationNoOp) {
SetupScrollAndContentsLayers(gfx::Size(100, 100));
host_impl_->SetViewportSize(gfx::Size(50, 50));
- InitializeRendererAndDrawFrame();
+ DrawFrame();
LayerImpl* scroll_layer = host_impl_->RootScrollLayer();
DCHECK(scroll_layer);
@@ -1088,8 +1126,9 @@ class LayerTreeHostImplOverridePhysicalTime : public LayerTreeHostImpl {
: LayerTreeHostImpl(settings,
client,
proxy,
- rendering_stats_instrumentation) {}
-
+ rendering_stats_instrumentation,
+ NULL,
+ 0) {}
virtual base::TimeTicks CurrentPhysicalTimeTicks() const OVERRIDE {
return fake_current_physical_time_;
@@ -1103,7 +1142,7 @@ class LayerTreeHostImplOverridePhysicalTime : public LayerTreeHostImpl {
base::TimeTicks fake_current_physical_time_;
};
-TEST_F(LayerTreeHostImplTest, DISABLED_ScrollbarLinearFadeScheduling) {
+TEST_F(LayerTreeHostImplTest, ScrollbarLinearFadeScheduling) {
LayerTreeSettings settings;
settings.scrollbar_animator = LayerTreeSettings::LinearFade;
settings.scrollbar_linear_fade_delay_ms = 20;
@@ -1115,7 +1154,7 @@ TEST_F(LayerTreeHostImplTest, DISABLED_ScrollbarLinearFadeScheduling) {
LayerTreeHostImplOverridePhysicalTime* host_impl_override_time =
new LayerTreeHostImplOverridePhysicalTime(
settings, this, &proxy_, &stats_instrumentation_);
- host_impl_ = make_scoped_ptr<LayerTreeHostImpl>(host_impl_override_time);
+ host_impl_ = make_scoped_ptr(host_impl_override_time);
host_impl_->InitializeRenderer(CreateOutputSurface());
host_impl_->SetViewportSize(viewport_size);
@@ -1148,9 +1187,9 @@ TEST_F(LayerTreeHostImplTest, DISABLED_ScrollbarLinearFadeScheduling) {
host_impl_->active_tree()->SetRootLayer(root.Pass());
host_impl_->active_tree()->DidBecomeActive();
- InitializeRendererAndDrawFrame();
+ DrawFrame();
- base::TimeTicks fake_now = base::TimeTicks::Now();
+ base::TimeTicks fake_now = gfx::FrameTime::Now();
host_impl_override_time->SetCurrentPhysicalTimeTicksForTest(fake_now);
// If no scroll happened recently, StartScrollbarAnimation should have no
@@ -1211,11 +1250,99 @@ TEST_F(LayerTreeHostImplTest, DISABLED_ScrollbarLinearFadeScheduling) {
EXPECT_EQ(fake_now, host_impl_->CurrentFrameTimeTicks());
}
+void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale(
+ float device_scale_factor) {
+ LayerTreeSettings settings;
+ 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 content_size(1000, 1000);
+
+ CreateHostImpl(settings, CreateOutputSurface());
+ host_impl_->SetDeviceScaleFactor(device_scale_factor);
+ host_impl_->SetViewportSize(device_viewport_size);
+
+ scoped_ptr<LayerImpl> root =
+ LayerImpl::Create(host_impl_->active_tree(), 1);
+ root->SetBounds(viewport_size);
+
+ scoped_ptr<LayerImpl> scroll =
+ LayerImpl::Create(host_impl_->active_tree(), 2);
+ scroll->SetScrollable(true);
+ scroll->SetScrollOffset(gfx::Vector2d());
+ scroll->SetMaxScrollOffset(gfx::Vector2d(content_size.width(),
+ content_size.height()));
+ scroll->SetBounds(content_size);
+ scroll->SetContentBounds(content_size);
+
+ scoped_ptr<LayerImpl> contents =
+ LayerImpl::Create(host_impl_->active_tree(), 3);
+ contents->SetDrawsContent(true);
+ contents->SetBounds(content_size);
+ contents->SetContentBounds(content_size);
+
+ // The scrollbar is on the right side.
+ scoped_ptr<PaintedScrollbarLayerImpl> scrollbar =
+ PaintedScrollbarLayerImpl::Create(host_impl_->active_tree(), 5, VERTICAL);
+ scrollbar->SetDrawsContent(true);
+ scrollbar->SetBounds(gfx::Size(15, viewport_size.height()));
+ scrollbar->SetContentBounds(gfx::Size(15, viewport_size.height()));
+ scrollbar->SetPosition(gfx::Point(285, 0));
+ scroll->SetVerticalScrollbarLayer(scrollbar.get());
+
+ scroll->AddChild(contents.Pass());
+ root->AddChild(scroll.Pass());
+ root->AddChild(scrollbar.PassAs<LayerImpl>());
+
+ host_impl_->active_tree()->SetRootLayer(root.Pass());
+ host_impl_->active_tree()->DidBecomeActive();
+ DrawFrame();
+
+ LayerImpl* root_scroll = host_impl_->active_tree()->RootScrollLayer();
+ ASSERT_TRUE(root_scroll->scrollbar_animation_controller());
+ ScrollbarAnimationControllerThinning* scrollbar_animation_controller =
+ static_cast<ScrollbarAnimationControllerThinning*>(
+ root_scroll->scrollbar_animation_controller());
+ scrollbar_animation_controller->set_mouse_move_distance_for_test(100.f);
+
+ host_impl_->MouseMoveAt(gfx::Point(1, 1));
+ EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar());
+
+ host_impl_->MouseMoveAt(gfx::Point(200, 50));
+ EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar());
+
+ host_impl_->MouseMoveAt(gfx::Point(184, 100));
+ EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar());
+
+ scrollbar_animation_controller->set_mouse_move_distance_for_test(102.f);
+ host_impl_->MouseMoveAt(gfx::Point(184, 100));
+ EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar());
+
+ did_request_redraw_ = false;
+ EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
+ host_impl_->MouseMoveAt(gfx::Point(290, 100));
+ EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
+ host_impl_->MouseMoveAt(gfx::Point(290, 120));
+ EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
+ host_impl_->MouseMoveAt(gfx::Point(150, 120));
+ EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
+}
+
+TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf1) {
+ SetupMouseMoveAtWithDeviceScale(1.f);
+}
+
+TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf2) {
+ SetupMouseMoveAtWithDeviceScale(2.f);
+}
+
TEST_F(LayerTreeHostImplTest, CompositorFrameMetadata) {
SetupScrollAndContentsLayers(gfx::Size(100, 100));
host_impl_->SetViewportSize(gfx::Size(50, 50));
host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
- InitializeRendererAndDrawFrame();
+ DrawFrame();
{
CompositorFrameMetadata metadata =
host_impl_->MakeCompositorFrameMetadata();
@@ -1356,7 +1483,7 @@ TEST_F(LayerTreeHostImplTest, WillDrawReturningFalseDoesNotCall) {
{
LayerTreeHostImpl::FrameData frame;
EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect(10, 10)));
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
EXPECT_TRUE(layer->will_draw_called());
@@ -1371,7 +1498,7 @@ TEST_F(LayerTreeHostImplTest, WillDrawReturningFalseDoesNotCall) {
layer->ClearDidDrawCheck();
EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect(10, 10)));
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
EXPECT_TRUE(layer->will_draw_called());
@@ -1403,7 +1530,7 @@ TEST_F(LayerTreeHostImplTest, DidDrawNotCalledOnHiddenLayer) {
EXPECT_FALSE(layer->did_draw_called());
EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
EXPECT_FALSE(layer->will_draw_called());
@@ -1418,7 +1545,7 @@ TEST_F(LayerTreeHostImplTest, DidDrawNotCalledOnHiddenLayer) {
EXPECT_FALSE(layer->did_draw_called());
EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
EXPECT_TRUE(layer->will_draw_called());
@@ -1457,7 +1584,7 @@ TEST_F(LayerTreeHostImplTest, WillDrawNotCalledOnOccludedLayer) {
EXPECT_FALSE(top_layer->did_draw_called());
EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
EXPECT_FALSE(occluded_layer->will_draw_called());
@@ -1489,7 +1616,7 @@ TEST_F(LayerTreeHostImplTest, DidDrawCalledOnAllLayers) {
LayerTreeHostImpl::FrameData frame;
EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
EXPECT_TRUE(root->did_draw_called());
@@ -1562,7 +1689,7 @@ TEST_F(LayerTreeHostImplTest, PrepareToDrawFailsWhenAnimationUsesCheckerboard) {
LayerTreeHostImpl::FrameData frame;
EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
// When a texture is missing and we're not animating, we draw as usual with
@@ -1580,7 +1707,7 @@ TEST_F(LayerTreeHostImplTest, PrepareToDrawFailsWhenAnimationUsesCheckerboard) {
host_impl_->resource_provider()));
EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
// When a texture is missing and we're animating, we don't want to draw
@@ -1598,7 +1725,7 @@ TEST_F(LayerTreeHostImplTest, PrepareToDrawFailsWhenAnimationUsesCheckerboard) {
host_impl_->resource_provider()));
EXPECT_FALSE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
// When the layer skips draw and we're animating, we still draw the frame.
@@ -1615,7 +1742,7 @@ TEST_F(LayerTreeHostImplTest, PrepareToDrawFailsWhenAnimationUsesCheckerboard) {
host_impl_->resource_provider()));
EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
@@ -1623,7 +1750,7 @@ TEST_F(LayerTreeHostImplTest, ScrollRootIgnored) {
scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
root->SetScrollable(false);
host_impl_->active_tree()->SetRootLayer(root.Pass());
- InitializeRendererAndDrawFrame();
+ DrawFrame();
// Scroll event is ignored because layer is not scrollable.
EXPECT_EQ(InputHandler::ScrollIgnored,
@@ -1637,12 +1764,7 @@ TEST_F(LayerTreeHostImplTest, ScrollNonScrollableRootWithTopControls) {
settings.calculate_top_controls_position = true;
settings.top_controls_height = 50;
- host_impl_ = LayerTreeHostImpl::Create(settings,
- this,
- &proxy_,
- &stats_instrumentation_);
- host_impl_->InitializeRenderer(CreateOutputSurface());
- host_impl_->SetViewportSize(gfx::Size(10, 10));
+ CreateHostImpl(settings, CreateOutputSurface());
gfx::Size layer_size(5, 5);
scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
@@ -1656,7 +1778,7 @@ TEST_F(LayerTreeHostImplTest, ScrollNonScrollableRootWithTopControls) {
root->SetDrawsContent(false);
host_impl_->active_tree()->SetRootLayer(root.Pass());
host_impl_->active_tree()->FindRootScrollLayer();
- InitializeRendererAndDrawFrame();
+ DrawFrame();
EXPECT_EQ(InputHandler::ScrollIgnored,
host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
@@ -1699,7 +1821,7 @@ TEST_F(LayerTreeHostImplTest, ScrollNonCompositedRoot) {
host_impl_->active_tree()->SetRootLayer(scroll_layer.Pass());
host_impl_->SetViewportSize(surface_size);
- InitializeRendererAndDrawFrame();
+ DrawFrame();
EXPECT_EQ(InputHandler::ScrollStarted,
host_impl_->ScrollBegin(gfx::Point(5, 5),
@@ -1718,7 +1840,7 @@ TEST_F(LayerTreeHostImplTest, ScrollChildCallsCommitAndRedraw) {
root->AddChild(CreateScrollableLayer(2, surface_size));
host_impl_->active_tree()->SetRootLayer(root.Pass());
host_impl_->SetViewportSize(surface_size);
- InitializeRendererAndDrawFrame();
+ DrawFrame();
EXPECT_EQ(InputHandler::ScrollStarted,
host_impl_->ScrollBegin(gfx::Point(5, 5),
@@ -1735,7 +1857,7 @@ TEST_F(LayerTreeHostImplTest, ScrollMissesChild) {
root->AddChild(CreateScrollableLayer(2, surface_size));
host_impl_->active_tree()->SetRootLayer(root.Pass());
host_impl_->SetViewportSize(surface_size);
- InitializeRendererAndDrawFrame();
+ DrawFrame();
// Scroll event is ignored because the input coordinate is outside the layer
// boundaries.
@@ -1759,7 +1881,7 @@ TEST_F(LayerTreeHostImplTest, ScrollMissesBackfacingChild) {
root->AddChild(child.Pass());
host_impl_->active_tree()->SetRootLayer(root.Pass());
- InitializeRendererAndDrawFrame();
+ DrawFrame();
// Scroll event is ignored because the scrollable layer is not facing the
// viewer and there is nothing scrollable behind it.
@@ -1781,7 +1903,7 @@ TEST_F(LayerTreeHostImplTest, ScrollBlockedByContentLayer) {
host_impl_->active_tree()->SetRootLayer(scroll_layer.Pass());
host_impl_->SetViewportSize(surface_size);
- InitializeRendererAndDrawFrame();
+ DrawFrame();
// Scrolling fails because the content layer is asking to be scrolled on the
// main thread.
@@ -1799,7 +1921,7 @@ TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnMainThread) {
host_impl_->active_tree()->SetRootLayer(root.Pass());
host_impl_->active_tree()->DidBecomeActive();
host_impl_->SetViewportSize(surface_size);
- InitializeRendererAndDrawFrame();
+ DrawFrame();
LayerImpl* root_scroll = host_impl_->active_tree()->RootScrollLayer();
@@ -1838,7 +1960,7 @@ TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnImplThread) {
host_impl_->active_tree()->DidBecomeActive();
host_impl_->SetViewportSize(surface_size);
host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 1.f, page_scale);
- InitializeRendererAndDrawFrame();
+ DrawFrame();
LayerImpl* root_scroll = host_impl_->active_tree()->RootScrollLayer();
@@ -1911,7 +2033,7 @@ TEST_F(LayerTreeHostImplTest, PageScaleDeltaAppliedToRootScrollLayerOnly) {
// the page scale delta on the root layer is applied hierarchically.
LayerTreeHostImpl::FrameData frame;
EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(0, 0));
@@ -1943,7 +2065,7 @@ TEST_F(LayerTreeHostImplTest, ScrollChildAndChangePageScaleOnMainThread) {
host_impl_->active_tree()->SetRootLayer(root.Pass());
host_impl_->active_tree()->DidBecomeActive();
host_impl_->SetViewportSize(surface_size);
- InitializeRendererAndDrawFrame();
+ DrawFrame();
gfx::Vector2d scroll_delta(0, 10);
gfx::Vector2d expected_scroll_delta(scroll_delta);
@@ -1991,7 +2113,7 @@ TEST_F(LayerTreeHostImplTest, ScrollChildBeyondLimit) {
host_impl_->active_tree()->SetRootLayer(root.Pass());
host_impl_->active_tree()->DidBecomeActive();
host_impl_->SetViewportSize(surface_size);
- InitializeRendererAndDrawFrame();
+ DrawFrame();
{
gfx::Vector2d scroll_delta(-8, -7);
EXPECT_EQ(InputHandler::ScrollStarted,
@@ -2032,7 +2154,7 @@ TEST_F(LayerTreeHostImplTest, ScrollWithoutBubbling) {
host_impl_->active_tree()->SetRootLayer(root.Pass());
host_impl_->active_tree()->DidBecomeActive();
host_impl_->SetViewportSize(surface_size);
- InitializeRendererAndDrawFrame();
+ DrawFrame();
{
gfx::Vector2d scroll_delta(0, -10);
EXPECT_EQ(InputHandler::ScrollStarted,
@@ -2124,7 +2246,7 @@ TEST_F(LayerTreeHostImplTest, ScrollEventBubbling) {
host_impl_->SetViewportSize(surface_size);
host_impl_->active_tree()->SetRootLayer(root.Pass());
host_impl_->active_tree()->DidBecomeActive();
- InitializeRendererAndDrawFrame();
+ DrawFrame();
{
gfx::Vector2d scroll_delta(0, 4);
EXPECT_EQ(InputHandler::ScrollStarted,
@@ -2153,7 +2275,7 @@ TEST_F(LayerTreeHostImplTest, ScrollBeforeRedraw) {
// Draw one frame and then immediately rebuild the layer tree to mimic a tree
// synchronization.
- InitializeRendererAndDrawFrame();
+ DrawFrame();
host_impl_->active_tree()->DetachLayerTree();
host_impl_->active_tree()->SetRootLayer(
CreateScrollableLayer(2, surface_size));
@@ -2175,7 +2297,7 @@ TEST_F(LayerTreeHostImplTest, ScrollAxisAlignedRotatedLayer) {
gfx::Size surface_size(50, 50);
host_impl_->SetViewportSize(surface_size);
- InitializeRendererAndDrawFrame();
+ DrawFrame();
// Scroll to the right in screen coordinates with a gesture.
gfx::Vector2d gesture_scroll_delta(10, 0);
@@ -2228,7 +2350,7 @@ TEST_F(LayerTreeHostImplTest, ScrollNonAxisAlignedRotatedLayer) {
gfx::Size surface_size(50, 50);
host_impl_->SetViewportSize(surface_size);
- InitializeRendererAndDrawFrame();
+ DrawFrame();
{
// Scroll down in screen coordinates with a gesture.
gfx::Vector2d gesture_scroll_delta(0, 10);
@@ -2297,7 +2419,7 @@ TEST_F(LayerTreeHostImplTest, ScrollScaledLayer) {
gfx::Size surface_size(50, 50);
host_impl_->SetViewportSize(surface_size);
- InitializeRendererAndDrawFrame();
+ DrawFrame();
// Scroll down in screen coordinates with a gesture.
gfx::Vector2d scroll_delta(0, 10);
@@ -2330,9 +2452,14 @@ TEST_F(LayerTreeHostImplTest, ScrollScaledLayer) {
class TestScrollOffsetDelegate : public LayerScrollOffsetDelegate {
public:
- TestScrollOffsetDelegate() {}
+ TestScrollOffsetDelegate() : page_scale_factor_(0.f) {}
+
virtual ~TestScrollOffsetDelegate() {}
+ virtual void SetMaxScrollOffset(gfx::Vector2dF max_scroll_offset) OVERRIDE {
+ max_scroll_offset_ = max_scroll_offset;
+ }
+
virtual void SetTotalScrollOffset(gfx::Vector2dF new_value) OVERRIDE {
last_set_scroll_offset_ = new_value;
}
@@ -2341,6 +2468,16 @@ class TestScrollOffsetDelegate : public LayerScrollOffsetDelegate {
return getter_return_value_;
}
+ virtual bool IsExternalFlingActive() const OVERRIDE { return false; }
+
+ virtual void SetTotalPageScaleFactor(float page_scale_factor) OVERRIDE {
+ page_scale_factor_ = page_scale_factor;
+ }
+
+ virtual void SetScrollableSize(gfx::SizeF scrollable_size) OVERRIDE {
+ scrollable_size_ = scrollable_size;
+ }
+
gfx::Vector2dF last_set_scroll_offset() {
return last_set_scroll_offset_;
}
@@ -2349,13 +2486,29 @@ class TestScrollOffsetDelegate : public LayerScrollOffsetDelegate {
getter_return_value_ = value;
}
+ gfx::Vector2dF max_scroll_offset() const {
+ return max_scroll_offset_;
+ }
+
+ gfx::SizeF scrollable_size() const {
+ return scrollable_size_;
+ }
+
+ float page_scale_factor() const {
+ return page_scale_factor_;
+ }
+
private:
gfx::Vector2dF last_set_scroll_offset_;
gfx::Vector2dF getter_return_value_;
+ gfx::Vector2dF max_scroll_offset_;
+ gfx::SizeF scrollable_size_;
+ float page_scale_factor_;
};
TEST_F(LayerTreeHostImplTest, RootLayerScrollOffsetDelegation) {
TestScrollOffsetDelegate scroll_delegate;
+ host_impl_->SetViewportSize(gfx::Size(10, 20));
LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
// Setting the delegate results in the current scroll offset being set.
@@ -2366,6 +2519,21 @@ TEST_F(LayerTreeHostImplTest, RootLayerScrollOffsetDelegation) {
EXPECT_EQ(initial_scroll_delta.ToString(),
scroll_delegate.last_set_scroll_offset().ToString());
+ // Setting the delegate results in the scrollable_size, max_scroll_offset and
+ // page_scale being set.
+ EXPECT_EQ(gfx::SizeF(100, 100), scroll_delegate.scrollable_size());
+ EXPECT_EQ(gfx::Vector2dF(90, 80), scroll_delegate.max_scroll_offset());
+ EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
+
+ // Updating page scale immediately updates the delegate.
+ host_impl_->active_tree()->SetPageScaleFactorAndLimits(2.f, 0.5f, 4.f);
+ EXPECT_EQ(2.f, scroll_delegate.page_scale_factor());
+ host_impl_->active_tree()->SetPageScaleDelta(1.5f);
+ EXPECT_EQ(3.f, scroll_delegate.page_scale_factor());
+ host_impl_->active_tree()->SetPageScaleDelta(1.f);
+ host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
+ EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
+
// Scrolling should be relative to the offset as returned by the delegate.
gfx::Vector2dF scroll_delta(0.f, 10.f);
gfx::Vector2dF current_offset(7.f, 8.f);
@@ -2385,6 +2553,14 @@ TEST_F(LayerTreeHostImplTest, RootLayerScrollOffsetDelegation) {
scroll_delegate.last_set_scroll_offset());
host_impl_->ScrollEnd();
+ // 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();
+ CreateScrollAndContentsLayers(host_impl_->pending_tree(), new_size);
+ host_impl_->ActivatePendingTree();
+ EXPECT_EQ(new_size, scroll_delegate.scrollable_size());
+
// Un-setting the delegate should propagate the delegate's current offset to
// the root scrollable layer.
current_offset = gfx::Vector2dF(13.f, 12.f);
@@ -2399,7 +2575,7 @@ TEST_F(LayerTreeHostImplTest, OverscrollRoot) {
SetupScrollAndContentsLayers(gfx::Size(100, 100));
host_impl_->SetViewportSize(gfx::Size(50, 50));
host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
- InitializeRendererAndDrawFrame();
+ DrawFrame();
EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
EXPECT_EQ(gfx::Vector2dF(), host_impl_->current_fling_velocity());
@@ -2470,7 +2646,7 @@ TEST_F(LayerTreeHostImplTest, OverscrollChildWithoutBubbling) {
host_impl_->active_tree()->SetRootLayer(root.Pass());
host_impl_->active_tree()->DidBecomeActive();
host_impl_->SetViewportSize(surface_size);
- InitializeRendererAndDrawFrame();
+ DrawFrame();
{
gfx::Vector2d scroll_delta(0, -10);
EXPECT_EQ(InputHandler::ScrollStarted,
@@ -2528,7 +2704,7 @@ TEST_F(LayerTreeHostImplTest, OverscrollChildEventBubbling) {
host_impl_->SetViewportSize(surface_size);
host_impl_->active_tree()->SetRootLayer(root.Pass());
host_impl_->active_tree()->DidBecomeActive();
- InitializeRendererAndDrawFrame();
+ DrawFrame();
{
gfx::Vector2d scroll_delta(0, 8);
EXPECT_EQ(InputHandler::ScrollStarted,
@@ -2544,26 +2720,25 @@ TEST_F(LayerTreeHostImplTest, OverscrollChildEventBubbling) {
}
}
+TEST_F(LayerTreeHostImplTest, OverscrollAlways) {
+ LayerTreeSettings settings;
+ settings.always_overscroll = true;
+ CreateHostImpl(settings, CreateOutputSurface());
-class BlendStateTrackerContext: public TestWebGraphicsContext3D {
- public:
- BlendStateTrackerContext() : blend_(false) {}
-
- virtual void enable(WebKit::WGC3Denum cap) OVERRIDE {
- if (cap == GL_BLEND)
- blend_ = true;
- }
-
- virtual void disable(WebKit::WGC3Denum cap) OVERRIDE {
- if (cap == GL_BLEND)
- blend_ = false;
- }
-
- bool blend() const { return blend_; }
+ SetupScrollAndContentsLayers(gfx::Size(50, 50));
+ host_impl_->SetViewportSize(gfx::Size(50, 50));
+ host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
+ DrawFrame();
+ EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
+ EXPECT_EQ(gfx::Vector2dF(), host_impl_->current_fling_velocity());
- private:
- bool blend_;
-};
+ // Even though the layer can't scroll the overscroll still happens.
+ EXPECT_EQ(InputHandler::ScrollStarted,
+ host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
+ host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
+ EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
+ EXPECT_EQ(gfx::Vector2dF(), host_impl_->current_fling_velocity());
+}
class BlendStateCheckLayer : public LayerImpl {
public:
@@ -2672,7 +2847,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
layer1->SetExpectation(false, false);
layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
EXPECT_TRUE(layer1->quads_appended());
host_impl_->DidDrawAllLayers(frame);
@@ -2681,7 +2856,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
layer1->SetExpectation(true, false);
layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
EXPECT_TRUE(layer1->quads_appended());
host_impl_->DidDrawAllLayers(frame);
@@ -2691,7 +2866,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
layer1->SetExpectation(true, false);
layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
EXPECT_TRUE(layer1->quads_appended());
host_impl_->DidDrawAllLayers(frame);
@@ -2701,7 +2876,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
layer1->SetExpectation(true, false);
layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
EXPECT_TRUE(layer1->quads_appended());
host_impl_->DidDrawAllLayers(frame);
@@ -2723,7 +2898,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
layer2->SetExpectation(false, false);
layer2->set_update_rect(gfx::RectF(layer1->content_bounds()));
EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
EXPECT_TRUE(layer1->quads_appended());
EXPECT_TRUE(layer2->quads_appended());
host_impl_->DidDrawAllLayers(frame);
@@ -2736,7 +2911,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
layer2->SetExpectation(false, false);
layer2->set_update_rect(gfx::RectF(layer1->content_bounds()));
EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
EXPECT_TRUE(layer1->quads_appended());
EXPECT_TRUE(layer2->quads_appended());
host_impl_->DidDrawAllLayers(frame);
@@ -2750,7 +2925,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
layer2->SetExpectation(false, false);
layer2->set_update_rect(gfx::RectF(layer1->content_bounds()));
EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
EXPECT_TRUE(layer1->quads_appended());
EXPECT_TRUE(layer2->quads_appended());
host_impl_->DidDrawAllLayers(frame);
@@ -2767,7 +2942,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
layer2->SetExpectation(false, false);
layer2->set_update_rect(gfx::RectF(layer1->content_bounds()));
EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
EXPECT_TRUE(layer1->quads_appended());
EXPECT_TRUE(layer2->quads_appended());
host_impl_->DidDrawAllLayers(frame);
@@ -2783,7 +2958,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
layer2->SetExpectation(true, false);
layer2->set_update_rect(gfx::RectF(layer1->content_bounds()));
EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
EXPECT_TRUE(layer1->quads_appended());
EXPECT_TRUE(layer2->quads_appended());
host_impl_->DidDrawAllLayers(frame);
@@ -2798,7 +2973,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
layer2->SetExpectation(true, false);
layer2->set_update_rect(gfx::RectF(layer1->content_bounds()));
EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
EXPECT_TRUE(layer1->quads_appended());
EXPECT_TRUE(layer2->quads_appended());
host_impl_->DidDrawAllLayers(frame);
@@ -2814,7 +2989,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
layer2->SetExpectation(false, false);
layer2->set_update_rect(gfx::RectF(layer1->content_bounds()));
EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
EXPECT_TRUE(layer1->quads_appended());
EXPECT_TRUE(layer2->quads_appended());
host_impl_->DidDrawAllLayers(frame);
@@ -2827,7 +3002,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
layer1->SetExpectation(true, false);
layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
EXPECT_TRUE(layer1->quads_appended());
host_impl_->DidDrawAllLayers(frame);
@@ -2839,7 +3014,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
layer1->SetExpectation(true, false);
layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
EXPECT_TRUE(layer1->quads_appended());
host_impl_->DidDrawAllLayers(frame);
@@ -2851,7 +3026,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
layer1->SetExpectation(true, false);
layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
EXPECT_TRUE(layer1->quads_appended());
host_impl_->DidDrawAllLayers(frame);
@@ -2864,33 +3039,24 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
layer1->SetExpectation(false, false);
layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
EXPECT_TRUE(layer1->quads_appended());
host_impl_->DidDrawAllLayers(frame);
}
class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest {
- public:
+ protected:
LayerTreeHostImplViewportCoveredTest() :
gutter_quad_material_(DrawQuad::SOLID_COLOR),
child_(NULL),
did_activate_pending_tree_(false) {}
- void CreateLayerTreeHostImpl(bool always_draw) {
- LayerTreeSettings settings;
- settings.minimum_occlusion_tracking_size = gfx::Size();
- settings.impl_side_painting = true;
- host_impl_ = LayerTreeHostImpl::Create(
- settings, this, &proxy_, &stats_instrumentation_);
-
- scoped_ptr<FakeOutputSurface> output_surface;
- if (always_draw)
- output_surface = FakeOutputSurface::CreateAlwaysDrawAndSwap3d().Pass();
- else
- output_surface = FakeOutputSurface::Create3d().Pass();
-
- host_impl_->InitializeRenderer(output_surface.PassAs<OutputSurface>());
- viewport_size_ = gfx::Size(1000, 1000);
+ scoped_ptr<OutputSurface> CreateFakeOutputSurface(bool always_draw) {
+ if (always_draw) {
+ return FakeOutputSurface::CreateAlwaysDrawAndSwap3d()
+ .PassAs<OutputSurface>();
+ }
+ return FakeOutputSurface::Create3d().PassAs<OutputSurface>();
}
void SetupActiveTreeLayers() {
@@ -3049,8 +3215,10 @@ class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest {
};
TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCovered) {
+ viewport_size_ = gfx::Size(1000, 1000);
+
bool always_draw = false;
- CreateLayerTreeHostImpl(always_draw);
+ CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
SetupActiveTreeLayers();
@@ -3061,8 +3229,10 @@ TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCovered) {
}
TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCoveredScaled) {
+ viewport_size_ = gfx::Size(1000, 1000);
+
bool always_draw = false;
- CreateLayerTreeHostImpl(always_draw);
+ CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
host_impl_->SetDeviceScaleFactor(2.f);
host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
@@ -3074,8 +3244,10 @@ TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCoveredScaled) {
}
TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCoveredOverhangBitmap) {
+ viewport_size_ = gfx::Size(1000, 1000);
+
bool always_draw = false;
- CreateLayerTreeHostImpl(always_draw);
+ CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
SetupActiveTreeLayers();
@@ -3086,7 +3258,8 @@ TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCoveredOverhangBitmap) {
skbitmap.setImmutable();
// Specify an overhang bitmap to use.
- UIResourceBitmap ui_resource_bitmap(skbitmap, UIResourceBitmap::REPEAT);
+ UIResourceBitmap ui_resource_bitmap(skbitmap);
+ ui_resource_bitmap.SetWrapMode(UIResourceBitmap::REPEAT);
UIResourceId ui_resource_id = 12345;
host_impl_->CreateUIResource(ui_resource_id, ui_resource_bitmap);
host_impl_->SetOverhangUIResource(ui_resource_id, gfx::Size(32, 32));
@@ -3118,8 +3291,10 @@ TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCoveredOverhangBitmap) {
}
TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeGrowViewportInvalid) {
+ viewport_size_ = gfx::Size(1000, 1000);
+
bool always_draw = true;
- CreateLayerTreeHostImpl(always_draw);
+ CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
// Pending tree to force active_tree size invalid. Not used otherwise.
host_impl_->CreatePendingTree();
@@ -3133,8 +3308,10 @@ TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeGrowViewportInvalid) {
}
TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeShrinkViewportInvalid) {
+ viewport_size_ = gfx::Size(1000, 1000);
+
bool always_draw = true;
- CreateLayerTreeHostImpl(always_draw);
+ CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
// Set larger viewport and activate it to active tree.
host_impl_->CreatePendingTree();
@@ -3157,36 +3334,6 @@ TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeShrinkViewportInvalid) {
TestLayerIsLargerThanViewport();
}
-class ReshapeTrackerContext: public TestWebGraphicsContext3D {
- public:
- ReshapeTrackerContext()
- : reshape_called_(false),
- last_reshape_width_(-1),
- last_reshape_height_(-1),
- last_reshape_scale_factor_(-1.f) {
- }
-
- virtual void reshapeWithScaleFactor(
- int width, int height, float scale_factor) OVERRIDE {
- reshape_called_ = true;
- last_reshape_width_ = width;
- last_reshape_height_ = height;
- last_reshape_scale_factor_ = scale_factor;
- }
-
- bool reshape_called() const { return reshape_called_; }
- void clear_reshape_called() { reshape_called_ = false; }
- int last_reshape_width() { return last_reshape_width_; }
- int last_reshape_height() { return last_reshape_height_; }
- int last_reshape_scale_factor() { return last_reshape_scale_factor_; }
-
- private:
- bool reshape_called_;
- int last_reshape_width_;
- int last_reshape_height_;
- float last_reshape_scale_factor_;
-};
-
class FakeDrawableLayerImpl: public LayerImpl {
public:
static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
@@ -3201,12 +3348,10 @@ class FakeDrawableLayerImpl: public LayerImpl {
// can leave the window at the wrong size if we never draw and the proper
// viewport size is never set.
TEST_F(LayerTreeHostImplTest, ReshapeNotCalledUntilDraw) {
- scoped_ptr<ReshapeTrackerContext> owned_reshape_tracker(
- new ReshapeTrackerContext);
- ReshapeTrackerContext* reshape_tracker = owned_reshape_tracker.get();
- scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
- owned_reshape_tracker.PassAs<TestWebGraphicsContext3D>()));
- host_impl_->InitializeRenderer(output_surface.Pass());
+ scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
+ scoped_ptr<OutputSurface> output_surface(
+ FakeOutputSurface::Create3d(provider));
+ CreateHostImpl(DefaultSettings(), output_surface.Pass());
scoped_ptr<LayerImpl> root =
FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
@@ -3215,96 +3360,60 @@ TEST_F(LayerTreeHostImplTest, ReshapeNotCalledUntilDraw) {
root->SetContentBounds(gfx::Size(10, 10));
root->SetDrawsContent(true);
host_impl_->active_tree()->SetRootLayer(root.Pass());
- EXPECT_FALSE(reshape_tracker->reshape_called());
- reshape_tracker->clear_reshape_called();
+ EXPECT_FALSE(provider->TestContext3d()->reshape_called());
+ provider->TestContext3d()->clear_reshape_called();
LayerTreeHostImpl::FrameData frame;
host_impl_->SetViewportSize(gfx::Size(10, 10));
host_impl_->SetDeviceScaleFactor(1.f);
EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
- EXPECT_TRUE(reshape_tracker->reshape_called());
- EXPECT_EQ(reshape_tracker->last_reshape_width(), 10);
- EXPECT_EQ(reshape_tracker->last_reshape_height(), 10);
- EXPECT_EQ(reshape_tracker->last_reshape_scale_factor(), 1.f);
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
+ EXPECT_TRUE(provider->TestContext3d()->reshape_called());
+ EXPECT_EQ(provider->TestContext3d()->width(), 10);
+ EXPECT_EQ(provider->TestContext3d()->height(), 10);
+ EXPECT_EQ(provider->TestContext3d()->scale_factor(), 1.f);
host_impl_->DidDrawAllLayers(frame);
- reshape_tracker->clear_reshape_called();
+ provider->TestContext3d()->clear_reshape_called();
host_impl_->SetViewportSize(gfx::Size(20, 30));
EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
- EXPECT_TRUE(reshape_tracker->reshape_called());
- EXPECT_EQ(reshape_tracker->last_reshape_width(), 20);
- EXPECT_EQ(reshape_tracker->last_reshape_height(), 30);
- EXPECT_EQ(reshape_tracker->last_reshape_scale_factor(), 1.f);
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
+ EXPECT_TRUE(provider->TestContext3d()->reshape_called());
+ EXPECT_EQ(provider->TestContext3d()->width(), 20);
+ EXPECT_EQ(provider->TestContext3d()->height(), 30);
+ EXPECT_EQ(provider->TestContext3d()->scale_factor(), 1.f);
host_impl_->DidDrawAllLayers(frame);
- reshape_tracker->clear_reshape_called();
+ provider->TestContext3d()->clear_reshape_called();
host_impl_->SetDeviceScaleFactor(2.f);
EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
- EXPECT_TRUE(reshape_tracker->reshape_called());
- EXPECT_EQ(reshape_tracker->last_reshape_width(), 20);
- EXPECT_EQ(reshape_tracker->last_reshape_height(), 30);
- EXPECT_EQ(reshape_tracker->last_reshape_scale_factor(), 2.f);
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
+ EXPECT_TRUE(provider->TestContext3d()->reshape_called());
+ EXPECT_EQ(provider->TestContext3d()->width(), 20);
+ EXPECT_EQ(provider->TestContext3d()->height(), 30);
+ EXPECT_EQ(provider->TestContext3d()->scale_factor(), 2.f);
host_impl_->DidDrawAllLayers(frame);
- reshape_tracker->clear_reshape_called();
+ provider->TestContext3d()->clear_reshape_called();
}
-class SwapTrackerContext : public TestWebGraphicsContext3D {
- public:
- SwapTrackerContext()
- : last_update_type_(NoUpdate) {
- test_capabilities_.post_sub_buffer = true;
- test_capabilities_.set_visibility = true;
- }
-
- virtual void prepareTexture() OVERRIDE {
- update_rect_ = gfx::Rect(width_, height_);
- last_update_type_ = PrepareTexture;
- }
-
- virtual void postSubBufferCHROMIUM(int x, int y, int width, int height)
- OVERRIDE {
- update_rect_ = gfx::Rect(x, y, width, height);
- last_update_type_ = PostSubBuffer;
- }
-
- gfx::Rect update_rect() const { return update_rect_; }
-
- enum UpdateType {
- NoUpdate = 0,
- PrepareTexture,
- PostSubBuffer
- };
-
- UpdateType last_update_type() {
- return last_update_type_;
- }
-
- private:
- gfx::Rect update_rect_;
- UpdateType last_update_type_;
-};
-
// Make sure damage tracking propagates all the way to the graphics context,
// where it should request to swap only the sub-buffer that is damaged.
TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) {
- scoped_ptr<SwapTrackerContext> context(new SwapTrackerContext);
- SwapTrackerContext* swap_tracker = context.get();
+ scoped_refptr<TestContextProvider> context_provider(
+ TestContextProvider::Create());
+ context_provider->BindToCurrentThread();
+ context_provider->TestContext3d()->set_have_post_sub_buffer(true);
- scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
- context.PassAs<TestWebGraphicsContext3D>()));
+ scoped_ptr<OutputSurface> output_surface(
+ FakeOutputSurface::Create3d(context_provider));
// This test creates its own LayerTreeHostImpl, so
// that we can force partial swap enabled.
LayerTreeSettings settings;
settings.partial_swap_enabled = true;
scoped_ptr<LayerTreeHostImpl> layer_tree_host_impl =
- LayerTreeHostImpl::Create(settings,
- this,
- &proxy_,
- &stats_instrumentation_);
+ LayerTreeHostImpl::Create(
+ settings, this, &proxy_, &stats_instrumentation_, NULL, 0);
layer_tree_host_impl->InitializeRenderer(output_surface.Pass());
layer_tree_host_impl->SetViewportSize(gfx::Size(500, 500));
@@ -3328,17 +3437,12 @@ TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) {
// First frame, the entire screen should get swapped.
EXPECT_TRUE(layer_tree_host_impl->PrepareToDraw(&frame, gfx::Rect()));
- layer_tree_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
+ layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
layer_tree_host_impl->DidDrawAllLayers(frame);
layer_tree_host_impl->SwapBuffers(frame);
- gfx::Rect actual_swap_rect = swap_tracker->update_rect();
- gfx::Rect expected_swap_rect = gfx::Rect(0, 0, 500, 500);
- EXPECT_EQ(expected_swap_rect.x(), actual_swap_rect.x());
- EXPECT_EQ(expected_swap_rect.y(), actual_swap_rect.y());
- EXPECT_EQ(expected_swap_rect.width(), actual_swap_rect.width());
- EXPECT_EQ(expected_swap_rect.height(), actual_swap_rect.height());
- EXPECT_EQ(swap_tracker->last_update_type(),
- SwapTrackerContext::PrepareTexture);
+ EXPECT_EQ(TestContextSupport::SWAP,
+ context_provider->support()->last_swap_type());
+
// Second frame, only the damaged area should get swapped. Damage should be
// the union of old and new child rects.
// expected damage rect: gfx::Rect(26, 28);
@@ -3346,37 +3450,31 @@ TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) {
layer_tree_host_impl->active_tree()->root_layer()->children()[0]->SetPosition(
gfx::PointF());
EXPECT_TRUE(layer_tree_host_impl->PrepareToDraw(&frame, gfx::Rect()));
- layer_tree_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
+ layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
layer_tree_host_impl->SwapBuffers(frame);
- actual_swap_rect = swap_tracker->update_rect();
- expected_swap_rect = gfx::Rect(0, 500-28, 26, 28);
- EXPECT_EQ(expected_swap_rect.x(), actual_swap_rect.x());
- EXPECT_EQ(expected_swap_rect.y(), actual_swap_rect.y());
- EXPECT_EQ(expected_swap_rect.width(), actual_swap_rect.width());
- EXPECT_EQ(expected_swap_rect.height(), actual_swap_rect.height());
- EXPECT_EQ(swap_tracker->last_update_type(),
- SwapTrackerContext::PostSubBuffer);
// Make sure that partial swap is constrained to the viewport dimensions
// expected damage rect: gfx::Rect(500, 500);
// expected swap rect: flipped damage rect, but also clamped to viewport
+ EXPECT_EQ(TestContextSupport::PARTIAL_SWAP,
+ context_provider->support()->last_swap_type());
+ gfx::Rect expected_swap_rect(0, 500-28, 26, 28);
+ EXPECT_EQ(expected_swap_rect.ToString(),
+ context_provider->support()->
+ last_partial_swap_rect().ToString());
+
layer_tree_host_impl->SetViewportSize(gfx::Size(10, 10));
// This will damage everything.
layer_tree_host_impl->active_tree()->root_layer()->SetBackgroundColor(
SK_ColorBLACK);
EXPECT_TRUE(layer_tree_host_impl->PrepareToDraw(&frame, gfx::Rect()));
- layer_tree_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
+ layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
layer_tree_host_impl->SwapBuffers(frame);
- actual_swap_rect = swap_tracker->update_rect();
- expected_swap_rect = gfx::Rect(10, 10);
- EXPECT_EQ(expected_swap_rect.x(), actual_swap_rect.x());
- EXPECT_EQ(expected_swap_rect.y(), actual_swap_rect.y());
- EXPECT_EQ(expected_swap_rect.width(), actual_swap_rect.width());
- EXPECT_EQ(expected_swap_rect.height(), actual_swap_rect.height());
- EXPECT_EQ(swap_tracker->last_update_type(),
- SwapTrackerContext::PrepareTexture);
+
+ EXPECT_EQ(TestContextSupport::SWAP,
+ context_provider->support()->last_swap_type());
}
TEST_F(LayerTreeHostImplTest, RootLayerDoesntCreateExtraSurface) {
@@ -3430,27 +3528,27 @@ class FakeLayerWithQuads : public LayerImpl {
class MockContext : public TestWebGraphicsContext3D {
public:
- MOCK_METHOD1(useProgram, void(WebKit::WebGLId program));
- MOCK_METHOD5(uniform4f, void(WebKit::WGC3Dint location,
- WebKit::WGC3Dfloat x,
- WebKit::WGC3Dfloat y,
- WebKit::WGC3Dfloat z,
- WebKit::WGC3Dfloat w));
- MOCK_METHOD4(uniformMatrix4fv, void(WebKit::WGC3Dint location,
- WebKit::WGC3Dsizei count,
- WebKit::WGC3Dboolean transpose,
- const WebKit::WGC3Dfloat* value));
- MOCK_METHOD4(drawElements, void(WebKit::WGC3Denum mode,
- WebKit::WGC3Dsizei count,
- WebKit::WGC3Denum type,
- WebKit::WGC3Dintptr offset));
- MOCK_METHOD0(getRequestableExtensionsCHROMIUM, WebKit::WebString());
- MOCK_METHOD1(enable, void(WebKit::WGC3Denum cap));
- MOCK_METHOD1(disable, void(WebKit::WGC3Denum cap));
- MOCK_METHOD4(scissor, void(WebKit::WGC3Dint x,
- WebKit::WGC3Dint y,
- WebKit::WGC3Dsizei width,
- WebKit::WGC3Dsizei height));
+ MOCK_METHOD1(useProgram, void(blink::WebGLId program));
+ MOCK_METHOD5(uniform4f, void(blink::WGC3Dint location,
+ blink::WGC3Dfloat x,
+ blink::WGC3Dfloat y,
+ blink::WGC3Dfloat z,
+ blink::WGC3Dfloat w));
+ MOCK_METHOD4(uniformMatrix4fv, void(blink::WGC3Dint location,
+ blink::WGC3Dsizei count,
+ blink::WGC3Dboolean transpose,
+ const blink::WGC3Dfloat* value));
+ MOCK_METHOD4(drawElements, void(blink::WGC3Denum mode,
+ blink::WGC3Dsizei count,
+ blink::WGC3Denum type,
+ blink::WGC3Dintptr offset));
+ MOCK_METHOD0(getRequestableExtensionsCHROMIUM, blink::WebString());
+ MOCK_METHOD1(enable, void(blink::WGC3Denum cap));
+ MOCK_METHOD1(disable, void(blink::WGC3Denum cap));
+ MOCK_METHOD4(scissor, void(blink::WGC3Dint x,
+ blink::WGC3Dint y,
+ blink::WGC3Dsizei width,
+ blink::WGC3Dsizei height));
};
class MockContextHarness {
@@ -3525,7 +3623,9 @@ TEST_F(LayerTreeHostImplTest, NoPartialSwap) {
MockContextHarness harness(mock_context);
// Run test case
- CreateLayerTreeHost(false, output_surface.Pass());
+ LayerTreeSettings settings = DefaultSettings();
+ settings.partial_swap_enabled = false;
+ CreateHostImpl(settings, output_surface.Pass());
SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
// Without partial swap, and no clipping, no scissor is set.
@@ -3534,7 +3634,7 @@ TEST_F(LayerTreeHostImplTest, NoPartialSwap) {
{
LayerTreeHostImpl::FrameData frame;
EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
Mock::VerifyAndClearExpectations(&mock_context);
@@ -3547,7 +3647,7 @@ TEST_F(LayerTreeHostImplTest, NoPartialSwap) {
{
LayerTreeHostImpl::FrameData frame;
EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
Mock::VerifyAndClearExpectations(&mock_context);
@@ -3560,7 +3660,9 @@ TEST_F(LayerTreeHostImplTest, PartialSwap) {
context_owned.PassAs<TestWebGraphicsContext3D>()));
MockContextHarness harness(mock_context);
- CreateLayerTreeHost(true, output_surface.Pass());
+ LayerTreeSettings settings = DefaultSettings();
+ settings.partial_swap_enabled = true;
+ CreateHostImpl(settings, output_surface.Pass());
SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
// The first frame is not a partially-swapped one.
@@ -3569,7 +3671,7 @@ TEST_F(LayerTreeHostImplTest, PartialSwap) {
{
LayerTreeHostImpl::FrameData frame;
EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
Mock::VerifyAndClearExpectations(&mock_context);
@@ -3584,40 +3686,27 @@ TEST_F(LayerTreeHostImplTest, PartialSwap) {
{
LayerTreeHostImpl::FrameData frame;
EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
Mock::VerifyAndClearExpectations(&mock_context);
}
-class PartialSwapContext : public TestWebGraphicsContext3D {
- public:
- PartialSwapContext() {
- test_capabilities_.post_sub_buffer = true;
- }
-
- // Unlimited texture size.
- virtual void getIntegerv(WebKit::WGC3Denum pname, WebKit::WGC3Dint* value)
- OVERRIDE {
- if (pname == GL_MAX_TEXTURE_SIZE)
- *value = 8192;
- else if (pname == GL_ACTIVE_TEXTURE)
- *value = GL_TEXTURE0;
- }
-};
-
static scoped_ptr<LayerTreeHostImpl> SetupLayersForOpacity(
bool partial_swap,
LayerTreeHostImplClient* client,
Proxy* proxy,
RenderingStatsInstrumentation* stats_instrumentation) {
- scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
- scoped_ptr<TestWebGraphicsContext3D>(new PartialSwapContext)));
+ scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
+ scoped_ptr<OutputSurface> output_surface(
+ FakeOutputSurface::Create3d(provider));
+ provider->BindToCurrentThread();
+ provider->TestContext3d()->set_have_post_sub_buffer(true);
LayerTreeSettings settings;
settings.partial_swap_enabled = partial_swap;
- scoped_ptr<LayerTreeHostImpl> my_host_impl =
- LayerTreeHostImpl::Create(settings, client, proxy, stats_instrumentation);
+ scoped_ptr<LayerTreeHostImpl> my_host_impl = LayerTreeHostImpl::Create(
+ settings, client, proxy, stats_instrumentation, NULL, 0);
my_host_impl->InitializeRenderer(output_surface.Pass());
my_host_impl->SetViewportSize(gfx::Size(100, 100));
@@ -3698,7 +3787,7 @@ TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorPartialSwap) {
EXPECT_EQ(DrawQuad::RENDER_PASS,
frame.render_passes[1]->quad_list[0]->material);
- my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
+ my_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
my_host_impl->DidDrawAllLayers(frame);
}
}
@@ -3719,51 +3808,18 @@ TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorNoPartialSwap) {
EXPECT_EQ(DrawQuad::RENDER_PASS,
frame.render_passes[1]->quad_list[0]->material);
- my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
+ my_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
my_host_impl->DidDrawAllLayers(frame);
}
}
-// Fake WebKit::WebGraphicsContext3D that tracks the number of textures in use.
-class TrackingWebGraphicsContext3D : public TestWebGraphicsContext3D {
- public:
- TrackingWebGraphicsContext3D()
- : TestWebGraphicsContext3D(),
- num_textures_(0) {
- test_capabilities_.iosurface = true;
- test_capabilities_.texture_rectangle = true;
- }
-
- virtual WebKit::WebGLId createTexture() OVERRIDE {
- WebKit::WebGLId id = TestWebGraphicsContext3D::createTexture();
-
- textures_[id] = true;
- ++num_textures_;
- return id;
- }
-
- virtual void deleteTexture(WebKit::WebGLId id) OVERRIDE {
- if (textures_.find(id) == textures_.end())
- return;
-
- textures_[id] = false;
- --num_textures_;
- }
-
- unsigned num_textures() const { return num_textures_; }
-
- private:
- base::hash_map<WebKit::WebGLId, bool> textures_;
- unsigned num_textures_;
-};
-
TEST_F(LayerTreeHostImplTest, LayersFreeTextures) {
scoped_ptr<TestWebGraphicsContext3D> context =
TestWebGraphicsContext3D::Create();
TestWebGraphicsContext3D* context3d = context.get();
scoped_ptr<OutputSurface> output_surface(
FakeOutputSurface::Create3d(context.Pass()));
- host_impl_->InitializeRenderer(output_surface.Pass());
+ CreateHostImpl(DefaultSettings(), output_surface.Pass());
scoped_ptr<LayerImpl> root_layer =
LayerImpl::Create(host_impl_->active_tree(), 1);
@@ -3798,7 +3854,7 @@ TEST_F(LayerTreeHostImplTest, LayersFreeTextures) {
LayerTreeHostImpl::FrameData frame;
EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
host_impl_->SwapBuffers(frame);
@@ -3813,11 +3869,11 @@ TEST_F(LayerTreeHostImplTest, LayersFreeTextures) {
class MockDrawQuadsToFillScreenContext : public TestWebGraphicsContext3D {
public:
- MOCK_METHOD1(useProgram, void(WebKit::WebGLId program));
- MOCK_METHOD4(drawElements, void(WebKit::WGC3Denum mode,
- WebKit::WGC3Dsizei count,
- WebKit::WGC3Denum type,
- WebKit::WGC3Dintptr offset));
+ MOCK_METHOD1(useProgram, void(blink::WebGLId program));
+ MOCK_METHOD4(drawElements, void(blink::WGC3Denum mode,
+ blink::WGC3Dsizei count,
+ blink::WGC3Denum type,
+ blink::WGC3Dintptr offset));
};
TEST_F(LayerTreeHostImplTest, HasTransparentBackground) {
@@ -3829,7 +3885,9 @@ TEST_F(LayerTreeHostImplTest, HasTransparentBackground) {
mock_context_owned.PassAs<TestWebGraphicsContext3D>()));
// Run test case
- CreateLayerTreeHost(false, output_surface.Pass());
+ LayerTreeSettings settings = DefaultSettings();
+ settings.partial_swap_enabled = false;
+ CreateHostImpl(settings, output_surface.Pass());
SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
host_impl_->active_tree()->set_background_color(SK_ColorWHITE);
@@ -3841,7 +3899,7 @@ TEST_F(LayerTreeHostImplTest, HasTransparentBackground) {
.Times(1);
LayerTreeHostImpl::FrameData frame;
EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
Mock::VerifyAndClearExpectations(&mock_context);
@@ -3849,1118 +3907,11 @@ TEST_F(LayerTreeHostImplTest, HasTransparentBackground) {
host_impl_->active_tree()->set_has_transparent_background(true);
host_impl_->SetFullRootLayerDamage();
EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
Mock::VerifyAndClearExpectations(&mock_context);
}
-static void AddDrawingLayerTo(LayerImpl* parent,
- int id,
- gfx::Rect layer_rect,
- LayerImpl** result) {
- scoped_ptr<LayerImpl> layer =
- FakeLayerWithQuads::Create(parent->layer_tree_impl(), id);
- LayerImpl* layer_ptr = layer.get();
- layer_ptr->SetAnchorPoint(gfx::PointF());
- layer_ptr->SetPosition(gfx::PointF(layer_rect.origin()));
- layer_ptr->SetBounds(layer_rect.size());
- layer_ptr->SetContentBounds(layer_rect.size());
- layer_ptr->SetDrawsContent(true); // only children draw content
- layer_ptr->SetContentsOpaque(true);
- parent->AddChild(layer.Pass());
- if (result)
- *result = layer_ptr;
-}
-
-static void SetupLayersForTextureCaching(
- LayerTreeHostImpl* layer_tree_host_impl,
- LayerImpl*& root_ptr,
- LayerImpl*& intermediate_layer_ptr,
- LayerImpl*& surface_layer_ptr,
- LayerImpl*& child_ptr,
- gfx::Size root_size) {
- scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
- scoped_ptr<TestWebGraphicsContext3D>(new PartialSwapContext)));
-
- layer_tree_host_impl->InitializeRenderer(output_surface.Pass());
- layer_tree_host_impl->SetViewportSize(root_size);
-
- scoped_ptr<LayerImpl> root =
- LayerImpl::Create(layer_tree_host_impl->active_tree(), 1);
- root_ptr = root.get();
-
- root->SetAnchorPoint(gfx::PointF());
- root->SetPosition(gfx::PointF());
- root->SetBounds(root_size);
- root->SetContentBounds(root_size);
- root->SetDrawsContent(true);
- layer_tree_host_impl->active_tree()->SetRootLayer(root.Pass());
-
- AddDrawingLayerTo(root_ptr,
- 2,
- gfx::Rect(10, 10, root_size.width(), root_size.height()),
- &intermediate_layer_ptr);
- // Only children draw content.
- intermediate_layer_ptr->SetDrawsContent(false);
-
- // Surface layer is the layer that changes its opacity
- // It will contain other layers that draw content.
- AddDrawingLayerTo(intermediate_layer_ptr,
- 3,
- gfx::Rect(10, 10, root_size.width(), root_size.height()),
- &surface_layer_ptr);
- // Only children draw content.
- surface_layer_ptr->SetDrawsContent(false);
- surface_layer_ptr->SetOpacity(0.5f);
- surface_layer_ptr->SetForceRenderSurface(true);
-
- // Child of the surface layer will produce some quads
- AddDrawingLayerTo(surface_layer_ptr,
- 4,
- gfx::Rect(5,
- 5,
- root_size.width() - 25,
- root_size.height() - 25),
- &child_ptr);
-}
-
-class GLRendererWithReleaseTextures : public GLRenderer {
- public:
- using GLRenderer::ReleaseRenderPassTextures;
-};
-
-TEST_F(LayerTreeHostImplTest, TextureCachingWithOcclusion) {
- LayerTreeSettings settings;
- settings.minimum_occlusion_tracking_size = gfx::Size();
- settings.cache_render_pass_contents = true;
- scoped_ptr<LayerTreeHostImpl> my_host_impl =
- LayerTreeHostImpl::Create(settings,
- this,
- &proxy_,
- &stats_instrumentation_);
-
- // Layers are structure as follows:
- //
- // R +-- S1 +- L10 (owning)
- // | +- L11
- // | +- L12
- // |
- // +-- S2 +- L20 (owning)
- // +- L21
- //
- // Occlusion:
- // L12 occludes L11 (internal)
- // L20 occludes L10 (external)
- // L21 occludes L20 (internal)
-
- LayerImpl* root_ptr;
- LayerImpl* layer_s1_ptr;
- LayerImpl* layer_s2_ptr;
-
- scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
- scoped_ptr<TestWebGraphicsContext3D>(new PartialSwapContext)));
-
- gfx::Size root_size(1000, 1000);
-
- my_host_impl->InitializeRenderer(output_surface.Pass());
- my_host_impl->SetViewportSize(root_size);
-
- scoped_ptr<LayerImpl> root =
- LayerImpl::Create(my_host_impl->active_tree(), 1);
- root_ptr = root.get();
-
- root->SetAnchorPoint(gfx::PointF());
- root->SetPosition(gfx::PointF());
- root->SetBounds(root_size);
- root->SetContentBounds(root_size);
- root->SetDrawsContent(true);
- root->SetMasksToBounds(true);
- my_host_impl->active_tree()->SetRootLayer(root.Pass());
-
- AddDrawingLayerTo(root_ptr, 2, gfx::Rect(300, 300, 300, 300), &layer_s1_ptr);
- layer_s1_ptr->SetForceRenderSurface(true);
-
- AddDrawingLayerTo(layer_s1_ptr, 3, gfx::Rect(10, 10, 10, 10), 0); // L11
- AddDrawingLayerTo(layer_s1_ptr, 4, gfx::Rect(0, 0, 30, 30), 0); // L12
-
- AddDrawingLayerTo(root_ptr, 5, gfx::Rect(550, 250, 300, 400), &layer_s2_ptr);
- layer_s2_ptr->SetForceRenderSurface(true);
-
- AddDrawingLayerTo(layer_s2_ptr, 6, gfx::Rect(20, 20, 5, 5), 0); // L21
-
- // Initial draw - must receive all quads
- {
- LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
-
- // Must receive 3 render passes.
- // For Root, there are 2 quads; for S1, there are 2 quads (1 is occluded);
- // for S2, there is 2 quads.
- ASSERT_EQ(3U, frame.render_passes.size());
-
- EXPECT_EQ(2U, frame.render_passes[0]->quad_list.size());
- EXPECT_EQ(2U, frame.render_passes[1]->quad_list.size());
- EXPECT_EQ(2U, frame.render_passes[2]->quad_list.size());
-
- my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
- my_host_impl->DidDrawAllLayers(frame);
- }
-
- // "Unocclude" surface S1 and repeat draw.
- // Must remove S2's render pass since it's cached;
- // Must keep S1 quads because texture contained external occlusion.
- gfx::Transform transform = layer_s2_ptr->transform();
- transform.Translate(150.0, 150.0);
- layer_s2_ptr->SetTransform(transform);
- {
- LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
-
- // Must receive 2 render passes.
- // For Root, there are 2 quads
- // For S1, the number of quads depends on what got unoccluded, so not
- // asserted beyond being positive.
- // For S2, there is no render pass
- ASSERT_EQ(2U, frame.render_passes.size());
-
- EXPECT_GT(frame.render_passes[0]->quad_list.size(), 0U);
- EXPECT_EQ(2U, frame.render_passes[1]->quad_list.size());
-
- my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
- my_host_impl->DidDrawAllLayers(frame);
- }
-
- // "Re-occlude" surface S1 and repeat draw.
- // Must remove S1's render pass since it is now available in full.
- // S2 has no change so must also be removed.
- transform = layer_s2_ptr->transform();
- transform.Translate(-15.0, -15.0);
- layer_s2_ptr->SetTransform(transform);
- {
- LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
-
- // Must receive 1 render pass - for the root.
- ASSERT_EQ(1U, frame.render_passes.size());
-
- EXPECT_EQ(2U, frame.render_passes[0]->quad_list.size());
-
- my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
- my_host_impl->DidDrawAllLayers(frame);
- }
-}
-
-TEST_F(LayerTreeHostImplTest, TextureCachingWithOcclusionEarlyOut) {
- LayerTreeSettings settings;
- settings.minimum_occlusion_tracking_size = gfx::Size();
- settings.cache_render_pass_contents = true;
- scoped_ptr<LayerTreeHostImpl> my_host_impl =
- LayerTreeHostImpl::Create(settings,
- this,
- &proxy_,
- &stats_instrumentation_);
-
- // Layers are structure as follows:
- //
- // R +-- S1 +- L10 (owning, non drawing)
- // | +- L11 (corner, unoccluded)
- // | +- L12 (corner, unoccluded)
- // | +- L13 (corner, unoccluded)
- // | +- L14 (corner, entirely occluded)
- // |
- // +-- S2 +- L20 (owning, drawing)
- //
-
- LayerImpl* root_ptr;
- LayerImpl* layer_s1_ptr;
- LayerImpl* layer_s2_ptr;
-
- scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
- scoped_ptr<TestWebGraphicsContext3D>(new PartialSwapContext)));
-
- gfx::Size root_size(1000, 1000);
-
- my_host_impl->InitializeRenderer(output_surface.Pass());
- my_host_impl->SetViewportSize(root_size);
-
- scoped_ptr<LayerImpl> root =
- LayerImpl::Create(my_host_impl->active_tree(), 1);
- root_ptr = root.get();
-
- root->SetAnchorPoint(gfx::PointF());
- root->SetPosition(gfx::PointF());
- root->SetBounds(root_size);
- root->SetContentBounds(root_size);
- root->SetDrawsContent(true);
- root->SetMasksToBounds(true);
- my_host_impl->active_tree()->SetRootLayer(root.Pass());
-
- AddDrawingLayerTo(root_ptr, 2, gfx::Rect(0, 0, 800, 800), &layer_s1_ptr);
- layer_s1_ptr->SetForceRenderSurface(true);
- layer_s1_ptr->SetDrawsContent(false);
-
- AddDrawingLayerTo(layer_s1_ptr, 3, gfx::Rect(0, 0, 300, 300), 0); // L11
- AddDrawingLayerTo(layer_s1_ptr, 4, gfx::Rect(0, 500, 300, 300), 0); // L12
- AddDrawingLayerTo(layer_s1_ptr, 5, gfx::Rect(500, 0, 300, 300), 0); // L13
- AddDrawingLayerTo(layer_s1_ptr, 6, gfx::Rect(500, 500, 300, 300), 0); // L14
- AddDrawingLayerTo(layer_s1_ptr, 9, gfx::Rect(500, 500, 300, 300), 0); // L14
-
- AddDrawingLayerTo(root_ptr, 7, gfx::Rect(450, 450, 450, 450), &layer_s2_ptr);
- layer_s2_ptr->SetForceRenderSurface(true);
-
- // Initial draw - must receive all quads
- {
- LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
-
- // Must receive 3 render passes.
- // For Root, there are 2 quads; for S1, there are 3 quads; for S2, there is
- // 1 quad.
- ASSERT_EQ(3U, frame.render_passes.size());
-
- EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
-
- // L14 is culled, so only 3 quads.
- EXPECT_EQ(3U, frame.render_passes[1]->quad_list.size());
- EXPECT_EQ(2U, frame.render_passes[2]->quad_list.size());
-
- my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
- my_host_impl->DidDrawAllLayers(frame);
- }
-
- // "Unocclude" surface S1 and repeat draw.
- // Must remove S2's render pass since it's cached;
- // Must keep S1 quads because texture contained external occlusion.
- gfx::Transform transform = layer_s2_ptr->transform();
- transform.Translate(100.0, 100.0);
- layer_s2_ptr->SetTransform(transform);
- {
- LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
-
- // Must receive 2 render passes.
- // For Root, there are 2 quads
- // For S1, the number of quads depends on what got unoccluded, so not
- // asserted beyond being positive.
- // For S2, there is no render pass
- ASSERT_EQ(2U, frame.render_passes.size());
-
- EXPECT_GT(frame.render_passes[0]->quad_list.size(), 0U);
- EXPECT_EQ(2U, frame.render_passes[1]->quad_list.size());
-
- my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
- my_host_impl->DidDrawAllLayers(frame);
- }
-
- // "Re-occlude" surface S1 and repeat draw.
- // Must remove S1's render pass since it is now available in full.
- // S2 has no change so must also be removed.
- transform = layer_s2_ptr->transform();
- transform.Translate(-15.0, -15.0);
- layer_s2_ptr->SetTransform(transform);
- {
- LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
-
- // Must receive 1 render pass - for the root.
- ASSERT_EQ(1U, frame.render_passes.size());
-
- EXPECT_EQ(2U, frame.render_passes[0]->quad_list.size());
-
- my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
- my_host_impl->DidDrawAllLayers(frame);
- }
-}
-
-TEST_F(LayerTreeHostImplTest, TextureCachingWithOcclusionExternalOverInternal) {
- LayerTreeSettings settings;
- settings.minimum_occlusion_tracking_size = gfx::Size();
- settings.cache_render_pass_contents = true;
- scoped_ptr<LayerTreeHostImpl> my_host_impl =
- LayerTreeHostImpl::Create(settings,
- this,
- &proxy_,
- &stats_instrumentation_);
-
- // Layers are structured as follows:
- //
- // R +-- S1 +- L10 (owning, drawing)
- // | +- L11 (corner, occluded by L12)
- // | +- L12 (opposite corner)
- // |
- // +-- S2 +- L20 (owning, drawing)
- //
-
- LayerImpl* root_ptr;
- LayerImpl* layer_s1_ptr;
- LayerImpl* layer_s2_ptr;
-
- scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
- scoped_ptr<TestWebGraphicsContext3D>(new PartialSwapContext)));
-
- gfx::Size root_size(1000, 1000);
-
- my_host_impl->InitializeRenderer(output_surface.Pass());
- my_host_impl->SetViewportSize(root_size);
-
- scoped_ptr<LayerImpl> root =
- LayerImpl::Create(my_host_impl->active_tree(), 1);
- root_ptr = root.get();
-
- root->SetAnchorPoint(gfx::PointF());
- root->SetPosition(gfx::PointF());
- root->SetBounds(root_size);
- root->SetContentBounds(root_size);
- root->SetDrawsContent(true);
- root->SetMasksToBounds(true);
- my_host_impl->active_tree()->SetRootLayer(root.Pass());
-
- AddDrawingLayerTo(root_ptr, 2, gfx::Rect(0, 0, 400, 400), &layer_s1_ptr);
- layer_s1_ptr->SetForceRenderSurface(true);
-
- AddDrawingLayerTo(layer_s1_ptr, 3, gfx::Rect(0, 0, 300, 300), 0); // L11
- AddDrawingLayerTo(layer_s1_ptr, 4, gfx::Rect(100, 0, 300, 300), 0); // L12
-
- AddDrawingLayerTo(root_ptr, 7, gfx::Rect(200, 0, 300, 300), &layer_s2_ptr);
- layer_s2_ptr->SetForceRenderSurface(true);
-
- // Initial draw - must receive all quads
- {
- LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
-
- // Must receive 3 render passes.
- // For Root, there are 2 quads; for S1, there are 3 quads; for S2, there is
- // 1 quad.
- ASSERT_EQ(3U, frame.render_passes.size());
-
- EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
- EXPECT_EQ(3U, frame.render_passes[1]->quad_list.size());
- EXPECT_EQ(2U, frame.render_passes[2]->quad_list.size());
-
- my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
- my_host_impl->DidDrawAllLayers(frame);
- }
-
- // "Unocclude" surface S1 and repeat draw.
- // Must remove S2's render pass since it's cached;
- // Must keep S1 quads because texture contained external occlusion.
- gfx::Transform transform = layer_s2_ptr->transform();
- transform.Translate(300.0, 0.0);
- layer_s2_ptr->SetTransform(transform);
- {
- LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
-
- // Must receive 2 render passes.
- // For Root, there are 2 quads
- // For S1, the number of quads depends on what got unoccluded, so not
- // asserted beyond being positive.
- // For S2, there is no render pass
- ASSERT_EQ(2U, frame.render_passes.size());
-
- EXPECT_GT(frame.render_passes[0]->quad_list.size(), 0U);
- EXPECT_EQ(2U, frame.render_passes[1]->quad_list.size());
-
- my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
- my_host_impl->DidDrawAllLayers(frame);
- }
-}
-
-TEST_F(LayerTreeHostImplTest, TextureCachingWithOcclusionExternalNotAligned) {
- LayerTreeSettings settings;
- settings.cache_render_pass_contents = true;
- scoped_ptr<LayerTreeHostImpl> my_host_impl =
- LayerTreeHostImpl::Create(settings,
- this,
- &proxy_,
- &stats_instrumentation_);
-
- // Layers are structured as follows:
- //
- // R +-- S1 +- L10 (rotated, drawing)
- // +- L11 (occupies half surface)
-
- LayerImpl* root_ptr;
- LayerImpl* layer_s1_ptr;
-
- scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
- scoped_ptr<TestWebGraphicsContext3D>(new PartialSwapContext)));
-
- gfx::Size root_size(1000, 1000);
-
- my_host_impl->InitializeRenderer(output_surface.Pass());
- my_host_impl->SetViewportSize(root_size);
-
- scoped_ptr<LayerImpl> root =
- LayerImpl::Create(my_host_impl->active_tree(), 1);
- root_ptr = root.get();
-
- root->SetAnchorPoint(gfx::PointF());
- root->SetPosition(gfx::PointF());
- root->SetBounds(root_size);
- root->SetContentBounds(root_size);
- root->SetDrawsContent(true);
- root->SetMasksToBounds(true);
- my_host_impl->active_tree()->SetRootLayer(root.Pass());
-
- AddDrawingLayerTo(root_ptr, 2, gfx::Rect(0, 0, 400, 400), &layer_s1_ptr);
- layer_s1_ptr->SetForceRenderSurface(true);
- gfx::Transform transform = layer_s1_ptr->transform();
- transform.Translate(200.0, 200.0);
- transform.Rotate(45.0);
- transform.Translate(-200.0, -200.0);
- layer_s1_ptr->SetTransform(transform);
-
- AddDrawingLayerTo(layer_s1_ptr, 3, gfx::Rect(200, 0, 200, 400), 0); // L11
-
- // Initial draw - must receive all quads
- {
- LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
-
- // Must receive 2 render passes.
- ASSERT_EQ(2U, frame.render_passes.size());
-
- EXPECT_EQ(2U, frame.render_passes[0]->quad_list.size());
- EXPECT_EQ(1U, frame.render_passes[1]->quad_list.size());
-
- my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
- my_host_impl->DidDrawAllLayers(frame);
- }
-
- // Change opacity and draw. Verify we used cached texture.
- layer_s1_ptr->SetOpacity(0.2f);
- {
- LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
-
- // One render pass must be gone due to cached texture.
- ASSERT_EQ(1U, frame.render_passes.size());
-
- EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
-
- my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
- my_host_impl->DidDrawAllLayers(frame);
- }
-}
-
-TEST_F(LayerTreeHostImplTest, TextureCachingWithOcclusionPartialSwap) {
- LayerTreeSettings settings;
- settings.minimum_occlusion_tracking_size = gfx::Size();
- settings.partial_swap_enabled = true;
- settings.cache_render_pass_contents = true;
- scoped_ptr<LayerTreeHostImpl> my_host_impl =
- LayerTreeHostImpl::Create(settings,
- this,
- &proxy_,
- &stats_instrumentation_);
-
- // Layers are structure as follows:
- //
- // R +-- S1 +- L10 (owning)
- // | +- L11
- // | +- L12
- // |
- // +-- S2 +- L20 (owning)
- // +- L21
- //
- // Occlusion:
- // L12 occludes L11 (internal)
- // L20 occludes L10 (external)
- // L21 occludes L20 (internal)
-
- LayerImpl* root_ptr;
- LayerImpl* layer_s1_ptr;
- LayerImpl* layer_s2_ptr;
-
- scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
- scoped_ptr<TestWebGraphicsContext3D>(new PartialSwapContext)));
-
- gfx::Size root_size(1000, 1000);
-
- my_host_impl->InitializeRenderer(output_surface.Pass());
- my_host_impl->SetViewportSize(root_size);
-
- scoped_ptr<LayerImpl> root =
- LayerImpl::Create(my_host_impl->active_tree(), 1);
- root_ptr = root.get();
-
- root->SetAnchorPoint(gfx::PointF());
- root->SetPosition(gfx::PointF());
- root->SetBounds(root_size);
- root->SetContentBounds(root_size);
- root->SetDrawsContent(true);
- root->SetMasksToBounds(true);
- my_host_impl->active_tree()->SetRootLayer(root.Pass());
-
- AddDrawingLayerTo(root_ptr, 2, gfx::Rect(300, 300, 300, 300), &layer_s1_ptr);
- layer_s1_ptr->SetForceRenderSurface(true);
-
- AddDrawingLayerTo(layer_s1_ptr, 3, gfx::Rect(10, 10, 10, 10), 0); // L11
- AddDrawingLayerTo(layer_s1_ptr, 4, gfx::Rect(0, 0, 30, 30), 0); // L12
-
- AddDrawingLayerTo(root_ptr, 5, gfx::Rect(550, 250, 300, 400), &layer_s2_ptr);
- layer_s2_ptr->SetForceRenderSurface(true);
-
- AddDrawingLayerTo(layer_s2_ptr, 6, gfx::Rect(20, 20, 5, 5), 0); // L21
-
- // Initial draw - must receive all quads
- {
- LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
-
- // Must receive 3 render passes.
- // For Root, there are 2 quads; for S1, there are 2 quads (one is occluded);
- // for S2, there is 2 quads.
- ASSERT_EQ(3U, frame.render_passes.size());
-
- EXPECT_EQ(2U, frame.render_passes[0]->quad_list.size());
- EXPECT_EQ(2U, frame.render_passes[1]->quad_list.size());
- EXPECT_EQ(2U, frame.render_passes[2]->quad_list.size());
-
- my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
- my_host_impl->DidDrawAllLayers(frame);
- }
-
- // "Unocclude" surface S1 and repeat draw.
- // Must remove S2's render pass since it's cached;
- // Must keep S1 quads because texture contained external occlusion.
- gfx::Transform transform = layer_s2_ptr->transform();
- transform.Translate(150.0, 150.0);
- layer_s2_ptr->SetTransform(transform);
- {
- LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
-
- // Must receive 2 render passes.
- // For Root, there are 2 quads.
- // For S1, there are 2 quads.
- // For S2, there is no render pass
- ASSERT_EQ(2U, frame.render_passes.size());
-
- EXPECT_EQ(2U, frame.render_passes[0]->quad_list.size());
- EXPECT_EQ(2U, frame.render_passes[1]->quad_list.size());
-
- my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
- my_host_impl->DidDrawAllLayers(frame);
- }
-
- // "Re-occlude" surface S1 and repeat draw.
- // Must remove S1's render pass since it is now available in full.
- // S2 has no change so must also be removed.
- transform = layer_s2_ptr->transform();
- transform.Translate(-15.0, -15.0);
- layer_s2_ptr->SetTransform(transform);
- {
- LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
-
- // Root render pass only.
- ASSERT_EQ(1U, frame.render_passes.size());
-
- my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
- my_host_impl->DidDrawAllLayers(frame);
- }
-}
-
-TEST_F(LayerTreeHostImplTest, TextureCachingWithScissor) {
- LayerTreeSettings settings;
- settings.minimum_occlusion_tracking_size = gfx::Size();
- settings.cache_render_pass_contents = true;
- scoped_ptr<LayerTreeHostImpl> my_host_impl =
- LayerTreeHostImpl::Create(settings,
- this,
- &proxy_,
- &stats_instrumentation_);
-
- /*
- Layers are created as follows:
-
- +--------------------+
- | 1 |
- | +-----------+ |
- | | 2 | |
- | | +-------------------+
- | | | 3 |
- | | +-------------------+
- | | | |
- | +-----------+ |
- | |
- | |
- +--------------------+
-
- Layers 1, 2 have render surfaces
- */
- scoped_ptr<LayerImpl> root =
- LayerImpl::Create(my_host_impl->active_tree(), 1);
- scoped_ptr<TiledLayerImpl> child =
- TiledLayerImpl::Create(my_host_impl->active_tree(), 2);
- scoped_ptr<LayerImpl> grand_child =
- LayerImpl::Create(my_host_impl->active_tree(), 3);
-
- gfx::Rect root_rect(0, 0, 100, 100);
- gfx::Rect child_rect(10, 10, 50, 50);
- gfx::Rect grand_child_rect(5, 5, 150, 150);
-
- scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
- scoped_ptr<TestWebGraphicsContext3D>(new PartialSwapContext)));
- my_host_impl->InitializeRenderer(output_surface.Pass());
-
- root->SetAnchorPoint(gfx::PointF());
- root->SetPosition(gfx::PointF(root_rect.x(), root_rect.y()));
- root->SetBounds(gfx::Size(root_rect.width(), root_rect.height()));
- root->SetContentBounds(root->bounds());
- root->SetDrawsContent(true);
- root->SetMasksToBounds(true);
-
- child->SetAnchorPoint(gfx::PointF());
- child->SetPosition(gfx::PointF(child_rect.x(), child_rect.y()));
- child->SetOpacity(0.5f);
- child->SetBounds(gfx::Size(child_rect.width(), child_rect.height()));
- child->SetContentBounds(child->bounds());
- child->SetDrawsContent(true);
- child->set_skips_draw(false);
-
- // child layer has 10x10 tiles.
- scoped_ptr<LayerTilingData> tiler =
- LayerTilingData::Create(gfx::Size(10, 10),
- LayerTilingData::HAS_BORDER_TEXELS);
- tiler->SetBounds(child->content_bounds());
- child->SetTilingData(*tiler.get());
-
- grand_child->SetAnchorPoint(gfx::PointF());
- grand_child->SetPosition(grand_child_rect.origin());
- grand_child->SetBounds(grand_child_rect.size());
- grand_child->SetContentBounds(grand_child->bounds());
- grand_child->SetDrawsContent(true);
-
- TiledLayerImpl* child_ptr = child.get();
- RenderPass::Id child_pass_id(child_ptr->id(), 0);
-
- child->AddChild(grand_child.Pass());
- root->AddChild(child.PassAs<LayerImpl>());
- my_host_impl->active_tree()->SetRootLayer(root.Pass());
- my_host_impl->SetViewportSize(root_rect.size());
-
- EXPECT_FALSE(my_host_impl->renderer()->HaveCachedResourcesForRenderPassId(
- child_pass_id));
- {
- LayerTreeHostImpl::FrameData frame;
- host_impl_->SetFullRootLayerDamage();
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
- my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
- my_host_impl->DidDrawAllLayers(frame);
- }
-
- // We should have cached textures for surface 2.
- EXPECT_TRUE(my_host_impl->renderer()->HaveCachedResourcesForRenderPassId(
- child_pass_id));
- {
- LayerTreeHostImpl::FrameData frame;
- host_impl_->SetFullRootLayerDamage();
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
- my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
- my_host_impl->DidDrawAllLayers(frame);
- }
-
- // We should still have cached textures for surface 2 after drawing with no
- // damage.
- EXPECT_TRUE(my_host_impl->renderer()->HaveCachedResourcesForRenderPassId(
- child_pass_id));
-
- // Damage a single tile of surface 2.
- child_ptr->set_update_rect(gfx::Rect(10, 10, 10, 10));
- {
- LayerTreeHostImpl::FrameData frame;
- host_impl_->SetFullRootLayerDamage();
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
- my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
- my_host_impl->DidDrawAllLayers(frame);
- }
-
- // We should have a cached texture for surface 2 again even though it was
- // damaged.
- EXPECT_TRUE(my_host_impl->renderer()->HaveCachedResourcesForRenderPassId(
- child_pass_id));
-}
-
-TEST_F(LayerTreeHostImplTest, SurfaceTextureCaching) {
- LayerTreeSettings settings;
- settings.minimum_occlusion_tracking_size = gfx::Size();
- settings.partial_swap_enabled = true;
- settings.cache_render_pass_contents = true;
- scoped_ptr<LayerTreeHostImpl> my_host_impl =
- LayerTreeHostImpl::Create(settings,
- this,
- &proxy_,
- &stats_instrumentation_);
-
- LayerImpl* root_ptr;
- LayerImpl* intermediate_layer_ptr;
- LayerImpl* surface_layer_ptr;
- LayerImpl* child_ptr;
-
- SetupLayersForTextureCaching(my_host_impl.get(),
- root_ptr,
- intermediate_layer_ptr,
- surface_layer_ptr,
- child_ptr,
- gfx::Size(100, 100));
- {
- LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
-
- // Must receive two render passes, each with one quad
- ASSERT_EQ(2U, frame.render_passes.size());
- EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
- EXPECT_EQ(1U, frame.render_passes[1]->quad_list.size());
-
- EXPECT_EQ(DrawQuad::RENDER_PASS,
- frame.render_passes[1]->quad_list[0]->material);
- const RenderPassDrawQuad* quad =
- RenderPassDrawQuad::MaterialCast(frame.render_passes[1]->quad_list[0]);
- RenderPass* target_pass = frame.render_passes_by_id[quad->render_pass_id];
- ASSERT_TRUE(target_pass);
- EXPECT_FALSE(target_pass->damage_rect.IsEmpty());
-
- my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
- my_host_impl->DidDrawAllLayers(frame);
- }
-
- // Draw without any change
- {
- LayerTreeHostImpl::FrameData frame;
- my_host_impl->SetFullRootLayerDamage();
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
-
- // Must receive one render pass, as the other one should be culled
- ASSERT_EQ(1U, frame.render_passes.size());
-
- EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
- EXPECT_EQ(DrawQuad::RENDER_PASS,
- frame.render_passes[0]->quad_list[0]->material);
- const RenderPassDrawQuad* quad =
- RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
- EXPECT_TRUE(frame.render_passes_by_id.find(quad->render_pass_id) ==
- frame.render_passes_by_id.end());
-
- my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
- my_host_impl->DidDrawAllLayers(frame);
- }
-
- // Change opacity and draw
- surface_layer_ptr->SetOpacity(0.6f);
- {
- LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
-
- // Must receive one render pass, as the other one should be culled
- ASSERT_EQ(1U, frame.render_passes.size());
-
- EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
- EXPECT_EQ(DrawQuad::RENDER_PASS,
- frame.render_passes[0]->quad_list[0]->material);
- const RenderPassDrawQuad* quad =
- RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
- EXPECT_TRUE(frame.render_passes_by_id.find(quad->render_pass_id) ==
- frame.render_passes_by_id.end());
-
- my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
- my_host_impl->DidDrawAllLayers(frame);
- }
-
- // Change less benign property and draw - should have contents changed flag
- surface_layer_ptr->SetStackingOrderChanged(true);
- {
- LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
-
- // Must receive two render passes, each with one quad
- ASSERT_EQ(2U, frame.render_passes.size());
-
- EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
- EXPECT_EQ(DrawQuad::SOLID_COLOR,
- frame.render_passes[0]->quad_list[0]->material);
-
- EXPECT_EQ(DrawQuad::RENDER_PASS,
- frame.render_passes[1]->quad_list[0]->material);
- const RenderPassDrawQuad* quad =
- RenderPassDrawQuad::MaterialCast(frame.render_passes[1]->quad_list[0]);
- RenderPass* target_pass = frame.render_passes_by_id[quad->render_pass_id];
- ASSERT_TRUE(target_pass);
- EXPECT_FALSE(target_pass->damage_rect.IsEmpty());
-
- my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
- my_host_impl->DidDrawAllLayers(frame);
- }
-
- // Change opacity again, and evict the cached surface texture.
- surface_layer_ptr->SetOpacity(0.5f);
- static_cast<GLRendererWithReleaseTextures*>(
- my_host_impl->renderer())->ReleaseRenderPassTextures();
-
- // Change opacity and draw
- surface_layer_ptr->SetOpacity(0.6f);
- {
- LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
-
- // Must receive two render passes
- ASSERT_EQ(2U, frame.render_passes.size());
-
- // Even though not enough properties changed, the entire thing must be
- // redrawn as we don't have cached textures
- EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
- EXPECT_EQ(1U, frame.render_passes[1]->quad_list.size());
-
- EXPECT_EQ(DrawQuad::RENDER_PASS,
- frame.render_passes[1]->quad_list[0]->material);
- const RenderPassDrawQuad* quad =
- RenderPassDrawQuad::MaterialCast(frame.render_passes[1]->quad_list[0]);
- RenderPass* target_pass = frame.render_passes_by_id[quad->render_pass_id];
- ASSERT_TRUE(target_pass);
- EXPECT_TRUE(target_pass->damage_rect.IsEmpty());
-
- // Was our surface evicted?
- EXPECT_FALSE(my_host_impl->renderer()->HaveCachedResourcesForRenderPassId(
- target_pass->id));
-
- my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
- my_host_impl->DidDrawAllLayers(frame);
- }
-
- // Draw without any change, to make sure the state is clear
- {
- LayerTreeHostImpl::FrameData frame;
- my_host_impl->SetFullRootLayerDamage();
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
-
- // Must receive one render pass, as the other one should be culled
- ASSERT_EQ(1U, frame.render_passes.size());
-
- EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
- EXPECT_EQ(DrawQuad::RENDER_PASS,
- frame.render_passes[0]->quad_list[0]->material);
- const RenderPassDrawQuad* quad =
- RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
- EXPECT_TRUE(frame.render_passes_by_id.find(quad->render_pass_id) ==
- frame.render_passes_by_id.end());
-
- my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
- my_host_impl->DidDrawAllLayers(frame);
- }
-
- // Change location of the intermediate layer
- gfx::Transform transform = intermediate_layer_ptr->transform();
- transform.matrix().setDouble(0, 3, 1.0001);
- intermediate_layer_ptr->SetTransform(transform);
- {
- LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
-
- // Must receive one render pass, as the other one should be culled.
- ASSERT_EQ(1U, frame.render_passes.size());
- EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
-
- EXPECT_EQ(DrawQuad::RENDER_PASS,
- frame.render_passes[0]->quad_list[0]->material);
- const RenderPassDrawQuad* quad =
- RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
- EXPECT_TRUE(frame.render_passes_by_id.find(quad->render_pass_id) ==
- frame.render_passes_by_id.end());
-
- my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
- my_host_impl->DidDrawAllLayers(frame);
- }
-}
-
-TEST_F(LayerTreeHostImplTest, SurfaceTextureCachingNoPartialSwap) {
- LayerTreeSettings settings;
- settings.minimum_occlusion_tracking_size = gfx::Size();
- settings.cache_render_pass_contents = true;
- scoped_ptr<LayerTreeHostImpl> my_host_impl =
- LayerTreeHostImpl::Create(settings,
- this,
- &proxy_,
- &stats_instrumentation_);
-
- LayerImpl* root_ptr;
- LayerImpl* intermediate_layer_ptr;
- LayerImpl* surface_layer_ptr;
- LayerImpl* child_ptr;
-
- SetupLayersForTextureCaching(my_host_impl.get(),
- root_ptr,
- intermediate_layer_ptr,
- surface_layer_ptr,
- child_ptr,
- gfx::Size(100, 100));
- {
- LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
-
- // Must receive two render passes, each with one quad
- ASSERT_EQ(2U, frame.render_passes.size());
- EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
- EXPECT_EQ(1U, frame.render_passes[1]->quad_list.size());
-
- EXPECT_EQ(DrawQuad::RENDER_PASS,
- frame.render_passes[1]->quad_list[0]->material);
- const RenderPassDrawQuad* quad =
- RenderPassDrawQuad::MaterialCast(frame.render_passes[1]->quad_list[0]);
- RenderPass* target_pass = frame.render_passes_by_id[quad->render_pass_id];
- EXPECT_FALSE(target_pass->damage_rect.IsEmpty());
-
- EXPECT_FALSE(frame.render_passes[0]->damage_rect.IsEmpty());
- EXPECT_FALSE(frame.render_passes[1]->damage_rect.IsEmpty());
-
- EXPECT_FALSE(
- frame.render_passes[0]->has_occlusion_from_outside_target_surface);
- EXPECT_FALSE(
- frame.render_passes[1]->has_occlusion_from_outside_target_surface);
-
- my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
- my_host_impl->DidDrawAllLayers(frame);
- }
-
- // Draw without any change
- {
- LayerTreeHostImpl::FrameData frame;
- my_host_impl->SetFullRootLayerDamage();
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
-
- // Even though there was no change, we set the damage to entire viewport.
- // One of the passes should be culled as a result, since contents didn't
- // change and we have cached texture.
- ASSERT_EQ(1U, frame.render_passes.size());
- EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
-
- my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
- my_host_impl->DidDrawAllLayers(frame);
- }
-
- // Change opacity and draw
- surface_layer_ptr->SetOpacity(0.6f);
- {
- LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
-
- // Must receive one render pass, as the other one should be culled
- ASSERT_EQ(1U, frame.render_passes.size());
-
- EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
- EXPECT_EQ(DrawQuad::RENDER_PASS,
- frame.render_passes[0]->quad_list[0]->material);
- const RenderPassDrawQuad* quad =
- RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
- EXPECT_TRUE(frame.render_passes_by_id.find(quad->render_pass_id) ==
- frame.render_passes_by_id.end());
-
- my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
- my_host_impl->DidDrawAllLayers(frame);
- }
-
- // Change less benign property and draw - should have contents changed flag
- surface_layer_ptr->SetStackingOrderChanged(true);
- {
- LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
-
- // Must receive two render passes, each with one quad
- ASSERT_EQ(2U, frame.render_passes.size());
-
- EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
- EXPECT_EQ(DrawQuad::SOLID_COLOR,
- frame.render_passes[0]->quad_list[0]->material);
-
- EXPECT_EQ(DrawQuad::RENDER_PASS,
- frame.render_passes[1]->quad_list[0]->material);
- const RenderPassDrawQuad* quad =
- RenderPassDrawQuad::MaterialCast(frame.render_passes[1]->quad_list[0]);
- RenderPass* target_pass = frame.render_passes_by_id[quad->render_pass_id];
- ASSERT_TRUE(target_pass);
- EXPECT_FALSE(target_pass->damage_rect.IsEmpty());
-
- my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
- my_host_impl->DidDrawAllLayers(frame);
- }
-
- // Change opacity again, and evict the cached surface texture.
- surface_layer_ptr->SetOpacity(0.5f);
- static_cast<GLRendererWithReleaseTextures*>(
- my_host_impl->renderer())->ReleaseRenderPassTextures();
-
- // Change opacity and draw
- surface_layer_ptr->SetOpacity(0.6f);
- {
- LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
-
- // Must receive two render passes
- ASSERT_EQ(2U, frame.render_passes.size());
-
- // Even though not enough properties changed, the entire thing must be
- // redrawn as we don't have cached textures
- EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
- EXPECT_EQ(1U, frame.render_passes[1]->quad_list.size());
-
- EXPECT_EQ(DrawQuad::RENDER_PASS,
- frame.render_passes[1]->quad_list[0]->material);
- const RenderPassDrawQuad* quad =
- RenderPassDrawQuad::MaterialCast(frame.render_passes[1]->quad_list[0]);
- RenderPass* target_pass = frame.render_passes_by_id[quad->render_pass_id];
- ASSERT_TRUE(target_pass);
- EXPECT_TRUE(target_pass->damage_rect.IsEmpty());
-
- // Was our surface evicted?
- EXPECT_FALSE(my_host_impl->renderer()->HaveCachedResourcesForRenderPassId(
- target_pass->id));
-
- my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
- my_host_impl->DidDrawAllLayers(frame);
- }
-
- // Draw without any change, to make sure the state is clear
- {
- LayerTreeHostImpl::FrameData frame;
- my_host_impl->SetFullRootLayerDamage();
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
-
- // Even though there was no change, we set the damage to entire viewport.
- // One of the passes should be culled as a result, since contents didn't
- // change and we have cached texture.
- ASSERT_EQ(1U, frame.render_passes.size());
- EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
-
- my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
- my_host_impl->DidDrawAllLayers(frame);
- }
-
- // Change location of the intermediate layer
- gfx::Transform transform = intermediate_layer_ptr->transform();
- transform.matrix().setDouble(0, 3, 1.0001);
- intermediate_layer_ptr->SetTransform(transform);
- {
- LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
-
- // Must receive one render pass, as the other one should be culled.
- ASSERT_EQ(1U, frame.render_passes.size());
- EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
-
- EXPECT_EQ(DrawQuad::RENDER_PASS,
- frame.render_passes[0]->quad_list[0]->material);
- const RenderPassDrawQuad* quad =
- RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
- EXPECT_TRUE(frame.render_passes_by_id.find(quad->render_pass_id) ==
- frame.render_passes_by_id.end());
-
- my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
- my_host_impl->DidDrawAllLayers(frame);
- }
-}
-
TEST_F(LayerTreeHostImplTest, ReleaseContentsTextureShouldTriggerCommit) {
set_reduce_memory_result(false);
@@ -4971,7 +3922,6 @@ TEST_F(LayerTreeHostImplTest, ReleaseContentsTextureShouldTriggerCommit) {
host_impl_->memory_allocation_limit_bytes() - 1);
host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
host_impl_->memory_allocation_limit_bytes() - 1));
- host_impl_->SetDiscardBackBufferWhenNotVisible(true);
EXPECT_FALSE(did_request_commit_);
did_request_commit_ = false;
@@ -4983,7 +3933,6 @@ TEST_F(LayerTreeHostImplTest, ReleaseContentsTextureShouldTriggerCommit) {
host_impl_->memory_allocation_limit_bytes());
host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
host_impl_->memory_allocation_limit_bytes() - 1));
- host_impl_->SetDiscardBackBufferWhenNotVisible(true);
EXPECT_TRUE(did_request_commit_);
did_request_commit_ = false;
@@ -4993,7 +3942,6 @@ TEST_F(LayerTreeHostImplTest, ReleaseContentsTextureShouldTriggerCommit) {
host_impl_->set_max_memory_needed_bytes(1);
host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
host_impl_->memory_allocation_limit_bytes() - 1));
- host_impl_->SetDiscardBackBufferWhenNotVisible(true);
EXPECT_TRUE(did_request_commit_);
did_request_commit_ = false;
@@ -5001,403 +3949,9 @@ TEST_F(LayerTreeHostImplTest, ReleaseContentsTextureShouldTriggerCommit) {
// re-commit.
host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
host_impl_->memory_allocation_limit_bytes()));
- host_impl_->SetDiscardBackBufferWhenNotVisible(true);
EXPECT_FALSE(did_request_commit_);
}
-struct RenderPassRemovalTestData : public LayerTreeHostImpl::FrameData {
- base::ScopedPtrHashMap<RenderPass::Id, TestRenderPass> render_pass_cache;
- scoped_ptr<SharedQuadState> shared_quad_state;
-};
-
-class TestRenderer : public GLRenderer, public RendererClient {
- public:
- static scoped_ptr<TestRenderer> Create(const LayerTreeSettings* settings,
- ResourceProvider* resource_provider,
- OutputSurface* output_surface,
- Proxy* proxy) {
- scoped_ptr<TestRenderer> renderer(
- new TestRenderer(settings, resource_provider, output_surface, proxy));
- if (!renderer->Initialize())
- return scoped_ptr<TestRenderer>();
-
- return renderer.Pass();
- }
-
- void ClearCachedTextures() { textures_.clear(); }
- void SetHaveCachedResourcesForRenderPassId(RenderPass::Id id) {
- textures_.insert(id);
- }
-
- virtual bool HaveCachedResourcesForRenderPassId(RenderPass::Id id) const
- OVERRIDE {
- return textures_.count(id);
- }
-
- // RendererClient implementation.
- virtual gfx::Rect DeviceViewport() const OVERRIDE {
- return gfx::Rect(viewport_size_);
- }
- virtual gfx::Rect DeviceClip() const OVERRIDE { return DeviceViewport(); }
- virtual void SetFullRootLayerDamage() OVERRIDE {}
- virtual CompositorFrameMetadata MakeCompositorFrameMetadata() const OVERRIDE {
- return CompositorFrameMetadata();
- }
-
- protected:
- TestRenderer(const LayerTreeSettings* settings,
- ResourceProvider* resource_provider,
- OutputSurface* output_surface,
- Proxy* proxy)
- : GLRenderer(this, settings, output_surface, resource_provider, NULL, 0) {
- }
-
- private:
- LayerTreeSettings settings_;
- gfx::Size viewport_size_;
- base::hash_set<RenderPass::Id> textures_;
-};
-
-static void ConfigureRenderPassTestData(const char* test_script,
- RenderPassRemovalTestData* test_data,
- TestRenderer* renderer) {
- renderer->ClearCachedTextures();
-
- // One shared state for all quads - we don't need the correct details
- test_data->shared_quad_state = SharedQuadState::Create();
- test_data->shared_quad_state->SetAll(gfx::Transform(),
- gfx::Size(),
- gfx::Rect(),
- gfx::Rect(),
- false,
- 1.f);
-
- const char* current_char = test_script;
-
- // Pre-create root pass
- RenderPass::Id root_render_pass_id =
- RenderPass::Id(test_script[0], test_script[1]);
- scoped_ptr<TestRenderPass> pass = TestRenderPass::Create();
- pass->SetNew(root_render_pass_id, gfx::Rect(), gfx::Rect(), gfx::Transform());
- test_data->render_pass_cache.add(root_render_pass_id, pass.Pass());
- while (*current_char) {
- int layer_id = *current_char;
- current_char++;
- ASSERT_TRUE(current_char);
- int index = *current_char;
- current_char++;
-
- RenderPass::Id render_pass_id = RenderPass::Id(layer_id, index);
-
- bool is_replica = false;
- if (!test_data->render_pass_cache.contains(render_pass_id))
- is_replica = true;
-
- scoped_ptr<TestRenderPass> render_pass =
- test_data->render_pass_cache.take(render_pass_id);
-
- // Cycle through quad data and create all quads.
- while (*current_char && *current_char != '\n') {
- if (*current_char == 's') {
- // Solid color draw quad.
- scoped_ptr<SolidColorDrawQuad> quad = SolidColorDrawQuad::Create();
- quad->SetNew(test_data->shared_quad_state.get(),
- gfx::Rect(0, 0, 10, 10),
- SK_ColorWHITE,
- false);
-
- render_pass->AppendQuad(quad.PassAs<DrawQuad>());
- current_char++;
- } else if ((*current_char >= 'A') && (*current_char <= 'Z')) {
- // RenderPass draw quad.
- int layer_id = *current_char;
- current_char++;
- ASSERT_TRUE(current_char);
- int index = *current_char;
- current_char++;
- RenderPass::Id new_render_pass_id = RenderPass::Id(layer_id, index);
- ASSERT_NE(root_render_pass_id, new_render_pass_id);
- bool has_texture = false;
- bool contents_changed = true;
-
- if (*current_char == '[') {
- current_char++;
- while (*current_char && *current_char != ']') {
- switch (*current_char) {
- case 'c':
- contents_changed = false;
- break;
- case 't':
- has_texture = true;
- break;
- }
- current_char++;
- }
- if (*current_char == ']')
- current_char++;
- }
-
- if (test_data->render_pass_cache.find(new_render_pass_id) ==
- test_data->render_pass_cache.end()) {
- if (has_texture)
- renderer->SetHaveCachedResourcesForRenderPassId(new_render_pass_id);
-
- scoped_ptr<TestRenderPass> pass = TestRenderPass::Create();
- pass->SetNew(new_render_pass_id,
- gfx::Rect(),
- gfx::Rect(),
- gfx::Transform());
- test_data->render_pass_cache.add(new_render_pass_id, pass.Pass());
- }
-
- gfx::Rect quad_rect = gfx::Rect(0, 0, 1, 1);
- gfx::Rect contents_changed_rect =
- contents_changed ? quad_rect : gfx::Rect();
- scoped_ptr<RenderPassDrawQuad> quad = RenderPassDrawQuad::Create();
- quad->SetNew(test_data->shared_quad_state.get(),
- quad_rect,
- new_render_pass_id,
- is_replica,
- 1,
- contents_changed_rect,
- gfx::RectF(0.f, 0.f, 1.f, 1.f),
- FilterOperations(),
- skia::RefPtr<SkImageFilter>(),
- FilterOperations());
- render_pass->AppendQuad(quad.PassAs<DrawQuad>());
- }
- }
- test_data->render_passes_by_id[render_pass_id] = render_pass.get();
- test_data->render_passes.insert(test_data->render_passes.begin(),
- render_pass.PassAs<RenderPass>());
- if (*current_char)
- current_char++;
- }
-}
-
-void DumpRenderPassTestData(const RenderPassRemovalTestData& test_data,
- char* buffer) {
- char* pos = buffer;
- for (RenderPassList::const_reverse_iterator it =
- test_data.render_passes.rbegin();
- it != test_data.render_passes.rend();
- ++it) {
- const RenderPass* current_pass = *it;
- *pos = current_pass->id.layer_id;
- pos++;
- *pos = current_pass->id.index;
- pos++;
-
- QuadList::const_iterator quad_list_iterator =
- current_pass->quad_list.begin();
- while (quad_list_iterator != current_pass->quad_list.end()) {
- DrawQuad* current_quad = *quad_list_iterator;
- switch (current_quad->material) {
- case DrawQuad::SOLID_COLOR:
- *pos = 's';
- pos++;
- break;
- case DrawQuad::RENDER_PASS:
- *pos = RenderPassDrawQuad::MaterialCast(current_quad)->
- render_pass_id.layer_id;
- pos++;
- *pos = RenderPassDrawQuad::MaterialCast(current_quad)->
- render_pass_id.index;
- pos++;
- break;
- default:
- *pos = 'x';
- pos++;
- break;
- }
-
- quad_list_iterator++;
- }
- *pos = '\n';
- pos++;
- }
- *pos = '\0';
-}
-
-// Each RenderPassList is represented by a string which describes the
-// configuration.
-// The syntax of the string is as follows:
-//
-// RsssssX[c]ssYsssZ[t]ssW[ct]
-// Identifies the render pass------------------------^ ^^^ ^ ^ ^ ^ ^
-// These are solid color quads--------------------------+ | | | | |
-// Identifies RenderPassDrawQuad's RenderPass--------------+ | | | |
-// This quad's contents didn't change------------------------+ | | |
-// This quad's contents changed and it has no texture------------+ | |
-// This quad has texture but its contents changed----------------------+ |
-// This quad's contents didn't change and it has texture - will be removed---+
-//
-// Expected results have exactly the same syntax, except they do not use square
-// brackets, since we only check the structure, not attributes.
-//
-// Test case configuration consists of initialization script and expected
-// results, all in the same format.
-struct TestCase {
- const char* name;
- const char* init_script;
- const char* expected_result;
-};
-
-TestCase remove_render_passes_cases[] = {
- {
- "Single root pass",
- "R0ssss\n",
- "R0ssss\n"
- }, {
- "Single pass - no quads",
- "R0\n",
- "R0\n"
- }, {
- "Two passes, no removal",
- "R0ssssA0sss\n"
- "A0ssss\n",
- "R0ssssA0sss\n"
- "A0ssss\n"
- }, {
- "Two passes, remove last",
- "R0ssssA0[ct]sss\n"
- "A0ssss\n",
- "R0ssssA0sss\n"
- }, {
- "Have texture but contents changed - leave pass",
- "R0ssssA0[t]sss\n"
- "A0ssss\n",
- "R0ssssA0sss\n"
- "A0ssss\n"
- }, {
- "Contents didn't change but no texture - leave pass",
- "R0ssssA0[c]sss\n"
- "A0ssss\n",
- "R0ssssA0sss\n"
- "A0ssss\n"
- }, {
- "Replica: two quads reference the same pass; remove",
- "R0ssssA0[ct]A0[ct]sss\n"
- "A0ssss\n",
- "R0ssssA0A0sss\n"
- }, {
- "Replica: two quads reference the same pass; leave",
- "R0ssssA0[c]A0[c]sss\n"
- "A0ssss\n",
- "R0ssssA0A0sss\n"
- "A0ssss\n",
- }, {
- "Many passes, remove all",
- "R0ssssA0[ct]sss\n"
- "A0sssB0[ct]C0[ct]s\n"
- "B0sssD0[ct]ssE0[ct]F0[ct]\n"
- "E0ssssss\n"
- "C0G0[ct]\n"
- "D0sssssss\n"
- "F0sssssss\n"
- "G0sss\n",
-
- "R0ssssA0sss\n"
- }, {
- "Deep recursion, remove all",
-
- "R0sssssA0[ct]ssss\n"
- "A0ssssB0sss\n"
- "B0C0\n"
- "C0D0\n"
- "D0E0\n"
- "E0F0\n"
- "F0G0\n"
- "G0H0\n"
- "H0sssI0sss\n"
- "I0J0\n"
- "J0ssss\n",
-
- "R0sssssA0ssss\n"
- }, {
- "Wide recursion, remove all",
- "R0A0[ct]B0[ct]C0[ct]D0[ct]E0[ct]F0[ct]G0[ct]H0[ct]I0[ct]J0[ct]\n"
- "A0s\n"
- "B0s\n"
- "C0ssss\n"
- "D0ssss\n"
- "E0s\n"
- "F0\n"
- "G0s\n"
- "H0s\n"
- "I0s\n"
- "J0ssss\n",
-
- "R0A0B0C0D0E0F0G0H0I0J0\n"
- }, {
- "Remove passes regardless of cache state",
- "R0ssssA0[ct]sss\n"
- "A0sssB0C0s\n"
- "B0sssD0[c]ssE0[t]F0\n"
- "E0ssssss\n"
- "C0G0\n"
- "D0sssssss\n"
- "F0sssssss\n"
- "G0sss\n",
-
- "R0ssssA0sss\n"
- }, {
- "Leave some passes, remove others",
-
- "R0ssssA0[c]sss\n"
- "A0sssB0[t]C0[ct]s\n"
- "B0sssD0[c]ss\n"
- "C0G0\n"
- "D0sssssss\n"
- "G0sss\n",
-
- "R0ssssA0sss\n"
- "A0sssB0C0s\n"
- "B0sssD0ss\n"
- "D0sssssss\n"
- }, {
- 0, 0, 0
- }
-};
-
-static void VerifyRenderPassTestData(
- const TestCase& test_case,
- const RenderPassRemovalTestData& test_data) {
- char actual_result[1024];
- DumpRenderPassTestData(test_data, actual_result);
- EXPECT_STREQ(test_case.expected_result, actual_result) << "In test case: " <<
- test_case.name;
-}
-
-TEST_F(LayerTreeHostImplTest, TestRemoveRenderPasses) {
- LayerTreeSettings settings;
- FakeOutputSurfaceClient output_surface_client;
- scoped_ptr<OutputSurface> output_surface(CreateOutputSurface());
- ASSERT_TRUE(output_surface->BindToClient(&output_surface_client));
- ASSERT_TRUE(output_surface->context_provider());
-
- scoped_ptr<ResourceProvider> resource_provider =
- ResourceProvider::Create(output_surface.get(), 0, false);
-
- scoped_ptr<TestRenderer> renderer = TestRenderer::Create(
- &settings, resource_provider.get(), output_surface.get(), &proxy_);
-
- int test_case_index = 0;
- while (remove_render_passes_cases[test_case_index].name) {
- RenderPassRemovalTestData test_data;
- ConfigureRenderPassTestData(
- remove_render_passes_cases[test_case_index].init_script,
- &test_data,
- renderer.get());
- LayerTreeHostImpl::RemoveRenderPasses(
- LayerTreeHostImpl::CullRenderPassesWithCachedTextures(renderer.get()),
- &test_data);
- VerifyRenderPassTestData(remove_render_passes_cases[test_case_index],
- test_data);
- test_case_index++;
- }
-}
-
class LayerTreeHostImplTestWithDelegatingRenderer
: public LayerTreeHostImplTest {
protected:
@@ -5436,7 +3990,7 @@ class LayerTreeHostImplTestWithDelegatingRenderer
root_render_pass->quad_list[1]->visible_rect);
}
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
EXPECT_EQ(expect_to_draw, host_impl_->SwapBuffers(frame));
}
@@ -5497,12 +4051,7 @@ class FakeMaskLayerImpl : public LayerImpl {
TEST_F(LayerTreeHostImplTest, MaskLayerWithScaling) {
LayerTreeSettings settings;
settings.layer_transforms_should_scale_layer_contents = true;
- host_impl_ = LayerTreeHostImpl::Create(settings,
- this,
- &proxy_,
- &stats_instrumentation_);
- host_impl_->InitializeRenderer(CreateOutputSurface());
- host_impl_->SetViewportSize(gfx::Size(10, 10));
+ CreateHostImpl(settings, CreateOutputSurface());
// Root
// |
@@ -5578,7 +4127,7 @@ TEST_F(LayerTreeHostImplTest, MaskLayerWithScaling) {
EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
render_pass_quad->mask_uv_rect.ToString());
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
@@ -5606,7 +4155,7 @@ TEST_F(LayerTreeHostImplTest, MaskLayerWithScaling) {
EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
render_pass_quad->mask_uv_rect.ToString());
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
@@ -5636,7 +4185,7 @@ TEST_F(LayerTreeHostImplTest, MaskLayerWithScaling) {
EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
render_pass_quad->mask_uv_rect.ToString());
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
}
@@ -5699,7 +4248,7 @@ TEST_F(LayerTreeHostImplTest, MaskLayerWithDifferentBounds) {
EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
render_pass_quad->mask_uv_rect.ToString());
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
@@ -5726,7 +4275,7 @@ TEST_F(LayerTreeHostImplTest, MaskLayerWithDifferentBounds) {
EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
render_pass_quad->mask_uv_rect.ToString());
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
@@ -5756,7 +4305,7 @@ TEST_F(LayerTreeHostImplTest, MaskLayerWithDifferentBounds) {
EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
render_pass_quad->mask_uv_rect.ToString());
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
@@ -5781,7 +4330,7 @@ TEST_F(LayerTreeHostImplTest, MaskLayerWithDifferentBounds) {
EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
render_pass_quad->mask_uv_rect.ToString());
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
}
@@ -5850,7 +4399,7 @@ TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerWithDifferentBounds) {
EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
replica_quad->mask_uv_rect.ToString());
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
@@ -5878,7 +4427,7 @@ TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerWithDifferentBounds) {
EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
replica_quad->mask_uv_rect.ToString());
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
@@ -5909,7 +4458,7 @@ TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerWithDifferentBounds) {
EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
replica_quad->mask_uv_rect.ToString());
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
@@ -5935,7 +4484,7 @@ TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerWithDifferentBounds) {
EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
replica_quad->mask_uv_rect.ToString());
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
}
@@ -6026,7 +4575,7 @@ TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerForSurfaceWithUnclippedChild) {
EXPECT_EQ(gfx::RectF(0.f, 0.f, 2.f, 1.f).ToString(),
replica_quad->mask_uv_rect.ToString());
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
@@ -6060,7 +4609,7 @@ TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerForSurfaceWithUnclippedChild) {
EXPECT_EQ(gfx::RectF(-1.f, 0.f, 2.f, 1.f).ToString(),
replica_quad->mask_uv_rect.ToString());
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
}
@@ -6156,7 +4705,7 @@ TEST_F(LayerTreeHostImplTest, MaskLayerForSurfaceWithClippedLayer) {
1.f / 50.f).ToString(),
render_pass_quad->mask_uv_rect.ToString());
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
}
@@ -6229,7 +4778,7 @@ TEST_F(LayerTreeHostImplTest, FarAwayQuadsDontNeedAA) {
quad->quadTransform(), quad, &device_layer_quad, edge);
EXPECT_FALSE(antialiased);
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
}
@@ -6279,13 +4828,14 @@ class CountingSoftwareDevice : public SoftwareOutputDevice {
TEST_F(LayerTreeHostImplTest, ForcedDrawToSoftwareDeviceBasicRender) {
// No main thread evictions in resourceless software mode.
set_reduce_memory_result(false);
- SetupScrollAndContentsLayers(gfx::Size(100, 100));
- host_impl_->SetViewportSize(gfx::Size(50, 50));
CountingSoftwareDevice* software_device = new CountingSoftwareDevice();
FakeOutputSurface* output_surface = FakeOutputSurface::CreateDeferredGL(
scoped_ptr<SoftwareOutputDevice>(software_device)).release();
- EXPECT_TRUE(host_impl_->InitializeRenderer(
- scoped_ptr<OutputSurface>(output_surface)));
+ EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
+ scoped_ptr<OutputSurface>(output_surface)));
+ host_impl_->SetViewportSize(gfx::Size(50, 50));
+
+ SetupScrollAndContentsLayers(gfx::Size(100, 100));
output_surface->set_forced_draw_to_software_device(true);
EXPECT_TRUE(output_surface->ForcedDrawToSoftwareDevice());
@@ -6308,8 +4858,8 @@ TEST_F(LayerTreeHostImplTest,
set_reduce_memory_result(false);
FakeOutputSurface* output_surface = FakeOutputSurface::CreateDeferredGL(
scoped_ptr<SoftwareOutputDevice>(new CountingSoftwareDevice())).release();
- host_impl_->InitializeRenderer(
- scoped_ptr<OutputSurface>(output_surface));
+ EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
+ scoped_ptr<OutputSurface>(output_surface)));
output_surface->set_forced_draw_to_software_device(true);
EXPECT_TRUE(output_surface->ForcedDrawToSoftwareDevice());
@@ -6330,7 +4880,7 @@ TEST_F(LayerTreeHostImplTest,
LayerTreeHostImpl::FrameData frame;
EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
EXPECT_EQ(1u, frame.will_draw_layers.size());
@@ -6349,8 +4899,8 @@ class LayerTreeHostImplTestDeferredInitialize : public LayerTreeHostImplTest {
scoped_ptr<SoftwareOutputDevice>(new CountingSoftwareDevice())));
output_surface_ = output_surface.get();
- EXPECT_TRUE(host_impl_->InitializeRenderer(
- output_surface.PassAs<OutputSurface>()));
+ EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
+ output_surface.PassAs<OutputSurface>()));
scoped_ptr<SolidColorLayerImpl> root_layer =
SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
@@ -6399,12 +4949,10 @@ TEST_F(LayerTreeHostImplTestDeferredInitialize, Fails_OnscreenContext_0) {
// Fail initialization of the onscreen context before the OutputSurface binds
// it to the thread.
- onscreen_context_provider_->UnboundTestContext3d()
- ->set_times_make_current_succeeds(0);
+ onscreen_context_provider_->UnboundTestContext3d()->set_context_lost(true);
EXPECT_FALSE(host_impl_->output_surface()->context_provider());
EXPECT_FALSE(host_impl_->offscreen_context_provider());
- EXPECT_FALSE(did_lose_output_surface_);
// DeferredInitialize fails.
EXPECT_FALSE(output_surface_->InitializeAndSetContext3d(
@@ -6420,78 +4968,58 @@ TEST_F(LayerTreeHostImplTestDeferredInitialize, Fails_OnscreenContext_1) {
// Software draw.
DrawFrame();
- // Fail initialization of the onscreen context after the OutputSurface binds
- // it to the thread.
- onscreen_context_provider_->UnboundTestContext3d()
- ->set_times_make_current_succeeds(2);
-
EXPECT_FALSE(host_impl_->output_surface()->context_provider());
EXPECT_FALSE(host_impl_->offscreen_context_provider());
- EXPECT_FALSE(did_lose_output_surface_);
+ onscreen_context_provider_->UnboundTestContext3d()->set_context_lost(true);
+
+ EXPECT_FALSE(host_impl_->output_surface()->context_provider());
// DeferredInitialize fails.
EXPECT_FALSE(output_surface_->InitializeAndSetContext3d(
onscreen_context_provider_, offscreen_context_provider_));
EXPECT_FALSE(host_impl_->output_surface()->context_provider());
EXPECT_FALSE(host_impl_->offscreen_context_provider());
-
- // We lose the output surface.
- EXPECT_TRUE(did_lose_output_surface_);
}
TEST_F(LayerTreeHostImplTestDeferredInitialize, Fails_OnscreenContext_2) {
// Software draw.
DrawFrame();
- // Fail initialization of the onscreen context after the OutputSurface binds
- // it to the thread and during renderer initialization.
- onscreen_context_provider_->UnboundTestContext3d()
- ->set_times_make_current_succeeds(1);
-
EXPECT_FALSE(host_impl_->output_surface()->context_provider());
EXPECT_FALSE(host_impl_->offscreen_context_provider());
- EXPECT_FALSE(did_lose_output_surface_);
+
+ onscreen_context_provider_->UnboundTestContext3d()->set_context_lost(true);
// DeferredInitialize fails.
EXPECT_FALSE(output_surface_->InitializeAndSetContext3d(
onscreen_context_provider_, offscreen_context_provider_));
EXPECT_FALSE(host_impl_->output_surface()->context_provider());
EXPECT_FALSE(host_impl_->offscreen_context_provider());
-
- // We lose the output surface.
- EXPECT_TRUE(did_lose_output_surface_);
}
TEST_F(LayerTreeHostImplTestDeferredInitialize, Fails_OffscreenContext) {
// Software draw.
DrawFrame();
- // Fail initialization of the offscreen context.
- offscreen_context_provider_->UnboundTestContext3d()
- ->set_times_make_current_succeeds(0);
-
EXPECT_FALSE(host_impl_->output_surface()->context_provider());
EXPECT_FALSE(host_impl_->offscreen_context_provider());
- EXPECT_FALSE(did_lose_output_surface_);
+
+ // Fail initialization of the offscreen context.
+ onscreen_context_provider_->UnboundTestContext3d()->set_context_lost(true);
// DeferredInitialize fails.
EXPECT_FALSE(output_surface_->InitializeAndSetContext3d(
onscreen_context_provider_, offscreen_context_provider_));
EXPECT_FALSE(host_impl_->output_surface()->context_provider());
EXPECT_FALSE(host_impl_->offscreen_context_provider());
-
- // We lose the output surface.
- EXPECT_TRUE(did_lose_output_surface_);
}
// Checks that we have a non-0 default allocation if we pass a context that
// doesn't support memory management extensions.
TEST_F(LayerTreeHostImplTest, DefaultMemoryAllocation) {
LayerTreeSettings settings;
- host_impl_ = LayerTreeHostImpl::Create(settings,
- this,
- &proxy_,
- &stats_instrumentation_);
+ host_impl_ = LayerTreeHostImpl::Create(
+ settings, this, &proxy_, &stats_instrumentation_, NULL, 0);
scoped_ptr<OutputSurface> output_surface(
FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create()));
@@ -6501,25 +5029,24 @@ TEST_F(LayerTreeHostImplTest, DefaultMemoryAllocation) {
TEST_F(LayerTreeHostImplTest, MemoryPolicy) {
ManagedMemoryPolicy policy1(
- 456, ManagedMemoryPolicy::CUTOFF_ALLOW_EVERYTHING,
- 123, ManagedMemoryPolicy::CUTOFF_ALLOW_NICE_TO_HAVE, 1000);
- int visible_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue(
- policy1.priority_cutoff_when_visible);
- int not_visible_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue(
- policy1.priority_cutoff_when_not_visible);
+ 456, gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING, 1000);
+ int everything_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue(
+ gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING);
+ int nothing_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue(
+ gpu::MemoryAllocation::CUTOFF_ALLOW_NOTHING);
host_impl_->SetVisible(true);
host_impl_->SetMemoryPolicy(policy1);
EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
- EXPECT_EQ(visible_cutoff_value, current_priority_cutoff_value_);
+ EXPECT_EQ(everything_cutoff_value, current_priority_cutoff_value_);
host_impl_->SetVisible(false);
- EXPECT_EQ(policy1.bytes_limit_when_not_visible, current_limit_bytes_);
- EXPECT_EQ(not_visible_cutoff_value, current_priority_cutoff_value_);
+ EXPECT_EQ(0u, current_limit_bytes_);
+ EXPECT_EQ(nothing_cutoff_value, current_priority_cutoff_value_);
host_impl_->SetVisible(true);
EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
- EXPECT_EQ(visible_cutoff_value, current_priority_cutoff_value_);
+ EXPECT_EQ(everything_cutoff_value, current_priority_cutoff_value_);
}
class LayerTreeHostImplTestManageTiles : public LayerTreeHostImplTest {
@@ -6549,7 +5076,7 @@ TEST_F(LayerTreeHostImplTest, UIResourceManagement) {
TestWebGraphicsContext3D::Create();
TestWebGraphicsContext3D* context3d = context.get();
scoped_ptr<OutputSurface> output_surface = CreateFakeOutputSurface();
- host_impl_->InitializeRenderer(output_surface.Pass());
+ CreateHostImpl(DefaultSettings(), output_surface.Pass());
EXPECT_EQ(0u, context3d->NumTextures());
@@ -6593,6 +5120,28 @@ TEST_F(LayerTreeHostImplTest, UIResourceManagement) {
EXPECT_EQ(0u, context3d->NumTextures());
}
+TEST_F(LayerTreeHostImplTest, CreateETC1UIResource) {
+ scoped_ptr<TestWebGraphicsContext3D> context =
+ TestWebGraphicsContext3D::Create();
+ TestWebGraphicsContext3D* context3d = context.get();
+ scoped_ptr<OutputSurface> output_surface = CreateFakeOutputSurface();
+ CreateHostImpl(DefaultSettings(), output_surface.Pass());
+
+ EXPECT_EQ(0u, context3d->NumTextures());
+
+ scoped_ptr<uint8_t[]> pixels(new uint8_t[8]);
+ skia::RefPtr<ETC1PixelRef> etc1_pixel_ref =
+ skia::AdoptRef(new ETC1PixelRef(pixels.Pass()));
+ UIResourceBitmap bitmap(etc1_pixel_ref, gfx::Size(4, 4));
+
+ UIResourceId ui_resource_id = 1;
+ host_impl_->CreateUIResource(ui_resource_id, bitmap);
+ EXPECT_EQ(1u, context3d->NumTextures());
+ ResourceProvider::ResourceId id1 =
+ host_impl_->ResourceIdForUIResource(ui_resource_id);
+ EXPECT_NE(0u, id1);
+}
+
void ShutdownReleasesContext_Callback(scoped_ptr<CopyOutputResult> result) {
}
@@ -6600,13 +5149,9 @@ TEST_F(LayerTreeHostImplTest, ShutdownReleasesContext) {
scoped_refptr<TestContextProvider> context_provider =
TestContextProvider::Create();
- host_impl_ = LayerTreeHostImpl::Create(LayerTreeSettings(),
- this,
- &proxy_,
- &stats_instrumentation_);
- host_impl_->InitializeRenderer(
+ CreateHostImpl(
+ DefaultSettings(),
FakeOutputSurface::Create3d(context_provider).PassAs<OutputSurface>());
- host_impl_->SetViewportSize(gfx::Size(10, 10));
SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
@@ -6618,7 +5163,7 @@ TEST_F(LayerTreeHostImplTest, ShutdownReleasesContext) {
LayerTreeHostImpl::FrameData frame;
EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
- host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
host_impl_->DidDrawAllLayers(frame);
// The CopyOutputResult's callback has a ref on the ContextProvider and a
@@ -6634,5 +5179,241 @@ TEST_F(LayerTreeHostImplTest, ShutdownReleasesContext) {
EXPECT_EQ(0u, context_provider->TestContext3d()->NumTextures());
}
+TEST_F(LayerTreeHostImplTest, TouchFlingShouldNotBubble) {
+ // When flinging via touch, only the child should scroll (we should not
+ // bubble).
+ gfx::Size surface_size(10, 10);
+ gfx::Size content_size(20, 20);
+ scoped_ptr<LayerImpl> root = CreateScrollableLayer(1, content_size);
+ scoped_ptr<LayerImpl> child = CreateScrollableLayer(2, content_size);
+
+ root->AddChild(child.Pass());
+
+ host_impl_->SetViewportSize(surface_size);
+ host_impl_->active_tree()->SetRootLayer(root.Pass());
+ host_impl_->active_tree()->DidBecomeActive();
+ DrawFrame();
+ {
+ EXPECT_EQ(InputHandler::ScrollStarted,
+ host_impl_->ScrollBegin(gfx::Point(),
+ InputHandler::Gesture));
+
+ EXPECT_EQ(InputHandler::ScrollStarted,
+ host_impl_->FlingScrollBegin());
+
+ gfx::Vector2d scroll_delta(0, 100);
+ host_impl_->ScrollBy(gfx::Point(), scroll_delta);
+ host_impl_->ScrollBy(gfx::Point(), scroll_delta);
+
+ host_impl_->ScrollEnd();
+
+ scoped_ptr<ScrollAndScaleSet> scroll_info =
+ host_impl_->ProcessScrollDeltas();
+
+ // Only the child should have scrolled.
+ ASSERT_EQ(1u, scroll_info->scrolls.size());
+ ExpectNone(*scroll_info.get(),
+ host_impl_->active_tree()->root_layer()->id());
+ }
+}
+
+TEST_F(LayerTreeHostImplTest, TouchFlingShouldBubbleIfPrecedingScrollBubbled) {
+ // When flinging via touch, bubble scrolls if the touch scroll
+ // immediately preceding the fling bubbled.
+ gfx::Size surface_size(10, 10);
+ gfx::Size root_content_size(10, 20);
+ gfx::Size child_content_size(40, 40);
+ scoped_ptr<LayerImpl> root = CreateScrollableLayer(1, root_content_size);
+ scoped_ptr<LayerImpl> child = CreateScrollableLayer(2, child_content_size);
+
+ root->AddChild(child.Pass());
+
+ host_impl_->SetViewportSize(surface_size);
+ host_impl_->active_tree()->SetRootLayer(root.Pass());
+ host_impl_->active_tree()->DidBecomeActive();
+ DrawFrame();
+ {
+ EXPECT_EQ(InputHandler::ScrollStarted,
+ host_impl_->ScrollBegin(gfx::Point(),
+ InputHandler::Gesture));
+
+ // Touch scroll before starting the fling. The second scroll should bubble.
+ EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 100)));
+ EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 5)));
+
+ scoped_ptr<ScrollAndScaleSet> scroll_info =
+ host_impl_->ProcessScrollDeltas();
+
+ // The root should have (partially) scrolled.
+ EXPECT_EQ(2u, scroll_info->scrolls.size());
+ ExpectContains(*scroll_info.get(),
+ host_impl_->active_tree()->root_layer()->id(),
+ gfx::Vector2d(0, 5));
+
+ EXPECT_EQ(InputHandler::ScrollStarted,
+ host_impl_->FlingScrollBegin());
+
+ EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 5)));
+ host_impl_->ScrollEnd();
+
+ // The root should have (fully) scrolled from the fling.
+ scroll_info = host_impl_->ProcessScrollDeltas();
+ EXPECT_EQ(2u, scroll_info->scrolls.size());
+ ExpectContains(*scroll_info.get(),
+ host_impl_->active_tree()->root_layer()->id(),
+ gfx::Vector2d(0, 10));
+ }
+}
+
+TEST_F(LayerTreeHostImplTest, WheelFlingShouldBubble) {
+ // When flinging via wheel, the root should eventually scroll (we should
+ // bubble).
+ gfx::Size surface_size(10, 10);
+ gfx::Size content_size(20, 20);
+ scoped_ptr<LayerImpl> root = CreateScrollableLayer(1, content_size);
+ scoped_ptr<LayerImpl> child = CreateScrollableLayer(2, content_size);
+
+ root->AddChild(child.Pass());
+
+ host_impl_->SetViewportSize(surface_size);
+ host_impl_->active_tree()->SetRootLayer(root.Pass());
+ host_impl_->active_tree()->DidBecomeActive();
+ DrawFrame();
+ {
+ EXPECT_EQ(InputHandler::ScrollStarted,
+ host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
+
+ EXPECT_EQ(InputHandler::ScrollStarted,
+ host_impl_->FlingScrollBegin());
+
+ gfx::Vector2d scroll_delta(0, 100);
+ host_impl_->ScrollBy(gfx::Point(), scroll_delta);
+ host_impl_->ScrollBy(gfx::Point(), scroll_delta);
+
+ host_impl_->ScrollEnd();
+
+ scoped_ptr<ScrollAndScaleSet> scroll_info =
+ host_impl_->ProcessScrollDeltas();
+
+ // The root should have scrolled.
+ ASSERT_EQ(2u, scroll_info->scrolls.size());
+ ExpectContains(*scroll_info.get(),
+ host_impl_->active_tree()->root_layer()->id(),
+ gfx::Vector2d(0, 10));
+ }
+}
+
+// Make sure LatencyInfo carried by LatencyInfoSwapPromise are passed
+// to CompositorFrameMetadata after SwapBuffers();
+TEST_F(LayerTreeHostImplTest, LatencyInfoPassedToCompositorFrameMetadata) {
+ scoped_ptr<SolidColorLayerImpl> root =
+ SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
+ root->SetAnchorPoint(gfx::PointF());
+ root->SetPosition(gfx::PointF());
+ root->SetBounds(gfx::Size(10, 10));
+ root->SetContentBounds(gfx::Size(10, 10));
+ root->SetDrawsContent(true);
+
+ host_impl_->active_tree()->SetRootLayer(root.PassAs<LayerImpl>());
+
+ FakeOutputSurface* fake_output_surface =
+ static_cast<FakeOutputSurface*>(host_impl_->output_surface());
+
+ const ui::LatencyInfo& metadata_latency_before =
+ fake_output_surface->last_sent_frame().metadata.latency_info;
+ EXPECT_FALSE(metadata_latency_before.FindLatency(
+ ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, NULL));
+
+ ui::LatencyInfo latency_info;
+ latency_info.AddLatencyNumber(
+ 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_->SetNeedsRedraw();
+
+ gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
+ LayerTreeHostImpl::FrameData frame;
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
+ host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
+ host_impl_->DidDrawAllLayers(frame);
+ EXPECT_TRUE(host_impl_->SwapBuffers(frame));
+
+ const ui::LatencyInfo& metadata_latency_after =
+ fake_output_surface->last_sent_frame().metadata.latency_info;
+ EXPECT_TRUE(metadata_latency_after.FindLatency(
+ ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, NULL));
+}
+
+class SimpleSwapPromiseMonitor : public SwapPromiseMonitor {
+ public:
+ SimpleSwapPromiseMonitor(LayerTreeHost* layer_tree_host,
+ LayerTreeHostImpl* layer_tree_host_impl,
+ int* set_needs_commit_count,
+ int* set_needs_redraw_count)
+ : SwapPromiseMonitor(layer_tree_host, layer_tree_host_impl),
+ set_needs_commit_count_(set_needs_commit_count),
+ set_needs_redraw_count_(set_needs_redraw_count) {}
+
+ virtual ~SimpleSwapPromiseMonitor() {}
+
+ virtual void OnSetNeedsCommitOnMain() OVERRIDE {
+ (*set_needs_commit_count_)++;
+ }
+
+ virtual void OnSetNeedsRedrawOnImpl() OVERRIDE {
+ (*set_needs_redraw_count_)++;
+ }
+
+ private:
+ int* set_needs_commit_count_;
+ int* set_needs_redraw_count_;
+};
+
+TEST_F(LayerTreeHostImplTest, SimpleSwapPromiseMonitor) {
+ int set_needs_commit_count = 0;
+ int set_needs_redraw_count = 0;
+
+ {
+ scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
+ new SimpleSwapPromiseMonitor(NULL,
+ host_impl_.get(),
+ &set_needs_commit_count,
+ &set_needs_redraw_count));
+ host_impl_->SetNeedsRedraw();
+ EXPECT_EQ(0, set_needs_commit_count);
+ EXPECT_EQ(1, set_needs_redraw_count);
+ }
+
+ // Now the monitor is destroyed, SetNeedsRedraw() is no longer being
+ // monitored.
+ host_impl_->SetNeedsRedraw();
+ EXPECT_EQ(0, set_needs_commit_count);
+ EXPECT_EQ(1, set_needs_redraw_count);
+
+ {
+ scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
+ new SimpleSwapPromiseMonitor(NULL,
+ host_impl_.get(),
+ &set_needs_commit_count,
+ &set_needs_redraw_count));
+ host_impl_->SetNeedsRedrawRect(gfx::Rect(10, 10));
+ EXPECT_EQ(0, set_needs_commit_count);
+ EXPECT_EQ(2, set_needs_redraw_count);
+ }
+
+ {
+ scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
+ new SimpleSwapPromiseMonitor(NULL,
+ host_impl_.get(),
+ &set_needs_commit_count,
+ &set_needs_redraw_count));
+ // Empty damage rect won't signal the monitor.
+ host_impl_->SetNeedsRedrawRect(gfx::Rect());
+ EXPECT_EQ(0, set_needs_commit_count);
+ EXPECT_EQ(2, set_needs_redraw_count);
+ }
+}
+
} // namespace
} // namespace cc
diff --git a/chromium/cc/trees/layer_tree_host_perftest.cc b/chromium/cc/trees/layer_tree_host_perftest.cc
index 5ca78b64d49..1bfe1c49d9e 100644
--- a/chromium/cc/trees/layer_tree_host_perftest.cc
+++ b/chromium/cc/trees/layer_tree_host_perftest.cc
@@ -4,6 +4,8 @@
#include "cc/trees/layer_tree_host.h"
+#include <sstream>
+
#include "base/file_util.h"
#include "base/files/file_path.h"
#include "base/path_service.h"
@@ -12,6 +14,8 @@
#include "cc/layers/content_layer.h"
#include "cc/layers/nine_patch_layer.h"
#include "cc/layers/solid_color_layer.h"
+#include "cc/layers/texture_layer.h"
+#include "cc/resources/texture_mailbox.h"
#include "cc/test/fake_content_layer_client.h"
#include "cc/test/lap_timer.h"
#include "cc/test/layer_tree_json_parser.h"
@@ -40,6 +44,10 @@ class LayerTreeHostPerfTest : public LayerTreeTest {
fake_content_layer_client_.set_paint_all_opaque(true);
}
+ virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
+ settings->throttle_frame_production = false;
+ }
+
virtual void BeginTest() OVERRIDE {
BuildTree();
PostSetNeedsCommitToMainThread();
@@ -62,12 +70,11 @@ class LayerTreeHostPerfTest : public LayerTreeTest {
}
virtual void DrawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE {
- if (TestEnded()) {
+ if (TestEnded() || CleanUpStarted())
return;
- }
draw_timer_.NextLap();
if (draw_timer_.HasTimeLimitExpired()) {
- EndTest();
+ CleanUpAndEndTest(impl);
return;
}
if (!animation_driven_drawing_)
@@ -76,17 +83,17 @@ class LayerTreeHostPerfTest : public LayerTreeTest {
impl->SetFullRootLayerDamage();
}
+ virtual void CleanUpAndEndTest(LayerTreeHostImpl* host_impl) { EndTest(); }
+
+ virtual bool CleanUpStarted() { return false; }
+
virtual void BuildTree() {}
virtual void AfterTest() OVERRIDE {
CHECK(!test_name_.empty()) << "Must SetTestName() before AfterTest().";
- perf_test::PrintResult("layer_tree_host_frame_count", "", test_name_,
- draw_timer_.NumLaps(), "frame_count", true);
perf_test::PrintResult("layer_tree_host_frame_time", "", test_name_,
1000 * draw_timer_.MsPerLap(), "us", true);
if (measure_commit_cost_) {
- perf_test::PrintResult("layer_tree_host_commit_count", "", test_name_,
- commit_timer_.NumLaps(), "commit_count", true);
perf_test::PrintResult("layer_tree_host_commit_time", "", test_name_,
1000 * commit_timer_.MsPerLap(), "us", true);
}
@@ -117,7 +124,7 @@ class LayerTreeHostPerfTestJsonReader : public LayerTreeHostPerfTest {
void ReadTestFile(const std::string& name) {
base::FilePath test_data_dir;
- ASSERT_TRUE(PathService::Get(cc::DIR_TEST_DATA, &test_data_dir));
+ ASSERT_TRUE(PathService::Get(CCPaths::DIR_TEST_DATA, &test_data_dir));
base::FilePath json_file = test_data_dir.AppendASCII(name + ".json");
ASSERT_TRUE(base::ReadFileToString(json_file, &json_));
}
@@ -142,6 +149,12 @@ TEST_F(LayerTreeHostPerfTestJsonReader, TenTenSingleThread) {
RunTest(false, false, false);
}
+TEST_F(LayerTreeHostPerfTestJsonReader, TenTenThreadedImplSide) {
+ SetTestName("10_10_threaded_impl_side");
+ ReadTestFile("10_10_layer_tree");
+ RunTestWithImplSidePainting();
+}
+
// Simulates a tab switcher scene with two stacks of 10 tabs each.
TEST_F(LayerTreeHostPerfTestJsonReader,
TenTenSingleThread_FullDamageEachFrame) {
@@ -151,6 +164,14 @@ TEST_F(LayerTreeHostPerfTestJsonReader,
RunTest(false, false, false);
}
+TEST_F(LayerTreeHostPerfTestJsonReader,
+ TenTenThreadedImplSide_FullDamageEachFrame) {
+ full_damage_each_frame_ = true;
+ SetTestName("10_10_threaded_impl_side_full_damage_each_frame");
+ ReadTestFile("10_10_layer_tree");
+ RunTestWithImplSidePainting();
+}
+
// Invalidates a leaf layer in the tree on the main thread after every commit.
class LayerTreeHostPerfTestLeafInvalidates
: public LayerTreeHostPerfTestJsonReader {
@@ -185,6 +206,12 @@ TEST_F(LayerTreeHostPerfTestLeafInvalidates, TenTenSingleThread) {
RunTest(false, false, false);
}
+TEST_F(LayerTreeHostPerfTestLeafInvalidates, TenTenThreadedImplSide) {
+ SetTestName("10_10_threaded_impl_side_leaf_invalidates");
+ ReadTestFile("10_10_layer_tree");
+ RunTestWithImplSidePainting();
+}
+
// Simulates main-thread scrolling on each frame.
class ScrollingLayerTreePerfTest : public LayerTreeHostPerfTestJsonReader {
public:
@@ -207,20 +234,93 @@ class ScrollingLayerTreePerfTest : public LayerTreeHostPerfTestJsonReader {
scoped_refptr<Layer> scrollable_;
};
-TEST_F(ScrollingLayerTreePerfTest, LongScrollablePage) {
+TEST_F(ScrollingLayerTreePerfTest, LongScrollablePageSingleThread) {
SetTestName("long_scrollable_page");
ReadTestFile("long_scrollable_page");
RunTest(false, false, false);
}
-class ImplSidePaintingPerfTest : public LayerTreeHostPerfTestJsonReader {
- protected:
- // Run test with impl-side painting.
- void RunTestWithImplSidePainting() { RunTest(true, false, true); }
+TEST_F(ScrollingLayerTreePerfTest, LongScrollablePageThreadedImplSide) {
+ SetTestName("long_scrollable_page_threaded_impl_side");
+ ReadTestFile("long_scrollable_page");
+ RunTestWithImplSidePainting();
+}
+
+static void EmptyReleaseCallback(unsigned sync_point, bool lost_resource) {}
+
+// Simulates main-thread scrolling on each frame.
+class BrowserCompositorInvalidateLayerTreePerfTest
+ : public LayerTreeHostPerfTestJsonReader {
+ public:
+ BrowserCompositorInvalidateLayerTreePerfTest()
+ : next_sync_point_(1), clean_up_started_(false) {}
+
+ virtual void BuildTree() OVERRIDE {
+ LayerTreeHostPerfTestJsonReader::BuildTree();
+ tab_contents_ =
+ static_cast<TextureLayer*>(
+ layer_tree_host()->root_layer()->children()[0]->
+ children()[0]->
+ children()[0]->
+ children()[0].get());
+ ASSERT_TRUE(tab_contents_.get());
+ }
+
+ virtual void WillCommit() OVERRIDE {
+ gpu::Mailbox gpu_mailbox;
+ std::ostringstream name_stream;
+ name_stream << "name" << next_sync_point_;
+ gpu_mailbox.SetName(
+ reinterpret_cast<const int8*>(name_stream.str().c_str()));
+ scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
+ base::Bind(&EmptyReleaseCallback));
+ TextureMailbox mailbox(gpu_mailbox, next_sync_point_);
+ next_sync_point_++;
+
+ tab_contents_->SetTextureMailbox(mailbox, callback.Pass());
+ }
+
+ virtual void DidCommit() OVERRIDE {
+ if (CleanUpStarted())
+ return;
+ layer_tree_host()->SetNeedsCommit();
+ }
+
+ virtual void DidCommitAndDrawFrame() OVERRIDE {
+ if (CleanUpStarted())
+ EndTest();
+ }
+
+ virtual void CleanUpAndEndTest(LayerTreeHostImpl* host_impl) OVERRIDE {
+ clean_up_started_ = true;
+ MainThreadTaskRunner()->PostTask(
+ FROM_HERE,
+ base::Bind(&BrowserCompositorInvalidateLayerTreePerfTest::
+ CleanUpAndEndTestOnMainThread,
+ base::Unretained(this)));
+ }
+
+ void CleanUpAndEndTestOnMainThread() {
+ tab_contents_->SetTextureMailbox(TextureMailbox(),
+ scoped_ptr<SingleReleaseCallback>());
+ }
+
+ virtual bool CleanUpStarted() OVERRIDE { return clean_up_started_; }
+
+ private:
+ scoped_refptr<TextureLayer> tab_contents_;
+ unsigned next_sync_point_;
+ bool clean_up_started_;
};
+TEST_F(BrowserCompositorInvalidateLayerTreePerfTest, DenseBrowserUI) {
+ SetTestName("dense_layer_tree");
+ ReadTestFile("dense_layer_tree");
+ RunTestWithImplSidePainting();
+}
+
// Simulates a page with several large, transformed and animated layers.
-TEST_F(ImplSidePaintingPerfTest, HeavyPage) {
+TEST_F(LayerTreeHostPerfTestJsonReader, HeavyPageThreadedImplSide) {
animation_driven_drawing_ = true;
measure_commit_cost_ = true;
SetTestName("heavy_page");
@@ -228,7 +328,8 @@ TEST_F(ImplSidePaintingPerfTest, HeavyPage) {
RunTestWithImplSidePainting();
}
-class PageScaleImplSidePaintingPerfTest : public ImplSidePaintingPerfTest {
+class PageScaleImplSidePaintingPerfTest
+ : public LayerTreeHostPerfTestJsonReader {
public:
PageScaleImplSidePaintingPerfTest()
: max_scale_(16.f), min_scale_(1.f / max_scale_) {}
diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc b/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc
new file mode 100644
index 00000000000..7a492a1d5bf
--- /dev/null
+++ b/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc
@@ -0,0 +1,120 @@
+// 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/solid_color_layer.h"
+#include "cc/layers/texture_layer.h"
+#include "cc/test/layer_tree_pixel_test.h"
+
+#if !defined(OS_ANDROID)
+
+namespace cc {
+namespace {
+
+SkXfermode::Mode const kBlendModes[] = {
+ SkXfermode::kSrcOver_Mode, SkXfermode::kScreen_Mode,
+ SkXfermode::kOverlay_Mode, SkXfermode::kDarken_Mode,
+ SkXfermode::kLighten_Mode, SkXfermode::kColorDodge_Mode,
+ SkXfermode::kColorBurn_Mode, SkXfermode::kHardLight_Mode,
+ SkXfermode::kSoftLight_Mode, SkXfermode::kDifference_Mode,
+ SkXfermode::kExclusion_Mode, SkXfermode::kMultiply_Mode,
+ SkXfermode::kHue_Mode, SkXfermode::kSaturation_Mode,
+ SkXfermode::kColor_Mode, SkXfermode::kLuminosity_Mode};
+
+const int kBlendModesCount = arraysize(kBlendModes);
+
+class LayerTreeHostBlendingPixelTest : public LayerTreePixelTest {
+ protected:
+ void RunBlendingWithRootPixelTestType(PixelTestType type) {
+ const int kLaneWidth = 15;
+ const int kLaneHeight = kBlendModesCount * kLaneWidth;
+ const int kRootSize = (kBlendModesCount + 2) * kLaneWidth;
+
+ scoped_refptr<SolidColorLayer> background =
+ CreateSolidColorLayer(gfx::Rect(kRootSize, kRootSize), kCSSOrange);
+
+ // Orange child layers will blend with the green background
+ for (int i = 0; i < kBlendModesCount; ++i) {
+ gfx::Rect child_rect(
+ (i + 1) * kLaneWidth, kLaneWidth, kLaneWidth, kLaneHeight);
+ scoped_refptr<SolidColorLayer> green_lane =
+ CreateSolidColorLayer(child_rect, kCSSGreen);
+ background->AddChild(green_lane);
+ green_lane->SetBlendMode(kBlendModes[i]);
+ }
+
+ RunPixelTest(type,
+ background,
+ base::FilePath(FILE_PATH_LITERAL("blending_with_root.png")));
+ }
+
+ void RunBlendingWithTransparentPixelTestType(PixelTestType type) {
+ const int kLaneWidth = 15;
+ const int kLaneHeight = kBlendModesCount * kLaneWidth;
+ const int kRootSize = (kBlendModesCount + 2) * kLaneWidth;
+
+ scoped_refptr<SolidColorLayer> root =
+ CreateSolidColorLayer(gfx::Rect(kRootSize, kRootSize), kCSSBrown);
+
+ scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer(
+ gfx::Rect(0, kLaneWidth * 2, kRootSize, kLaneWidth), kCSSOrange);
+
+ root->AddChild(background);
+ background->SetIsRootForIsolatedGroup(true);
+
+ // Orange child layers will blend with the green background
+ for (int i = 0; i < kBlendModesCount; ++i) {
+ gfx::Rect child_rect(
+ (i + 1) * kLaneWidth, -kLaneWidth, kLaneWidth, kLaneHeight);
+ scoped_refptr<SolidColorLayer> green_lane =
+ CreateSolidColorLayer(child_rect, kCSSGreen);
+ background->AddChild(green_lane);
+ green_lane->SetBlendMode(kBlendModes[i]);
+ }
+
+ RunPixelTest(type,
+ root,
+ base::FilePath(FILE_PATH_LITERAL("blending_transparent.png")));
+ }
+};
+
+TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithRoot_GL) {
+ RunBlendingWithRootPixelTestType(GL_WITH_BITMAP);
+}
+
+TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithBackgroundFilter) {
+ const int kLaneWidth = 15;
+ const int kLaneHeight = kBlendModesCount * kLaneWidth;
+ const int kRootSize = (kBlendModesCount + 2) * kLaneWidth;
+
+ scoped_refptr<SolidColorLayer> background =
+ CreateSolidColorLayer(gfx::Rect(kRootSize, kRootSize), kCSSOrange);
+
+ // Orange child layers have a background filter set and they will blend with
+ // the green background
+ for (int i = 0; i < kBlendModesCount; ++i) {
+ gfx::Rect child_rect(
+ (i + 1) * kLaneWidth, kLaneWidth, kLaneWidth, kLaneHeight);
+ scoped_refptr<SolidColorLayer> green_lane =
+ CreateSolidColorLayer(child_rect, kCSSGreen);
+ background->AddChild(green_lane);
+
+ FilterOperations filters;
+ filters.Append(FilterOperation::CreateGrayscaleFilter(.75));
+ green_lane->SetBackgroundFilters(filters);
+ green_lane->SetBlendMode(kBlendModes[i]);
+ }
+
+ RunPixelTest(GL_WITH_BITMAP,
+ background,
+ base::FilePath(FILE_PATH_LITERAL("blending_and_filter.png")));
+}
+
+TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithTransparent_GL) {
+ RunBlendingWithTransparentPixelTestType(GL_WITH_BITMAP);
+}
+
+} // namespace
+} // namespace cc
+
+#endif // OS_ANDROID
diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_filters.cc b/chromium/cc/trees/layer_tree_host_pixeltest_filters.cc
index 7068b4b1047..d2a6507f940 100644
--- a/chromium/cc/trees/layer_tree_host_pixeltest_filters.cc
+++ b/chromium/cc/trees/layer_tree_host_pixeltest_filters.cc
@@ -129,8 +129,8 @@ TEST_F(LayerTreeHostFiltersPixelTest, BackgroundFilterBlurOffAxis) {
blur->SetBackgroundFilters(filters);
#if defined(OS_WIN)
- // Windows has 151 pixels off by at most 2: crbug.com/225027
- float percentage_pixels_large_error = 0.3775f; // 151px / (200*200)
+ // 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;
@@ -150,49 +150,58 @@ TEST_F(LayerTreeHostFiltersPixelTest, BackgroundFilterBlurOffAxis) {
"background_filter_blur_off_axis.png")));
}
-TEST_F(LayerTreeHostFiltersPixelTest, ImageFilterClipped) {
- scoped_refptr<SolidColorLayer> root = CreateSolidColorLayer(
- gfx::Rect(200, 200), SK_ColorBLACK);
-
- scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer(
- gfx::Rect(200, 200), SK_ColorYELLOW);
- root->AddChild(background);
-
- scoped_refptr<SolidColorLayer> foreground = CreateSolidColorLayer(
- gfx::Rect(200, 200), SK_ColorRED);
- background->AddChild(foreground);
-
- SkScalar matrix[20];
- memset(matrix, 0, 20 * sizeof(matrix[0]));
- // This filter does a red-blue swap, so the foreground becomes blue.
- matrix[2] = matrix[6] = matrix[10] = matrix[18] = SK_Scalar1;
- skia::RefPtr<SkColorFilter> colorFilter(skia::AdoptRef(
- new SkColorMatrixFilter(matrix)));
- // We filter only the bottom 200x100 pixels of the foreground.
- SkIRect cropRect = SkIRect::MakeXYWH(0, 100, 200, 100);
- skia::RefPtr<SkImageFilter> filter =
- skia::AdoptRef(SkColorFilterImageFilter::Create(
- colorFilter.get(),
- NULL,
- &cropRect));
-
- // Make the foreground layer's render surface be clipped by the background
- // layer.
- background->SetMasksToBounds(true);
- foreground->SetFilter(filter);
-
- // Then we translate the foreground up by 100 pixels in Y, so the cropped
- // region is moved to to the top. This ensures that the crop rect is being
- // correctly transformed in skia by the amount of clipping that the
- // compositor performs.
- gfx::Transform transform;
- transform.Translate(0.0, -100.0);
- foreground->SetTransform(transform);
+class ImageFilterClippedPixelTest : public LayerTreeHostFiltersPixelTest {
+ protected:
+ void RunPixelTestType(PixelTestType test_type) {
+ scoped_refptr<SolidColorLayer> root =
+ CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorBLACK);
+
+ scoped_refptr<SolidColorLayer> background =
+ CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorYELLOW);
+ root->AddChild(background);
+
+ scoped_refptr<SolidColorLayer> foreground =
+ CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorRED);
+ background->AddChild(foreground);
+
+ SkScalar matrix[20];
+ memset(matrix, 0, 20 * sizeof(matrix[0]));
+ // This filter does a red-blue swap, so the foreground becomes blue.
+ matrix[2] = matrix[6] = matrix[10] = matrix[18] = SK_Scalar1;
+ skia::RefPtr<SkColorFilter> colorFilter(
+ skia::AdoptRef(new SkColorMatrixFilter(matrix)));
+ // We filter only the bottom 200x100 pixels of the foreground.
+ SkImageFilter::CropRect crop_rect(SkRect::MakeXYWH(0, 100, 200, 100));
+ skia::RefPtr<SkImageFilter> filter = skia::AdoptRef(
+ SkColorFilterImageFilter::Create(colorFilter.get(), NULL, &crop_rect));
+ FilterOperations filters;
+ filters.Append(FilterOperation::CreateReferenceFilter(filter));
+
+ // Make the foreground layer's render surface be clipped by the background
+ // layer.
+ background->SetMasksToBounds(true);
+ foreground->SetFilters(filters);
+
+ // Then we translate the foreground up by 100 pixels in Y, so the cropped
+ // region is moved to to the top. This ensures that the crop rect is being
+ // correctly transformed in skia by the amount of clipping that the
+ // compositor performs.
+ gfx::Transform transform;
+ transform.Translate(0.0, -100.0);
+ foreground->SetTransform(transform);
+
+ RunPixelTest(test_type,
+ background,
+ base::FilePath(FILE_PATH_LITERAL("blue_yellow.png")));
+ }
+};
+
+TEST_F(ImageFilterClippedPixelTest, ImageFilterClipped_GL) {
+ RunPixelTestType(GL_WITH_BITMAP);
+}
- RunPixelTest(GL_WITH_BITMAP,
- background,
- base::FilePath(FILE_PATH_LITERAL(
- "blue_yellow.png")));
+TEST_F(ImageFilterClippedPixelTest, ImageFilterClipped_Software) {
+ RunPixelTestType(SOFTWARE_WITH_BITMAP);
}
} // namespace
diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc b/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc
index 90570ec0b64..1d4f893d7d0 100644
--- a/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc
+++ b/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc
@@ -58,6 +58,7 @@ TEST_F(LayerTreeHostMasksPixelTest, MaskOfLayer) {
mask->SetIsMask(true);
green->SetMaskLayer(mask.get());
+ this->impl_side_painting_ = false;
RunPixelTest(GL_WITH_BITMAP,
background,
base::FilePath(FILE_PATH_LITERAL("mask_of_layer.png")));
@@ -88,6 +89,7 @@ TEST_F(LayerTreeHostMasksPixelTest, ImageMaskOfLayer) {
green->SetMaskLayer(mask.get());
background->AddChild(green);
+ this->impl_side_painting_ = false;
RunPixelTest(GL_WITH_BITMAP,
background,
base::FilePath(FILE_PATH_LITERAL("image_mask_of_layer.png")));
@@ -116,6 +118,7 @@ TEST_F(LayerTreeHostMasksPixelTest, MaskOfClippedLayer) {
mask->SetIsMask(true);
green->SetMaskLayer(mask.get());
+ this->impl_side_painting_ = false;
RunPixelTest(GL_WITH_BITMAP,
background,
base::FilePath(FILE_PATH_LITERAL("mask_of_clipped_layer.png")));
@@ -145,6 +148,7 @@ TEST_F(LayerTreeHostMasksPixelTest, MaskWithReplica) {
replica->SetTransform(replica_transform);
green->SetReplicaLayer(replica.get());
+ this->impl_side_painting_ = false;
RunPixelTest(GL_WITH_BITMAP,
background,
base::FilePath(FILE_PATH_LITERAL("mask_with_replica.png")));
@@ -183,6 +187,7 @@ TEST_F(LayerTreeHostMasksPixelTest, MaskWithReplicaOfClippedLayer) {
replica->SetTransform(replica_transform);
green->SetReplicaLayer(replica.get());
+ this->impl_side_painting_ = false;
RunPixelTest(GL_WITH_BITMAP,
background,
base::FilePath(FILE_PATH_LITERAL(
@@ -218,6 +223,7 @@ TEST_F(LayerTreeHostMasksPixelTest, MaskOfReplica) {
replica->SetMaskLayer(mask.get());
green->SetReplicaLayer(replica.get());
+ this->impl_side_painting_ = false;
RunPixelTest(GL_WITH_BITMAP,
background,
base::FilePath(FILE_PATH_LITERAL("mask_of_replica.png")));
@@ -260,6 +266,7 @@ TEST_F(LayerTreeHostMasksPixelTest, MaskOfReplicaOfClippedLayer) {
replica->SetMaskLayer(mask.get());
green->SetReplicaLayer(replica.get());
+ this->impl_side_painting_ = false;
RunPixelTest(GL_WITH_BITMAP,
background,
base::FilePath(FILE_PATH_LITERAL(
diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_on_demand_raster.cc b/chromium/cc/trees/layer_tree_host_pixeltest_on_demand_raster.cc
index a1990b01d5b..eaa97492c65 100644
--- a/chromium/cc/trees/layer_tree_host_pixeltest_on_demand_raster.cc
+++ b/chromium/cc/trees/layer_tree_host_pixeltest_on_demand_raster.cc
@@ -29,10 +29,8 @@ class LayerTreeHostOnDemandRasterPixelTest : public LayerTreePixelTest {
virtual void BeginCommitOnThread(LayerTreeHostImpl* impl) OVERRIDE {
// Not enough memory available. Enforce on-demand rasterization.
impl->SetMemoryPolicy(
- ManagedMemoryPolicy(1, ManagedMemoryPolicy::CUTOFF_ALLOW_EVERYTHING,
- 1, ManagedMemoryPolicy::CUTOFF_ALLOW_NOTHING,
+ ManagedMemoryPolicy(1, gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING,
1000));
- impl->SetDiscardBackBufferWhenNotVisible(true);
}
virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_readback.cc b/chromium/cc/trees/layer_tree_host_pixeltest_readback.cc
index d8e286183f5..e5bfcd24599 100644
--- a/chromium/cc/trees/layer_tree_host_pixeltest_readback.cc
+++ b/chromium/cc/trees/layer_tree_host_pixeltest_readback.cc
@@ -679,6 +679,7 @@ TEST_F(LayerTreeHostReadbackDeviceScalePixelTest,
copy_subrect_ = gfx::Rect(25, 25, 50, 50);
device_scale_factor_ = 2.f;
+ this->impl_side_painting_ = false;
RunPixelTest(SOFTWARE_WITH_DEFAULT,
background,
base::FilePath(FILE_PATH_LITERAL(
@@ -709,6 +710,7 @@ TEST_F(LayerTreeHostReadbackDeviceScalePixelTest,
copy_subrect_ = gfx::Rect(25, 25, 50, 50);
device_scale_factor_ = 2.f;
+ this->impl_side_painting_ = false;
RunPixelTest(GL_WITH_DEFAULT,
background,
base::FilePath(FILE_PATH_LITERAL(
@@ -740,6 +742,7 @@ TEST_F(LayerTreeHostReadbackDeviceScalePixelTest,
copy_subrect_ = gfx::Rect(25, 25, 50, 50);
device_scale_factor_ = 2.f;
+ this->impl_side_painting_ = false;
RunPixelTestWithReadbackTarget(SOFTWARE_WITH_DEFAULT,
background,
green.get(),
@@ -772,6 +775,7 @@ TEST_F(LayerTreeHostReadbackDeviceScalePixelTest,
copy_subrect_ = gfx::Rect(25, 25, 50, 50);
device_scale_factor_ = 2.f;
+ this->impl_side_painting_ = false;
RunPixelTestWithReadbackTarget(GL_WITH_DEFAULT,
background,
green.get(),
@@ -870,6 +874,7 @@ TEST_F(LayerTreeHostReadbackViaCompositeAndReadbackPixelTest,
device_viewport_copy_subrect_ = gfx::Rect(50, 50, 100, 100);
device_scale_factor_ = 1.f;
+ this->impl_side_painting_ = false;
RunPixelTestWithReadbackTarget(SOFTWARE_WITH_DEFAULT,
background,
green.get(),
@@ -901,6 +906,7 @@ TEST_F(LayerTreeHostReadbackViaCompositeAndReadbackPixelTest,
device_viewport_copy_subrect_ = gfx::Rect(50, 50, 100, 100);
device_scale_factor_ = 2.f;
+ this->impl_side_painting_ = false;
RunPixelTestWithReadbackTarget(SOFTWARE_WITH_DEFAULT,
background,
green.get(),
@@ -932,6 +938,7 @@ TEST_F(LayerTreeHostReadbackViaCompositeAndReadbackPixelTest,
device_viewport_copy_subrect_ = gfx::Rect(50, 50, 100, 100);
device_scale_factor_ = 1.f;
+ this->impl_side_painting_ = false;
RunPixelTestWithReadbackTarget(GL_WITH_DEFAULT,
background,
green.get(),
@@ -963,6 +970,7 @@ TEST_F(LayerTreeHostReadbackViaCompositeAndReadbackPixelTest,
device_viewport_copy_subrect_ = gfx::Rect(50, 50, 100, 100);
device_scale_factor_ = 2.f;
+ this->impl_side_painting_ = false;
RunPixelTestWithReadbackTarget(GL_WITH_DEFAULT,
background,
green.get(),
@@ -992,46 +1000,6 @@ TEST_F(LayerTreeHostReadbackPixelTest, ReadbackNonRootLayerOutsideViewport) {
"green_with_blue_corner.png")));
}
-// TextureLayers are clipped differently than SolidColorLayers, verify they
-// also can be copied when outside of the viewport.
-TEST_F(LayerTreeHostReadbackPixelTest,
- ReadbackNonRootTextureLayerOutsideViewport) {
- scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer(
- gfx::Rect(200, 200), SK_ColorWHITE);
-
- SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kARGB_8888_Config, 200, 200);
- bitmap.allocPixels();
- bitmap.eraseColor(SK_ColorGREEN);
- {
- SkBitmapDevice device(bitmap);
- skia::RefPtr<SkCanvas> canvas = skia::AdoptRef(new SkCanvas(&device));
- SkPaint paint;
- paint.setStyle(SkPaint::kFill_Style);
- paint.setColor(SK_ColorBLUE);
- canvas->drawRect(SkRect::MakeXYWH(150, 150, 50, 50), paint);
- }
-
- scoped_refptr<TextureLayer> texture = CreateTextureLayer(
- gfx::Rect(200, 200), bitmap);
-
- // Tests with solid color layers verify correctness when CanClipSelf is false.
- EXPECT_FALSE(background->CanClipSelf());
- // This test verifies correctness when CanClipSelf is true.
- EXPECT_TRUE(texture->CanClipSelf());
-
- // Only the top left quarter of the layer is inside the viewport, so the
- // blue corner is entirely outside.
- texture->SetPosition(gfx::Point(100, 100));
- background->AddChild(texture);
-
- RunPixelTestWithReadbackTarget(GL_WITH_DEFAULT,
- background,
- texture.get(),
- base::FilePath(FILE_PATH_LITERAL(
- "green_with_blue_corner.png")));
-}
-
} // namespace
} // namespace cc
diff --git a/chromium/cc/trees/layer_tree_host_single_thread_client.h b/chromium/cc/trees/layer_tree_host_single_thread_client.h
new file mode 100644
index 00000000000..cb6145048e6
--- /dev/null
+++ b/chromium/cc/trees/layer_tree_host_single_thread_client.h
@@ -0,0 +1,33 @@
+// 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_TREES_LAYER_TREE_HOST_SINGLE_THREAD_CLIENT_H_
+#define CC_TREES_LAYER_TREE_HOST_SINGLE_THREAD_CLIENT_H_
+
+namespace cc {
+
+class LayerTreeHostSingleThreadClient {
+ public:
+ // Request that the client schedule a composite.
+ virtual void ScheduleComposite() = 0;
+ // Request that the client schedule a composite now, and calculate appropriate
+ // delay for potential future frame.
+ virtual void ScheduleAnimation() = 0;
+
+ // Called whenever the compositor posts a SwapBuffers (either full or
+ // partial). After DidPostSwapBuffers(), exactly one of
+ // DidCompleteSwapBuffers() or DidAbortSwapBuffers() will be called, thus
+ // these functions can be used to keep track of pending swap buffers calls for
+ // rate limiting.
+ virtual void DidPostSwapBuffers() = 0;
+ virtual void DidCompleteSwapBuffers() = 0;
+ virtual void DidAbortSwapBuffers() = 0;
+
+ protected:
+ virtual ~LayerTreeHostSingleThreadClient() {}
+};
+
+} // namespace cc
+
+#endif // CC_TREES_LAYER_TREE_HOST_SINGLE_THREAD_CLIENT_H_
diff --git a/chromium/cc/trees/layer_tree_host_unittest.cc b/chromium/cc/trees/layer_tree_host_unittest.cc
index 92cba325587..0ac203a9a9e 100644
--- a/chromium/cc/trees/layer_tree_host_unittest.cc
+++ b/chromium/cc/trees/layer_tree_host_unittest.cc
@@ -9,8 +9,8 @@
#include "base/auto_reset.h"
#include "base/synchronization/lock.h"
#include "cc/animation/timing_function.h"
+#include "cc/base/swap_promise.h"
#include "cc/debug/frame_rate_counter.h"
-#include "cc/debug/test_web_graphics_context_3d.h"
#include "cc/layers/content_layer.h"
#include "cc/layers/content_layer_client.h"
#include "cc/layers/io_surface_layer.h"
@@ -29,6 +29,7 @@
#include "cc/scheduler/frame_rate_controller.h"
#include "cc/test/fake_content_layer.h"
#include "cc/test/fake_content_layer_client.h"
+#include "cc/test/fake_content_layer_impl.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"
@@ -40,6 +41,7 @@
#include "cc/test/geometry_test_utils.h"
#include "cc/test/layer_tree_test.h"
#include "cc/test/occlusion_tracker_test_common.h"
+#include "cc/test/test_web_graphics_context_3d.h"
#include "cc/trees/layer_tree_host_impl.h"
#include "cc/trees/layer_tree_impl.h"
#include "cc/trees/single_thread_proxy.h"
@@ -50,6 +52,7 @@
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/khronos/GLES2/gl2ext.h"
#include "third_party/skia/include/core/SkPicture.h"
+#include "ui/gfx/frame_time.h"
#include "ui/gfx/point_conversions.h"
#include "ui/gfx/size_conversions.h"
#include "ui/gfx/vector2d_conversions.h"
@@ -636,6 +639,194 @@ class LayerTreeHostTestCompositeAndReadbackAfterForcedDraw
MULTI_THREAD_TEST_F(LayerTreeHostTestCompositeAndReadbackAfterForcedDraw);
+class LayerTreeHostTestSetNextCommitForcesRedraw : public LayerTreeHostTest {
+ public:
+ LayerTreeHostTestSetNextCommitForcesRedraw()
+ : num_draws_(0),
+ bounds_(50, 50),
+ invalid_rect_(10, 10, 20, 20),
+ root_layer_(ContentLayer::Create(&client_)) {
+ }
+
+ virtual void BeginTest() OVERRIDE {
+ root_layer_->SetIsDrawable(true);
+ root_layer_->SetBounds(bounds_);
+ layer_tree_host()->SetRootLayer(root_layer_);
+ layer_tree_host()->SetViewportSize(bounds_);
+ PostSetNeedsCommitToMainThread();
+ }
+
+ virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
+ if (num_draws_ == 3 && host_impl->settings().impl_side_painting)
+ host_impl->SetNeedsRedrawRect(invalid_rect_);
+ }
+
+ virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
+ LayerTreeHostImpl::FrameData* frame_data,
+ bool result) OVERRIDE {
+ EXPECT_TRUE(result);
+
+ gfx::RectF root_damage_rect;
+ if (!frame_data->render_passes.empty())
+ root_damage_rect = frame_data->render_passes.back()->damage_rect;
+
+ switch (num_draws_) {
+ case 0:
+ EXPECT_RECT_EQ(gfx::Rect(bounds_), root_damage_rect);
+ break;
+ case 1:
+ case 2:
+ EXPECT_RECT_EQ(gfx::Rect(0, 0, 0, 0), root_damage_rect);
+ break;
+ case 3:
+ EXPECT_RECT_EQ(invalid_rect_, root_damage_rect);
+ break;
+ case 4:
+ EXPECT_RECT_EQ(gfx::Rect(bounds_), root_damage_rect);
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ return result;
+ }
+
+ virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
+ switch (num_draws_) {
+ case 0:
+ case 1:
+ // Cycle through a couple of empty commits to ensure we're observing the
+ // right behavior
+ PostSetNeedsCommitToMainThread();
+ break;
+ case 2:
+ // Should force full frame damage on the next commit
+ PostSetNextCommitForcesRedrawToMainThread();
+ PostSetNeedsCommitToMainThread();
+ if (host_impl->settings().impl_side_painting)
+ host_impl->BlockNotifyReadyToActivateForTesting(true);
+ else
+ num_draws_++;
+ break;
+ case 3:
+ host_impl->BlockNotifyReadyToActivateForTesting(false);
+ break;
+ default:
+ EndTest();
+ break;
+ }
+ num_draws_++;
+ }
+
+ virtual void AfterTest() OVERRIDE {
+ EXPECT_EQ(5, num_draws_);
+ }
+
+ private:
+ int num_draws_;
+ const gfx::Size bounds_;
+ const gfx::Rect invalid_rect_;
+ FakeContentLayerClient client_;
+ scoped_refptr<ContentLayer> root_layer_;
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestSetNextCommitForcesRedraw);
+
+// Tests that if a layer is not drawn because of some reason in the parent then
+// its damage is preserved until the next time it is drawn.
+class LayerTreeHostTestUndrawnLayersDamageLater : public LayerTreeHostTest {
+ public:
+ LayerTreeHostTestUndrawnLayersDamageLater()
+ : root_layer_(ContentLayer::Create(&client_)) {
+ }
+
+ virtual void SetupTree() OVERRIDE {
+ root_layer_->SetIsDrawable(true);
+ root_layer_->SetBounds(gfx::Size(50, 50));
+ layer_tree_host()->SetRootLayer(root_layer_);
+
+ // The initially transparent layer has a larger child layer, which is
+ // not initially drawn because of the this (parent) layer.
+ parent_layer_ = FakeContentLayer::Create(&client_);
+ parent_layer_->SetBounds(gfx::Size(15, 15));
+ parent_layer_->SetOpacity(0.0f);
+ root_layer_->AddChild(parent_layer_);
+
+ child_layer_ = FakeContentLayer::Create(&client_);
+ child_layer_->SetBounds(gfx::Size(25, 25));
+ parent_layer_->AddChild(child_layer_);
+
+ LayerTreeHostTest::SetupTree();
+ }
+
+ virtual void BeginTest() OVERRIDE {
+ PostSetNeedsCommitToMainThread();
+ }
+
+ virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
+ LayerTreeHostImpl::FrameData* frame_data,
+ bool result) OVERRIDE {
+ EXPECT_TRUE(result);
+
+ gfx::RectF root_damage_rect;
+ if (!frame_data->render_passes.empty())
+ root_damage_rect = frame_data->render_passes.back()->damage_rect;
+
+ // The first time, the whole view needs be drawn.
+ // Afterwards, just the opacity of surface_layer1 is changed a few times,
+ // and each damage should be the bounding box of it and its child. If this
+ // was working improperly, the damage might not include its childs bounding
+ // box.
+ switch (layer_tree_host()->source_frame_number()) {
+ case 1:
+ EXPECT_RECT_EQ(gfx::Rect(root_layer_->bounds()), root_damage_rect);
+ break;
+ case 2:
+ case 3:
+ case 4:
+ EXPECT_RECT_EQ(gfx::Rect(child_layer_->bounds()), root_damage_rect);
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ return result;
+ }
+
+ virtual void DidCommitAndDrawFrame() OVERRIDE {
+ switch (layer_tree_host()->source_frame_number()) {
+ case 1:
+ // Test not owning the surface.
+ parent_layer_->SetOpacity(1.0f);
+ break;
+ case 2:
+ parent_layer_->SetOpacity(0.0f);
+ break;
+ case 3:
+ // Test owning the surface.
+ parent_layer_->SetOpacity(0.5f);
+ parent_layer_->SetForceRenderSurface(true);
+ break;
+ case 4:
+ EndTest();
+ break;
+ default:
+ NOTREACHED();
+ }
+ }
+
+
+ virtual void AfterTest() OVERRIDE {}
+
+ private:
+ FakeContentLayerClient client_;
+ scoped_refptr<ContentLayer> root_layer_;
+ scoped_refptr<FakeContentLayer> parent_layer_;
+ scoped_refptr<FakeContentLayer> child_layer_;
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestUndrawnLayersDamageLater);
+
// If the layerTreeHost says it can't draw, Then we should not try to draw.
class LayerTreeHostTestCanDrawBlocksDrawing : public LayerTreeHostTest {
public:
@@ -842,16 +1033,31 @@ class LayerTreeHostTestFrameTimeUpdatesAfterActivationFails
PostSetNeedsCommitToMainThread();
}
- virtual void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl,
+ virtual void BeginCommitOnThread(LayerTreeHostImpl *impl) OVERRIDE {
+ EXPECT_EQ(frame_count_with_pending_tree_, 0);
+ impl->BlockNotifyReadyToActivateForTesting(true);
+ }
+
+ virtual void WillBeginImplFrameOnThread(LayerTreeHostImpl* impl,
const BeginFrameArgs& args) OVERRIDE {
- if (host_impl->pending_tree())
+ if (impl->pending_tree())
frame_count_with_pending_tree_++;
- host_impl->BlockNotifyReadyToActivateForTesting(
- frame_count_with_pending_tree_ <= 1);
+
+ if (frame_count_with_pending_tree_ == 2)
+ impl->BlockNotifyReadyToActivateForTesting(false);
+ }
+
+ virtual void DidBeginImplFrameOnThread(LayerTreeHostImpl* impl,
+ const BeginFrameArgs& args) OVERRIDE {
+ if (frame_count_with_pending_tree_ == 1) {
+ EXPECT_EQ(first_frame_time_.ToInternalValue(), 0);
+ first_frame_time_ = impl->CurrentFrameTimeTicks();
+ }
}
virtual void DrawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE {
if (frame_count_with_pending_tree_ > 1) {
+ EXPECT_NE(first_frame_time_.ToInternalValue(), 0);
EXPECT_NE(first_frame_time_.ToInternalValue(),
impl->CurrentFrameTimeTicks().ToInternalValue());
EndTest();
@@ -895,10 +1101,9 @@ class LayerTreeHostTestFrameTimeUpdatesAfterDraw : public LayerTreeHostTest {
first_frame_time_ = impl->CurrentFrameTimeTicks();
impl->SetNeedsRedraw();
- // Since base::TimeTicks::Now() uses a low-resolution clock on
- // Windows, we need to make sure that the clock has incremented past
- // first_frame_time_.
- while (first_frame_time_ == base::TimeTicks::Now()) {}
+ // Since we might use a low-resolution clock on Windows, we need to
+ // make sure that the clock has incremented past first_frame_time_.
+ while (first_frame_time_ == gfx::FrameTime::Now()) {}
return;
}
@@ -935,10 +1140,19 @@ class LayerTreeHostTestStartPageScaleAnimation
virtual void SetupTree() OVERRIDE {
LayerTreeHostTest::SetupTree();
- scroll_layer_ = FakeContentLayer::Create(&client_);
+ if (layer_tree_host()->settings().impl_side_painting) {
+ scoped_refptr<FakePictureLayer> layer =
+ FakePictureLayer::Create(&client_);
+ layer->set_always_update_resources(true);
+ scroll_layer_ = layer;
+ } else {
+ scroll_layer_ = FakeContentLayer::Create(&client_);
+ }
+
scroll_layer_->SetScrollable(true);
scroll_layer_->SetScrollOffset(gfx::Vector2d());
layer_tree_host()->root_layer()->AddChild(scroll_layer_);
+ layer_tree_host()->SetPageScaleFactorAndLimits(1.f, 0.5f, 2.f);
}
virtual void BeginTest() OVERRIDE {
@@ -953,7 +1167,6 @@ class LayerTreeHostTestStartPageScaleAnimation
}
virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
- impl->ProcessScrollDeltas();
// We get one commit before the first draw, and the animation doesn't happen
// until the second draw.
switch (impl->active_tree()->source_frame_number()) {
@@ -963,7 +1176,6 @@ class LayerTreeHostTestStartPageScaleAnimation
break;
case 1:
EXPECT_EQ(1.f, impl->active_tree()->page_scale_factor());
- PostSetNeedsRedrawToMainThread();
break;
case 2:
EXPECT_EQ(1.25f, impl->active_tree()->page_scale_factor());
@@ -977,7 +1189,6 @@ class LayerTreeHostTestStartPageScaleAnimation
virtual void DidCommitAndDrawFrame() OVERRIDE {
switch (layer_tree_host()->source_frame_number()) {
case 1:
- layer_tree_host()->SetPageScaleFactorAndLimits(1.f, 0.5f, 2.f);
layer_tree_host()->StartPageScaleAnimation(
gfx::Vector2d(), false, 1.25f, base::TimeDelta());
break;
@@ -987,7 +1198,7 @@ class LayerTreeHostTestStartPageScaleAnimation
virtual void AfterTest() OVERRIDE {}
FakeContentLayerClient client_;
- scoped_refptr<FakeContentLayer> scroll_layer_;
+ scoped_refptr<Layer> scroll_layer_;
};
MULTI_THREAD_TEST_F(LayerTreeHostTestStartPageScaleAnimation);
@@ -1236,6 +1447,7 @@ MULTI_THREAD_TEST_F(LayerTreeHostTestDeviceScaleFactorScalesViewportAndLayers);
class LayerTreeHostTestDirectRendererAtomicCommit : public LayerTreeHostTest {
public:
virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
+ settings->texture_id_allocation_chunk_size = 1;
// Make sure partial texture updates are turned off.
settings->max_partial_texture_updates = 0;
// Linear fade animator prevents scrollbars from drawing immediately.
@@ -1337,7 +1549,7 @@ class LayerTreeHostTestDirectRendererAtomicCommit : public LayerTreeHostTest {
int drew_frame_;
};
-MULTI_THREAD_DIRECT_RENDERER_TEST_F(
+MULTI_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F(
LayerTreeHostTestDirectRendererAtomicCommit);
class LayerTreeHostTestDelegatingRendererAtomicCommit
@@ -1390,7 +1602,7 @@ class LayerTreeHostTestDelegatingRendererAtomicCommit
}
};
-MULTI_THREAD_DELEGATING_RENDERER_TEST_F(
+MULTI_THREAD_DELEGATING_RENDERER_NOIMPL_TEST_F(
LayerTreeHostTestDelegatingRendererAtomicCommit);
static void SetLayerPropertiesForTesting(Layer* layer,
@@ -1414,6 +1626,7 @@ class LayerTreeHostTestAtomicCommitWithPartialUpdate
: public LayerTreeHostTest {
public:
virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
+ settings->texture_id_allocation_chunk_size = 1;
// Allow one partial texture update.
settings->max_partial_texture_updates = 1;
// No partial updates when impl side painting is enabled.
@@ -1483,31 +1696,57 @@ class LayerTreeHostTestAtomicCommitWithPartialUpdate
context->ResetUsedTextures();
break;
case 1:
- // Number of textures should be two for each content layer.
- ASSERT_EQ(4u, context->NumTextures());
+ if (HasImplThread()) {
+ // Number of textures should be two for each content layer.
+ ASSERT_EQ(4u, context->NumTextures());
+ } else {
+ // In single thread we can always do partial updates, so the limit has
+ // no effect.
+ ASSERT_EQ(2u, context->NumTextures());
+ }
// Number of textures used for commit should be one for each content
// layer.
EXPECT_EQ(2u, context->NumUsedTextures());
- // First content textures should not have been used.
- EXPECT_FALSE(context->UsedTexture(context->TextureAt(0)));
- EXPECT_FALSE(context->UsedTexture(context->TextureAt(1)));
- // New textures should have been used.
- EXPECT_TRUE(context->UsedTexture(context->TextureAt(2)));
- EXPECT_TRUE(context->UsedTexture(context->TextureAt(3)));
+ if (HasImplThread()) {
+ // First content textures should not have been used.
+ EXPECT_FALSE(context->UsedTexture(context->TextureAt(0)));
+ EXPECT_FALSE(context->UsedTexture(context->TextureAt(1)));
+ // New textures should have been used.
+ EXPECT_TRUE(context->UsedTexture(context->TextureAt(2)));
+ EXPECT_TRUE(context->UsedTexture(context->TextureAt(3)));
+ } else {
+ // In single thread we can always do partial updates, so the limit has
+ // no effect.
+ EXPECT_TRUE(context->UsedTexture(context->TextureAt(0)));
+ EXPECT_TRUE(context->UsedTexture(context->TextureAt(1)));
+ }
context->ResetUsedTextures();
break;
case 2:
- // Number of textures should be two for each content layer.
- ASSERT_EQ(4u, context->NumTextures());
+ if (HasImplThread()) {
+ // Number of textures should be two for each content layer.
+ ASSERT_EQ(4u, context->NumTextures());
+ } else {
+ // In single thread we can always do partial updates, so the limit has
+ // no effect.
+ ASSERT_EQ(2u, context->NumTextures());
+ }
// Number of textures used for commit should be one for each content
// layer.
EXPECT_EQ(2u, context->NumUsedTextures());
- // One content layer does a partial update also.
- EXPECT_TRUE(context->UsedTexture(context->TextureAt(2)));
- EXPECT_FALSE(context->UsedTexture(context->TextureAt(3)));
+ if (HasImplThread()) {
+ // One content layer does a partial update also.
+ EXPECT_TRUE(context->UsedTexture(context->TextureAt(2)));
+ EXPECT_FALSE(context->UsedTexture(context->TextureAt(3)));
+ } else {
+ // In single thread we can always do partial updates, so the limit has
+ // no effect.
+ EXPECT_TRUE(context->UsedTexture(context->TextureAt(0)));
+ EXPECT_TRUE(context->UsedTexture(context->TextureAt(1)));
+ }
context->ResetUsedTextures();
break;
@@ -1623,10 +1862,6 @@ SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestCompositeAndReadbackCleanup);
class LayerTreeHostTestSurfaceNotAllocatedForLayersOutsideMemoryLimit
: public LayerTreeHostTest {
protected:
- virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
- settings->cache_render_pass_contents = true;
- }
-
virtual void SetupTree() OVERRIDE {
root_layer_ = FakeContentLayer::Create(&client_);
root_layer_->SetBounds(gfx::Size(100, 100));
@@ -1667,21 +1902,20 @@ class LayerTreeHostTestSurfaceNotAllocatedForLayersOutsideMemoryLimit
switch (host_impl->active_tree()->source_frame_number()) {
case 0:
- EXPECT_TRUE(renderer->HaveCachedResourcesForRenderPassId(
+ EXPECT_TRUE(renderer->HasAllocatedResourcesForTesting(
surface1_render_pass_id));
- EXPECT_TRUE(renderer->HaveCachedResourcesForRenderPassId(
+ EXPECT_TRUE(renderer->HasAllocatedResourcesForTesting(
surface2_render_pass_id));
// Reduce the memory limit to only fit the root layer and one render
// surface. This prevents any contents drawing into surfaces
// from being allocated.
host_impl->SetMemoryPolicy(ManagedMemoryPolicy(100 * 100 * 4 * 2));
- host_impl->SetDiscardBackBufferWhenNotVisible(true);
break;
case 1:
- EXPECT_FALSE(renderer->HaveCachedResourcesForRenderPassId(
+ EXPECT_FALSE(renderer->HasAllocatedResourcesForTesting(
surface1_render_pass_id));
- EXPECT_FALSE(renderer->HaveCachedResourcesForRenderPassId(
+ EXPECT_FALSE(renderer->HasAllocatedResourcesForTesting(
surface2_render_pass_id));
EndTest();
@@ -1709,7 +1943,7 @@ class LayerTreeHostTestSurfaceNotAllocatedForLayersOutsideMemoryLimit
};
// Surfaces don't exist with a delegated renderer.
-SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
+SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F(
LayerTreeHostTestSurfaceNotAllocatedForLayersOutsideMemoryLimit);
class EvictionTestLayer : public Layer {
@@ -1933,7 +2167,7 @@ class LayerTreeHostTestEvictTextures : public LayerTreeHostTest {
int num_commits_;
};
-MULTI_THREAD_TEST_F(LayerTreeHostTestEvictTextures);
+MULTI_THREAD_NOIMPL_TEST_F(LayerTreeHostTestEvictTextures);
class LayerTreeHostTestContinuousCommit : public LayerTreeHostTest {
public:
@@ -2024,7 +2258,7 @@ class LayerTreeHostTestContinuousInvalidate : public LayerTreeHostTest {
int num_draw_layers_;
};
-MULTI_THREAD_TEST_F(LayerTreeHostTestContinuousInvalidate);
+MULTI_THREAD_NOIMPL_TEST_F(LayerTreeHostTestContinuousInvalidate);
class LayerTreeHostTestDeferCommits : public LayerTreeHostTest {
public:
@@ -2072,7 +2306,7 @@ class LayerTreeHostWithProxy : public LayerTreeHost {
LayerTreeHostWithProxy(FakeLayerTreeHostClient* client,
const LayerTreeSettings& settings,
scoped_ptr<FakeProxy> proxy)
- : LayerTreeHost(client, settings) {
+ : LayerTreeHost(client, NULL, settings) {
proxy->SetLayerTreeHost(this);
EXPECT_TRUE(InitializeForTesting(proxy.PassAs<Proxy>()));
}
@@ -2093,7 +2327,7 @@ TEST(LayerTreeHostTest, LimitPartialUpdates) {
LayerTreeHostWithProxy host(&client, settings, proxy.Pass());
EXPECT_TRUE(host.InitializeOutputSurfaceIfNeeded());
- EXPECT_EQ(0u, host.settings().max_partial_texture_updates);
+ EXPECT_EQ(0u, host.MaxPartialTextureUpdates());
}
// When partial updates are allowed,
@@ -2111,7 +2345,7 @@ TEST(LayerTreeHostTest, LimitPartialUpdates) {
LayerTreeHostWithProxy host(&client, settings, proxy.Pass());
EXPECT_TRUE(host.InitializeOutputSurfaceIfNeeded());
- EXPECT_EQ(5u, host.settings().max_partial_texture_updates);
+ EXPECT_EQ(5u, host.MaxPartialTextureUpdates());
}
// When partial updates are allowed,
@@ -2129,7 +2363,7 @@ TEST(LayerTreeHostTest, LimitPartialUpdates) {
LayerTreeHostWithProxy host(&client, settings, proxy.Pass());
EXPECT_TRUE(host.InitializeOutputSurfaceIfNeeded());
- EXPECT_EQ(10u, host.settings().max_partial_texture_updates);
+ EXPECT_EQ(10u, host.MaxPartialTextureUpdates());
}
}
@@ -2140,7 +2374,7 @@ TEST(LayerTreeHostTest, PartialUpdatesWithGLRenderer) {
settings.max_partial_texture_updates = 4;
scoped_ptr<LayerTreeHost> host =
- LayerTreeHost::Create(&client, settings, NULL);
+ LayerTreeHost::CreateSingleThreaded(&client, &client, NULL, settings);
EXPECT_TRUE(host->InitializeOutputSurfaceIfNeeded());
EXPECT_EQ(4u, host->settings().max_partial_texture_updates);
}
@@ -2152,7 +2386,7 @@ TEST(LayerTreeHostTest, PartialUpdatesWithSoftwareRenderer) {
settings.max_partial_texture_updates = 4;
scoped_ptr<LayerTreeHost> host =
- LayerTreeHost::Create(&client, settings, NULL);
+ LayerTreeHost::CreateSingleThreaded(&client, &client, NULL, settings);
EXPECT_TRUE(host->InitializeOutputSurfaceIfNeeded());
EXPECT_EQ(4u, host->settings().max_partial_texture_updates);
}
@@ -2164,9 +2398,9 @@ TEST(LayerTreeHostTest, PartialUpdatesWithDelegatingRendererAndGLContent) {
settings.max_partial_texture_updates = 4;
scoped_ptr<LayerTreeHost> host =
- LayerTreeHost::Create(&client, settings, NULL);
+ LayerTreeHost::CreateSingleThreaded(&client, &client, NULL, settings);
EXPECT_TRUE(host->InitializeOutputSurfaceIfNeeded());
- EXPECT_EQ(0u, host->settings().max_partial_texture_updates);
+ EXPECT_EQ(0u, host->MaxPartialTextureUpdates());
}
TEST(LayerTreeHostTest,
@@ -2177,9 +2411,9 @@ TEST(LayerTreeHostTest,
settings.max_partial_texture_updates = 4;
scoped_ptr<LayerTreeHost> host =
- LayerTreeHost::Create(&client, settings, NULL);
+ LayerTreeHost::CreateSingleThreaded(&client, &client, NULL, settings);
EXPECT_TRUE(host->InitializeOutputSurfaceIfNeeded());
- EXPECT_EQ(0u, host->settings().max_partial_texture_updates);
+ EXPECT_EQ(0u, host->MaxPartialTextureUpdates());
}
class LayerTreeHostTestShutdownWithOnlySomeResourcesEvicted
@@ -2204,9 +2438,17 @@ class LayerTreeHostTestShutdownWithOnlySomeResourcesEvicted
virtual void DidSetVisibleOnImplTree(LayerTreeHostImpl* host_impl,
bool visible) OVERRIDE {
- // One backing should remain unevicted.
- EXPECT_EQ(100u * 100u * 4u * 1u,
- layer_tree_host()->contents_texture_manager()->MemoryUseBytes());
+ if (visible) {
+ // One backing should remain unevicted.
+ EXPECT_EQ(
+ 100u * 100u * 4u * 1u,
+ layer_tree_host()->contents_texture_manager()->MemoryUseBytes());
+ } else {
+ EXPECT_EQ(
+ 0u,
+ layer_tree_host()->contents_texture_manager()->MemoryUseBytes());
+ }
+
// Make sure that contents textures are marked as having been
// purged.
EXPECT_TRUE(host_impl->active_tree()->ContentsTexturesPurged());
@@ -2226,11 +2468,8 @@ class LayerTreeHostTestShutdownWithOnlySomeResourcesEvicted
// Because a resource was evicted, a commit will be kicked off.
host_impl->SetMemoryPolicy(
ManagedMemoryPolicy(100 * 100 * 4 * 2,
- ManagedMemoryPolicy::CUTOFF_ALLOW_EVERYTHING,
- 100 * 100 * 4 * 1,
- ManagedMemoryPolicy::CUTOFF_ALLOW_EVERYTHING,
+ gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING,
1000));
- host_impl->SetDiscardBackBufferWhenNotVisible(true);
break;
case 2:
// Only two backings should have memory.
@@ -2259,7 +2498,7 @@ class LayerTreeHostTestShutdownWithOnlySomeResourcesEvicted
int num_commits_;
};
-SINGLE_AND_MULTI_THREAD_TEST_F(
+SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F(
LayerTreeHostTestShutdownWithOnlySomeResourcesEvicted);
class LayerTreeHostTestLCDNotification : public LayerTreeHostTest {
@@ -2350,15 +2589,16 @@ class LayerTreeHostTestLCDNotification : public LayerTreeHostTest {
SINGLE_THREAD_TEST_F(LayerTreeHostTestLCDNotification);
-// Verify that the BeginFrame notification is used to initiate rendering.
-class LayerTreeHostTestBeginFrameNotification : public LayerTreeHostTest {
+// Verify that the BeginImplFrame notification is used to initiate rendering.
+class LayerTreeHostTestBeginImplFrameNotification : public LayerTreeHostTest {
public:
virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
- settings->begin_frame_scheduling_enabled = true;
+ settings->begin_impl_frame_scheduling_enabled = true;
}
virtual void BeginTest() OVERRIDE {
- // This will trigger a SetNeedsBeginFrame which will trigger a BeginFrame.
+ // This will trigger a SetNeedsBeginImplFrame which will trigger a
+ // BeginImplFrame.
PostSetNeedsCommitToMainThread();
}
@@ -2376,24 +2616,24 @@ class LayerTreeHostTestBeginFrameNotification : public LayerTreeHostTest {
base::TimeTicks frame_time_;
};
-MULTI_THREAD_TEST_F(LayerTreeHostTestBeginFrameNotification);
+MULTI_THREAD_TEST_F(LayerTreeHostTestBeginImplFrameNotification);
-class LayerTreeHostTestBeginFrameNotificationShutdownWhileEnabled
+class LayerTreeHostTestBeginImplFrameNotificationShutdownWhileEnabled
: public LayerTreeHostTest {
public:
virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
- settings->begin_frame_scheduling_enabled = true;
+ settings->begin_impl_frame_scheduling_enabled = true;
settings->using_synchronous_renderer_compositor = true;
}
virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
- // The BeginFrame notification is turned off now but will get enabled
+ // The BeginImplFrame notification is turned off now but will get enabled
// once we return. End test while it's enabled.
ImplThreadTaskRunner()->PostTask(
FROM_HERE,
- base::Bind(&LayerTreeHostTestBeginFrameNotification::EndTest,
+ base::Bind(&LayerTreeHostTestBeginImplFrameNotification::EndTest,
base::Unretained(this)));
}
@@ -2401,35 +2641,40 @@ class LayerTreeHostTestBeginFrameNotificationShutdownWhileEnabled
};
MULTI_THREAD_TEST_F(
- LayerTreeHostTestBeginFrameNotificationShutdownWhileEnabled);
+ LayerTreeHostTestBeginImplFrameNotificationShutdownWhileEnabled);
-class LayerTreeHostTestAbortedCommitDoesntStallNextCommitWhenIdle
- : public LayerTreeHostTest {
+class LayerTreeHostTestAbortedCommitDoesntStall : public LayerTreeHostTest {
protected:
- LayerTreeHostTestAbortedCommitDoesntStallNextCommitWhenIdle()
- : commit_count_(0), commit_complete_count_(0) {}
+ LayerTreeHostTestAbortedCommitDoesntStall()
+ : commit_count_(0), commit_abort_count_(0), commit_complete_count_(0) {}
virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
- settings->begin_frame_scheduling_enabled = true;
- settings->using_synchronous_renderer_compositor = true;
+ settings->begin_impl_frame_scheduling_enabled = true;
}
virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
virtual void DidCommit() OVERRIDE {
commit_count_++;
- if (commit_count_ == 2) {
- // A commit was just aborted, request a real commit now to make sure a
+ if (commit_count_ == 4) {
+ // After two aborted commits, request a real commit now to make sure a
// real commit following an aborted commit will still complete and
// end the test even when the Impl thread is idle.
layer_tree_host()->SetNeedsCommit();
}
}
+ virtual void BeginMainFrameAbortedOnThread(
+ LayerTreeHostImpl *host_impl, bool did_handle) OVERRIDE {
+ commit_abort_count_++;
+ // Initiate another abortable commit.
+ host_impl->SetNeedsCommit();
+ }
+
virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
commit_complete_count_++;
if (commit_complete_count_ == 1) {
- // Initiate an aborted commit after the first commit.
+ // Initiate an abortable commit after the first commit.
host_impl->SetNeedsCommit();
} else {
EndTest();
@@ -2437,16 +2682,36 @@ class LayerTreeHostTestAbortedCommitDoesntStallNextCommitWhenIdle
}
virtual void AfterTest() OVERRIDE {
- EXPECT_EQ(commit_count_, 3);
+ EXPECT_EQ(commit_count_, 5);
+ EXPECT_EQ(commit_abort_count_, 3);
EXPECT_EQ(commit_complete_count_, 2);
}
int commit_count_;
+ int commit_abort_count_;
int commit_complete_count_;
};
+class LayerTreeHostTestAbortedCommitDoesntStallSynchronousCompositor
+ : public LayerTreeHostTestAbortedCommitDoesntStall {
+ virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
+ LayerTreeHostTestAbortedCommitDoesntStall::InitializeSettings(settings);
+ settings->using_synchronous_renderer_compositor = true;
+ }
+};
+
MULTI_THREAD_TEST_F(
- LayerTreeHostTestAbortedCommitDoesntStallNextCommitWhenIdle);
+ LayerTreeHostTestAbortedCommitDoesntStallSynchronousCompositor);
+
+class LayerTreeHostTestAbortedCommitDoesntStallDisabledVsync
+ : public LayerTreeHostTestAbortedCommitDoesntStall {
+ virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
+ LayerTreeHostTestAbortedCommitDoesntStall::InitializeSettings(settings);
+ settings->throttle_frame_production = false;
+ }
+};
+
+MULTI_THREAD_TEST_F(LayerTreeHostTestAbortedCommitDoesntStallDisabledVsync);
class LayerTreeHostTestUninvertibleTransformDoesNotBlockActivation
: public LayerTreeHostTest {
@@ -2544,26 +2809,26 @@ class MockIOSurfaceWebGraphicsContext3D : public TestWebGraphicsContext3D {
test_capabilities_.texture_rectangle = true;
}
- virtual WebKit::WebGLId createTexture() OVERRIDE {
+ virtual blink::WebGLId createTexture() OVERRIDE {
return 1;
}
- MOCK_METHOD1(activeTexture, void(WebKit::WGC3Denum texture));
- MOCK_METHOD2(bindTexture, void(WebKit::WGC3Denum target,
- WebKit::WebGLId texture_id));
- MOCK_METHOD3(texParameteri, void(WebKit::WGC3Denum target,
- WebKit::WGC3Denum pname,
- WebKit::WGC3Dint param));
- MOCK_METHOD5(texImageIOSurface2DCHROMIUM, void(WebKit::WGC3Denum target,
- WebKit::WGC3Dint width,
- WebKit::WGC3Dint height,
- WebKit::WGC3Duint ioSurfaceId,
- WebKit::WGC3Duint plane));
- MOCK_METHOD4(drawElements, void(WebKit::WGC3Denum mode,
- WebKit::WGC3Dsizei count,
- WebKit::WGC3Denum type,
- WebKit::WGC3Dintptr offset));
- MOCK_METHOD1(deleteTexture, void(WebKit::WGC3Denum texture));
+ MOCK_METHOD1(activeTexture, void(blink::WGC3Denum texture));
+ MOCK_METHOD2(bindTexture, void(blink::WGC3Denum target,
+ blink::WebGLId texture_id));
+ MOCK_METHOD3(texParameteri, void(blink::WGC3Denum target,
+ blink::WGC3Denum pname,
+ blink::WGC3Dint param));
+ MOCK_METHOD5(texImageIOSurface2DCHROMIUM, void(blink::WGC3Denum target,
+ blink::WGC3Dint width,
+ blink::WGC3Dint height,
+ blink::WGC3Duint ioSurfaceId,
+ blink::WGC3Duint plane));
+ MOCK_METHOD4(drawElements, void(blink::WGC3Denum mode,
+ blink::WGC3Dsizei count,
+ blink::WGC3Denum type,
+ blink::WGC3Dintptr offset));
+ MOCK_METHOD1(deleteTexture, void(blink::WGC3Denum texture));
};
@@ -2671,676 +2936,6 @@ class LayerTreeHostTestIOSurfaceDrawing : public LayerTreeHostTest {
SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
LayerTreeHostTestIOSurfaceDrawing);
-class LayerTreeHostTestAsyncReadback : public LayerTreeHostTest {
- protected:
- virtual void SetupTree() OVERRIDE {
- root = FakeContentLayer::Create(&client_);
- root->SetBounds(gfx::Size(20, 20));
-
- child = FakeContentLayer::Create(&client_);
- child->SetBounds(gfx::Size(10, 10));
- root->AddChild(child);
-
- layer_tree_host()->SetRootLayer(root);
- LayerTreeHostTest::SetupTree();
- }
-
- virtual void BeginTest() OVERRIDE {
- PostSetNeedsCommitToMainThread();
- }
-
- virtual void DidCommitAndDrawFrame() OVERRIDE {
- WaitForCallback();
- }
-
- void WaitForCallback() {
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(
- &LayerTreeHostTestAsyncReadback::NextStep,
- base::Unretained(this)));
- }
-
- void NextStep() {
- int frame = layer_tree_host()->source_frame_number();
- switch (frame) {
- case 1:
- child->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
- base::Bind(&LayerTreeHostTestAsyncReadback::CopyOutputCallback,
- base::Unretained(this))));
- EXPECT_EQ(0u, callbacks_.size());
- break;
- case 2:
- if (callbacks_.size() < 1u) {
- WaitForCallback();
- return;
- }
- EXPECT_EQ(1u, callbacks_.size());
- EXPECT_EQ(gfx::Size(10, 10).ToString(), callbacks_[0].ToString());
-
- child->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
- base::Bind(&LayerTreeHostTestAsyncReadback::CopyOutputCallback,
- base::Unretained(this))));
- root->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
- base::Bind(&LayerTreeHostTestAsyncReadback::CopyOutputCallback,
- base::Unretained(this))));
- child->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
- base::Bind(&LayerTreeHostTestAsyncReadback::CopyOutputCallback,
- base::Unretained(this))));
- EXPECT_EQ(1u, callbacks_.size());
- break;
- case 3:
- if (callbacks_.size() < 4u) {
- WaitForCallback();
- return;
- }
- EXPECT_EQ(4u, callbacks_.size());
- // The child was copied to a bitmap and passed back twice.
- EXPECT_EQ(gfx::Size(10, 10).ToString(), callbacks_[1].ToString());
- EXPECT_EQ(gfx::Size(10, 10).ToString(), callbacks_[2].ToString());
- // The root was copied to a bitmap and passed back also.
- EXPECT_EQ(gfx::Size(20, 20).ToString(), callbacks_[3].ToString());
- EndTest();
- break;
- }
- }
-
- void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
- EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
- EXPECT_TRUE(result->HasBitmap());
- scoped_ptr<SkBitmap> bitmap = result->TakeBitmap().Pass();
- EXPECT_EQ(result->size().ToString(),
- gfx::Size(bitmap->width(), bitmap->height()).ToString());
- callbacks_.push_back(result->size());
- }
-
- virtual void AfterTest() OVERRIDE {
- EXPECT_EQ(4u, callbacks_.size());
- }
-
- virtual scoped_ptr<OutputSurface> CreateOutputSurface(bool fallback)
- OVERRIDE {
- scoped_ptr<FakeOutputSurface> output_surface;
- if (use_gl_renderer_) {
- output_surface = FakeOutputSurface::Create3d().Pass();
- } else {
- output_surface = FakeOutputSurface::CreateSoftware(
- make_scoped_ptr(new SoftwareOutputDevice)).Pass();
- }
- return output_surface.PassAs<OutputSurface>();
- }
-
- bool use_gl_renderer_;
- std::vector<gfx::Size> callbacks_;
- FakeContentLayerClient client_;
- scoped_refptr<FakeContentLayer> root;
- scoped_refptr<FakeContentLayer> child;
-};
-
-// Readback can't be done with a delegating renderer.
-TEST_F(LayerTreeHostTestAsyncReadback, GLRenderer_RunSingleThread) {
- use_gl_renderer_ = true;
- RunTest(false, false, false);
-}
-
-TEST_F(LayerTreeHostTestAsyncReadback,
- GLRenderer_RunMultiThread_MainThreadPainting) {
- use_gl_renderer_ = true;
- RunTest(true, false, false);
-}
-
-TEST_F(LayerTreeHostTestAsyncReadback,
- GLRenderer_RunMultiThread_ImplSidePainting) {
- use_gl_renderer_ = true;
- RunTest(true, false, true);
-}
-
-TEST_F(LayerTreeHostTestAsyncReadback, SoftwareRenderer_RunSingleThread) {
- use_gl_renderer_ = false;
- RunTest(false, false, false);
-}
-
-TEST_F(LayerTreeHostTestAsyncReadback,
- SoftwareRenderer_RunMultiThread_MainThreadPainting) {
- use_gl_renderer_ = false;
- RunTest(true, false, false);
-}
-
-TEST_F(LayerTreeHostTestAsyncReadback,
- SoftwareRenderer_RunMultiThread_ImplSidePainting) {
- use_gl_renderer_ = false;
- RunTest(true, false, true);
-}
-
-class LayerTreeHostTestAsyncReadbackLayerDestroyed : public LayerTreeHostTest {
- protected:
- virtual void SetupTree() OVERRIDE {
- root_ = FakeContentLayer::Create(&client_);
- root_->SetBounds(gfx::Size(20, 20));
-
- main_destroyed_ = FakeContentLayer::Create(&client_);
- main_destroyed_->SetBounds(gfx::Size(15, 15));
- root_->AddChild(main_destroyed_);
-
- impl_destroyed_ = FakeContentLayer::Create(&client_);
- impl_destroyed_->SetBounds(gfx::Size(10, 10));
- root_->AddChild(impl_destroyed_);
-
- layer_tree_host()->SetRootLayer(root_);
- LayerTreeHostTest::SetupTree();
- }
-
- virtual void BeginTest() OVERRIDE {
- callback_count_ = 0;
- PostSetNeedsCommitToMainThread();
- }
-
- virtual void DidCommit() OVERRIDE {
- int frame = layer_tree_host()->source_frame_number();
- switch (frame) {
- case 1:
- main_destroyed_->RequestCopyOfOutput(
- CopyOutputRequest::CreateBitmapRequest(base::Bind(
- &LayerTreeHostTestAsyncReadbackLayerDestroyed::
- CopyOutputCallback,
- base::Unretained(this))));
- impl_destroyed_->RequestCopyOfOutput(
- CopyOutputRequest::CreateBitmapRequest(base::Bind(
- &LayerTreeHostTestAsyncReadbackLayerDestroyed::
- CopyOutputCallback,
- base::Unretained(this))));
- EXPECT_EQ(0, callback_count_);
-
- // Destroy the main thread layer right away.
- main_destroyed_->RemoveFromParent();
- main_destroyed_ = NULL;
-
- // Should callback with a NULL bitmap.
- EXPECT_EQ(1, callback_count_);
-
- // Prevent drawing so we can't make a copy of the impl_destroyed layer.
- layer_tree_host()->SetViewportSize(gfx::Size());
- break;
- case 2:
- // Flush the message loops and make sure the callbacks run.
- layer_tree_host()->SetNeedsCommit();
- break;
- case 3:
- // No drawing means no readback yet.
- EXPECT_EQ(1, callback_count_);
-
- // Destroy the impl thread layer.
- impl_destroyed_->RemoveFromParent();
- impl_destroyed_ = NULL;
-
- // No callback yet because it's on the impl side.
- EXPECT_EQ(1, callback_count_);
- break;
- case 4:
- // Flush the message loops and make sure the callbacks run.
- layer_tree_host()->SetNeedsCommit();
- break;
- case 5:
- // We should get another callback with a NULL bitmap.
- EXPECT_EQ(2, callback_count_);
- EndTest();
- break;
- }
- }
-
- void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
- EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
- EXPECT_TRUE(result->IsEmpty());
- ++callback_count_;
- }
-
- virtual void AfterTest() OVERRIDE {}
-
- int callback_count_;
- FakeContentLayerClient client_;
- scoped_refptr<FakeContentLayer> root_;
- scoped_refptr<FakeContentLayer> main_destroyed_;
- scoped_refptr<FakeContentLayer> impl_destroyed_;
-};
-
-SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestAsyncReadbackLayerDestroyed);
-
-class LayerTreeHostTestAsyncReadbackInHiddenSubtree : public LayerTreeHostTest {
- protected:
- virtual void SetupTree() OVERRIDE {
- root_ = FakeContentLayer::Create(&client_);
- root_->SetBounds(gfx::Size(20, 20));
-
- grand_parent_layer_ = FakeContentLayer::Create(&client_);
- grand_parent_layer_->SetBounds(gfx::Size(15, 15));
- root_->AddChild(grand_parent_layer_);
-
- // parent_layer_ owns a render surface.
- parent_layer_ = FakeContentLayer::Create(&client_);
- parent_layer_->SetBounds(gfx::Size(15, 15));
- parent_layer_->SetForceRenderSurface(true);
- grand_parent_layer_->AddChild(parent_layer_);
-
- copy_layer_ = FakeContentLayer::Create(&client_);
- copy_layer_->SetBounds(gfx::Size(10, 10));
- parent_layer_->AddChild(copy_layer_);
-
- layer_tree_host()->SetRootLayer(root_);
- LayerTreeHostTest::SetupTree();
- }
-
- void AddCopyRequest(Layer* layer) {
- layer->RequestCopyOfOutput(
- CopyOutputRequest::CreateBitmapRequest(base::Bind(
- &LayerTreeHostTestAsyncReadbackInHiddenSubtree::CopyOutputCallback,
- base::Unretained(this))));
- }
-
- virtual void BeginTest() OVERRIDE {
- callback_count_ = 0;
- PostSetNeedsCommitToMainThread();
-
- AddCopyRequest(copy_layer_.get());
- }
-
- void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
- EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
- EXPECT_EQ(copy_layer_->bounds().ToString(), result->size().ToString());
- ++callback_count_;
-
- switch (callback_count_) {
- case 1:
- // Hide the copy request layer.
- grand_parent_layer_->SetHideLayerAndSubtree(false);
- parent_layer_->SetHideLayerAndSubtree(false);
- copy_layer_->SetHideLayerAndSubtree(true);
- AddCopyRequest(copy_layer_.get());
- break;
- case 2:
- // Hide the copy request layer's parent only.
- grand_parent_layer_->SetHideLayerAndSubtree(false);
- parent_layer_->SetHideLayerAndSubtree(true);
- copy_layer_->SetHideLayerAndSubtree(false);
- AddCopyRequest(copy_layer_.get());
- break;
- case 3:
- // Hide the copy request layer's grand parent only.
- grand_parent_layer_->SetHideLayerAndSubtree(true);
- parent_layer_->SetHideLayerAndSubtree(false);
- copy_layer_->SetHideLayerAndSubtree(false);
- AddCopyRequest(copy_layer_.get());
- break;
- case 4:
- // Hide the copy request layer's parent and grandparent.
- grand_parent_layer_->SetHideLayerAndSubtree(true);
- parent_layer_->SetHideLayerAndSubtree(true);
- copy_layer_->SetHideLayerAndSubtree(false);
- AddCopyRequest(copy_layer_.get());
- break;
- case 5:
- // Hide the copy request layer as well as its parent and grandparent.
- grand_parent_layer_->SetHideLayerAndSubtree(true);
- parent_layer_->SetHideLayerAndSubtree(true);
- copy_layer_->SetHideLayerAndSubtree(true);
- AddCopyRequest(copy_layer_.get());
- break;
- case 6:
- EndTest();
- break;
- }
- }
-
- virtual void AfterTest() OVERRIDE {}
-
- int callback_count_;
- FakeContentLayerClient client_;
- scoped_refptr<FakeContentLayer> root_;
- scoped_refptr<FakeContentLayer> grand_parent_layer_;
- scoped_refptr<FakeContentLayer> parent_layer_;
- scoped_refptr<FakeContentLayer> copy_layer_;
-};
-
-// No output to copy for delegated renderers.
-SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
- LayerTreeHostTestAsyncReadbackInHiddenSubtree);
-
-class LayerTreeHostTestHiddenSurfaceNotAllocatedForSubtreeCopyRequest
- : public LayerTreeHostTest {
- protected:
- virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
- settings->cache_render_pass_contents = true;
- }
-
- virtual void SetupTree() OVERRIDE {
- root_ = FakeContentLayer::Create(&client_);
- root_->SetBounds(gfx::Size(20, 20));
-
- grand_parent_layer_ = FakeContentLayer::Create(&client_);
- grand_parent_layer_->SetBounds(gfx::Size(15, 15));
- grand_parent_layer_->SetHideLayerAndSubtree(true);
- root_->AddChild(grand_parent_layer_);
-
- // parent_layer_ owns a render surface.
- parent_layer_ = FakeContentLayer::Create(&client_);
- parent_layer_->SetBounds(gfx::Size(15, 15));
- parent_layer_->SetForceRenderSurface(true);
- grand_parent_layer_->AddChild(parent_layer_);
-
- copy_layer_ = FakeContentLayer::Create(&client_);
- copy_layer_->SetBounds(gfx::Size(10, 10));
- parent_layer_->AddChild(copy_layer_);
-
- layer_tree_host()->SetRootLayer(root_);
- LayerTreeHostTest::SetupTree();
- }
-
- virtual void BeginTest() OVERRIDE {
- did_draw_ = false;
- PostSetNeedsCommitToMainThread();
-
- copy_layer_->RequestCopyOfOutput(
- CopyOutputRequest::CreateBitmapRequest(base::Bind(
- &LayerTreeHostTestHiddenSurfaceNotAllocatedForSubtreeCopyRequest::
- CopyOutputCallback,
- base::Unretained(this))));
- }
-
- void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
- EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
- EXPECT_EQ(copy_layer_->bounds().ToString(), result->size().ToString());
- EndTest();
- }
-
- virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
- Renderer* renderer = host_impl->renderer();
-
- LayerImpl* root = host_impl->active_tree()->root_layer();
- LayerImpl* grand_parent = root->children()[0];
- LayerImpl* parent = grand_parent->children()[0];
- LayerImpl* copy_layer = parent->children()[0];
-
- // |parent| owns a surface, but it was hidden and not part of the copy
- // request so it should not allocate any resource.
- EXPECT_FALSE(renderer->HaveCachedResourcesForRenderPassId(
- parent->render_surface()->RenderPassId()));
-
- // |copy_layer| should have been rendered to a texture since it was needed
- // for a copy request.
- EXPECT_TRUE(renderer->HaveCachedResourcesForRenderPassId(
- copy_layer->render_surface()->RenderPassId()));
-
- did_draw_ = true;
- }
-
- virtual void AfterTest() OVERRIDE { EXPECT_TRUE(did_draw_); }
-
- FakeContentLayerClient client_;
- bool did_draw_;
- scoped_refptr<FakeContentLayer> root_;
- scoped_refptr<FakeContentLayer> grand_parent_layer_;
- scoped_refptr<FakeContentLayer> parent_layer_;
- scoped_refptr<FakeContentLayer> copy_layer_;
-};
-
-// No output to copy for delegated renderers.
-SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
- LayerTreeHostTestHiddenSurfaceNotAllocatedForSubtreeCopyRequest);
-
-class LayerTreeHostTestAsyncReadbackClippedOut : public LayerTreeHostTest {
- protected:
- virtual void SetupTree() OVERRIDE {
- root_ = FakeContentLayer::Create(&client_);
- root_->SetBounds(gfx::Size(20, 20));
-
- parent_layer_ = FakeContentLayer::Create(&client_);
- parent_layer_->SetBounds(gfx::Size(15, 15));
- parent_layer_->SetMasksToBounds(true);
- root_->AddChild(parent_layer_);
-
- copy_layer_ = FakeContentLayer::Create(&client_);
- copy_layer_->SetPosition(gfx::Point(15, 15));
- copy_layer_->SetBounds(gfx::Size(10, 10));
- parent_layer_->AddChild(copy_layer_);
-
- layer_tree_host()->SetRootLayer(root_);
- LayerTreeHostTest::SetupTree();
- }
-
- virtual void BeginTest() OVERRIDE {
- PostSetNeedsCommitToMainThread();
-
- copy_layer_->RequestCopyOfOutput(
- CopyOutputRequest::CreateBitmapRequest(base::Bind(
- &LayerTreeHostTestAsyncReadbackClippedOut::CopyOutputCallback,
- base::Unretained(this))));
- }
-
- void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
- // We should still get a callback with no output if the copy requested layer
- // was completely clipped away.
- EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
- EXPECT_EQ(gfx::Size().ToString(), result->size().ToString());
- EndTest();
- }
-
- virtual void AfterTest() OVERRIDE {}
-
- FakeContentLayerClient client_;
- scoped_refptr<FakeContentLayer> root_;
- scoped_refptr<FakeContentLayer> parent_layer_;
- scoped_refptr<FakeContentLayer> copy_layer_;
-};
-
-// No output to copy for delegated renderers.
-SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
- LayerTreeHostTestAsyncReadbackClippedOut);
-
-class LayerTreeHostTestAsyncTwoReadbacksWithoutDraw : public LayerTreeHostTest {
- protected:
- virtual void SetupTree() OVERRIDE {
- root_ = FakeContentLayer::Create(&client_);
- root_->SetBounds(gfx::Size(20, 20));
-
- copy_layer_ = FakeContentLayer::Create(&client_);
- copy_layer_->SetBounds(gfx::Size(10, 10));
- root_->AddChild(copy_layer_);
-
- layer_tree_host()->SetRootLayer(root_);
- LayerTreeHostTest::SetupTree();
- }
-
- void AddCopyRequest(Layer* layer) {
- layer->RequestCopyOfOutput(
- CopyOutputRequest::CreateBitmapRequest(base::Bind(
- &LayerTreeHostTestAsyncTwoReadbacksWithoutDraw::CopyOutputCallback,
- base::Unretained(this))));
- }
-
- virtual void BeginTest() OVERRIDE {
- saw_copy_request_ = false;
- callback_count_ = 0;
- PostSetNeedsCommitToMainThread();
-
- // Prevent drawing.
- layer_tree_host()->SetViewportSize(gfx::Size(0, 0));
-
- AddCopyRequest(copy_layer_.get());
- }
-
- virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
- if (impl->active_tree()->source_frame_number() == 0) {
- LayerImpl* root = impl->active_tree()->root_layer();
- EXPECT_TRUE(root->children()[0]->HasCopyRequest());
- saw_copy_request_ = true;
- }
- }
-
- virtual void DidCommit() OVERRIDE {
- if (layer_tree_host()->source_frame_number() == 1) {
- // Allow drawing.
- layer_tree_host()->SetViewportSize(gfx::Size(root_->bounds()));
-
- AddCopyRequest(copy_layer_.get());
- }
- }
-
- void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
- EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
- EXPECT_EQ(copy_layer_->bounds().ToString(), result->size().ToString());
- ++callback_count_;
-
- if (callback_count_ == 2)
- EndTest();
- }
-
- virtual void AfterTest() OVERRIDE { EXPECT_TRUE(saw_copy_request_); }
-
- bool saw_copy_request_;
- int callback_count_;
- FakeContentLayerClient client_;
- scoped_refptr<FakeContentLayer> root_;
- scoped_refptr<FakeContentLayer> copy_layer_;
-};
-
-// No output to copy for delegated renderers.
-SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
- LayerTreeHostTestAsyncTwoReadbacksWithoutDraw);
-
-class LayerTreeHostTestAsyncReadbackLostOutputSurface
- : public LayerTreeHostTest {
- protected:
- virtual scoped_ptr<OutputSurface> CreateOutputSurface(bool fallback)
- OVERRIDE {
- if (!first_context_provider_.get()) {
- first_context_provider_ = TestContextProvider::Create();
- return FakeOutputSurface::Create3d(first_context_provider_)
- .PassAs<OutputSurface>();
- }
-
- EXPECT_FALSE(second_context_provider_.get());
- second_context_provider_ = TestContextProvider::Create();
- return FakeOutputSurface::Create3d(second_context_provider_)
- .PassAs<OutputSurface>();
- }
-
- virtual void SetupTree() OVERRIDE {
- root_ = FakeContentLayer::Create(&client_);
- root_->SetBounds(gfx::Size(20, 20));
-
- copy_layer_ = FakeContentLayer::Create(&client_);
- copy_layer_->SetBounds(gfx::Size(10, 10));
- root_->AddChild(copy_layer_);
-
- layer_tree_host()->SetRootLayer(root_);
- LayerTreeHostTest::SetupTree();
- }
-
- virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
-
- void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
- EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
- EXPECT_EQ(gfx::Size(10, 10).ToString(), result->size().ToString());
- EXPECT_TRUE(result->HasTexture());
-
- // Save the result for later.
- EXPECT_FALSE(result_);
- result_ = result.Pass();
-
- // Post a commit to lose the output surface.
- layer_tree_host()->SetNeedsCommit();
- }
-
- virtual void DidCommitAndDrawFrame() OVERRIDE {
- switch (layer_tree_host()->source_frame_number()) {
- case 1:
- // The layers have been pushed to the impl side. The layer textures have
- // been allocated.
-
- // Request a copy of the layer. This will use another texture.
- copy_layer_->RequestCopyOfOutput(
- CopyOutputRequest::CreateRequest(base::Bind(
- &LayerTreeHostTestAsyncReadbackLostOutputSurface::
- CopyOutputCallback,
- base::Unretained(this))));
- break;
- case 4:
- // With SingleThreadProxy it takes two commits to finally swap after a
- // context loss.
- case 5:
- // Now destroy the CopyOutputResult, releasing the texture inside back
- // to the compositor.
- EXPECT_TRUE(result_);
- result_.reset();
-
- // Check that it is released.
- ImplThreadTaskRunner()->PostTask(
- FROM_HERE,
- base::Bind(&LayerTreeHostTestAsyncReadbackLostOutputSurface::
- CheckNumTextures,
- base::Unretained(this),
- num_textures_after_loss_ - 1));
- break;
- }
- }
-
- virtual void SwapBuffersOnThread(LayerTreeHostImpl *impl, bool result)
- OVERRIDE {
- switch (impl->active_tree()->source_frame_number()) {
- case 0:
- // The layers have been drawn, so their textures have been allocated.
- EXPECT_FALSE(result_);
- num_textures_without_readback_ =
- first_context_provider_->TestContext3d()->NumTextures();
- break;
- case 1:
- // We did a readback, so there will be a readback texture around now.
- EXPECT_LT(num_textures_without_readback_,
- first_context_provider_->TestContext3d()->NumTextures());
- break;
- case 2:
- // The readback texture is collected.
- EXPECT_TRUE(result_);
-
- // Lose the output surface.
- first_context_provider_->TestContext3d()->loseContextCHROMIUM(
- GL_GUILTY_CONTEXT_RESET_ARB,
- GL_INNOCENT_CONTEXT_RESET_ARB);
- break;
- case 3:
- // With SingleThreadProxy it takes two commits to finally swap after a
- // context loss.
- case 4:
- // The output surface has been recreated.
- EXPECT_TRUE(second_context_provider_.get());
-
- num_textures_after_loss_ =
- first_context_provider_->TestContext3d()->NumTextures();
- break;
- }
- }
-
- void CheckNumTextures(size_t expected_num_textures) {
- EXPECT_EQ(expected_num_textures,
- first_context_provider_->TestContext3d()->NumTextures());
- EndTest();
- }
-
- virtual void AfterTest() OVERRIDE {}
-
- scoped_refptr<TestContextProvider> first_context_provider_;
- scoped_refptr<TestContextProvider> second_context_provider_;
- size_t num_textures_without_readback_;
- size_t num_textures_after_loss_;
- FakeContentLayerClient client_;
- scoped_refptr<FakeContentLayer> root_;
- scoped_refptr<FakeContentLayer> copy_layer_;
- scoped_ptr<CopyOutputResult> result_;
-};
-
-// No output to copy for delegated renderers.
-SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
- LayerTreeHostTestAsyncReadbackLostOutputSurface);
-
class LayerTreeHostTestNumFramesPending : public LayerTreeHostTest {
public:
virtual void BeginTest() OVERRIDE {
@@ -3417,7 +3012,6 @@ class LayerTreeHostTestDeferredInitialize : public LayerTreeHostTest {
virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
// PictureLayer can only be used with impl side painting enabled.
settings->impl_side_painting = true;
- settings->solid_color_scrollbars = true;
}
virtual void SetupTree() OVERRIDE {
@@ -3440,7 +3034,6 @@ class LayerTreeHostTestDeferredInitialize : public LayerTreeHostTest {
OVERRIDE {
scoped_ptr<TestWebGraphicsContext3D> context3d(
TestWebGraphicsContext3D::Create());
- context3d->set_support_swapbuffers_complete_callback(false);
return FakeOutputSurface::CreateDeferredGL(
scoped_ptr<SoftwareOutputDevice>(new SoftwareOutputDevice))
@@ -3524,6 +3117,10 @@ class LayerTreeHostTestUIResource : public LayerTreeHostTest {
public:
LayerTreeHostTestUIResource() : num_ui_resources_(0), num_commits_(0) {}
+ virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
+ settings->texture_id_allocation_chunk_size = 1;
+ }
+
virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
virtual void DidCommit() OVERRIDE {
@@ -3672,13 +3269,13 @@ class LayerTreeHostTestLayersPushProperties : public LayerTreeHostTest {
child_ = PushPropertiesCountingLayer::Create();
child2_ = PushPropertiesCountingLayer::Create();
grandchild_ = PushPropertiesCountingLayer::Create();
- leaf_scrollbar_layer_ =
- FakePaintedScrollbarLayer::Create(false, false, root_->id());
+ leaf_always_pushing_layer_ = PushPropertiesCountingLayer::Create();
+ leaf_always_pushing_layer_->set_persist_needs_push_properties(true);
root_->AddChild(child_);
root_->AddChild(child2_);
child_->AddChild(grandchild_);
- child2_->AddChild(leaf_scrollbar_layer_);
+ child2_->AddChild(leaf_always_pushing_layer_);
other_root_ = PushPropertiesCountingLayer::Create();
@@ -3698,7 +3295,7 @@ class LayerTreeHostTestLayersPushProperties : public LayerTreeHostTest {
EXPECT_EQ(expected_push_properties_other_root_,
other_root_->push_properties_count());
EXPECT_EQ(expected_push_properties_leaf_layer_,
- leaf_scrollbar_layer_->push_properties_count());
+ leaf_always_pushing_layer_->push_properties_count());
// The scrollbar layer always needs to be pushed.
if (root_->layer_tree_host()) {
@@ -3709,9 +3306,10 @@ class LayerTreeHostTestLayersPushProperties : public LayerTreeHostTest {
EXPECT_TRUE(child2_->descendant_needs_push_properties());
EXPECT_FALSE(child2_->needs_push_properties());
}
- if (leaf_scrollbar_layer_->layer_tree_host()) {
- EXPECT_FALSE(leaf_scrollbar_layer_->descendant_needs_push_properties());
- EXPECT_TRUE(leaf_scrollbar_layer_->needs_push_properties());
+ if (leaf_always_pushing_layer_->layer_tree_host()) {
+ EXPECT_FALSE(
+ leaf_always_pushing_layer_->descendant_needs_push_properties());
+ EXPECT_TRUE(leaf_always_pushing_layer_->needs_push_properties());
}
// child_ and grandchild_ don't persist their need to push properties.
@@ -3820,9 +3418,8 @@ class LayerTreeHostTestLayersPushProperties : public LayerTreeHostTest {
break;
}
- // Content/Picture layers require PushProperties every commit that they are
- // in the tree.
- if (leaf_scrollbar_layer_->layer_tree_host())
+ // The leaf layer always pushes.
+ if (leaf_always_pushing_layer_->layer_tree_host())
++expected_push_properties_leaf_layer_;
}
@@ -3835,7 +3432,7 @@ class LayerTreeHostTestLayersPushProperties : public LayerTreeHostTest {
scoped_refptr<PushPropertiesCountingLayer> child2_;
scoped_refptr<PushPropertiesCountingLayer> grandchild_;
scoped_refptr<PushPropertiesCountingLayer> other_root_;
- scoped_refptr<FakePaintedScrollbarLayer> leaf_scrollbar_layer_;
+ scoped_refptr<PushPropertiesCountingLayer> leaf_always_pushing_layer_;
size_t expected_push_properties_root_;
size_t expected_push_properties_child_;
size_t expected_push_properties_child2_;
@@ -4578,7 +4175,7 @@ MULTI_THREAD_TEST_F(LayerTreeHostTestUpdateLayerInEmptyViewport);
class LayerTreeHostTestAbortEvictedTextures : public LayerTreeHostTest {
public:
LayerTreeHostTestAbortEvictedTextures()
- : num_will_begin_frames_(0), num_impl_commits_(0) {}
+ : num_will_begin_main_frames_(0), num_impl_commits_(0) {}
protected:
virtual void SetupTree() OVERRIDE {
@@ -4592,9 +4189,9 @@ class LayerTreeHostTestAbortEvictedTextures : public LayerTreeHostTest {
virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
- virtual void WillBeginFrame() OVERRIDE {
- num_will_begin_frames_++;
- switch (num_will_begin_frames_) {
+ virtual void WillBeginMainFrame() OVERRIDE {
+ num_will_begin_main_frames_++;
+ switch (num_will_begin_main_frames_) {
case 2:
// Send a redraw to the compositor thread. This will (wrongly) be
// ignored unless aborting resets the texture state.
@@ -4624,12 +4221,12 @@ class LayerTreeHostTestAbortEvictedTextures : public LayerTreeHostTest {
virtual void AfterTest() OVERRIDE {
// Ensure that the commit was truly aborted.
- EXPECT_EQ(2, num_will_begin_frames_);
+ EXPECT_EQ(2, num_will_begin_main_frames_);
EXPECT_EQ(1, num_impl_commits_);
}
private:
- int num_will_begin_frames_;
+ int num_will_begin_main_frames_;
int num_impl_commits_;
};
@@ -4640,6 +4237,7 @@ class LayerTreeHostTestMaxTransferBufferUsageBytes : public LayerTreeHostTest {
protected:
virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
settings->impl_side_painting = true;
+ settings->default_tile_size = gfx::Size(128, 128);
}
virtual scoped_ptr<OutputSurface> CreateOutputSurface(bool fallback)
@@ -4671,8 +4269,11 @@ class LayerTreeHostTestMaxTransferBufferUsageBytes : public LayerTreeHostTest {
// Expect that the transfer buffer memory used is equal to the
// MaxTransferBufferUsageBytes value set in CreateOutputSurface.
- EXPECT_EQ(1024 * 1024u,
- context->GetTransferBufferMemoryUsedBytes());
+ // NOTE: This is now 1/2 due to raster memory limit in TileManager.
+ // Only half the limit will be reached unless the task set
+ // thrashes to a completly new set of tiles.
+ EXPECT_EQ(512 * 1024u,
+ context->GetPeakTransferBufferMemoryUsedBytes());
EndTest();
}
@@ -4750,9 +4351,7 @@ class LayerTreeHostTestMemoryLimits : public LayerTreeHostTest {
// This will trigger a commit because the priority cutoff has changed.
impl->SetMemoryPolicy(ManagedMemoryPolicy(
16u*1024u*1024u,
- ManagedMemoryPolicy::CUTOFF_ALLOW_NICE_TO_HAVE,
- 0,
- ManagedMemoryPolicy::CUTOFF_ALLOW_NOTHING,
+ gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE,
1000));
break;
case 2:
@@ -4760,9 +4359,7 @@ class LayerTreeHostTestMemoryLimits : public LayerTreeHostTest {
// changed, and there is already enough memory for all allocations.
impl->SetMemoryPolicy(ManagedMemoryPolicy(
32u*1024u*1024u,
- ManagedMemoryPolicy::CUTOFF_ALLOW_NICE_TO_HAVE,
- 0,
- ManagedMemoryPolicy::CUTOFF_ALLOW_NOTHING,
+ gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE,
1000));
break;
case 3:
@@ -4777,8 +4374,402 @@ class LayerTreeHostTestMemoryLimits : public LayerTreeHostTest {
int num_commits_;
};
-SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestMemoryLimits);
+SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F(LayerTreeHostTestMemoryLimits);
+
+class LayerSetsNeedsFilterContext : public Layer {
+ public:
+ static scoped_refptr<LayerSetsNeedsFilterContext> Create() {
+ return make_scoped_refptr(new LayerSetsNeedsFilterContext());
+ }
+
+ virtual bool Update(ResourceUpdateQueue* queue,
+ const OcclusionTracker* occlusion) OVERRIDE {
+ bool updated = Layer::Update(queue, occlusion);
+ if (needs_context_) {
+ layer_tree_host()->set_needs_filter_context();
+ return true;
+ }
+ return updated;
+ }
+
+ void set_needs_context(bool need) { needs_context_ = need; }
+
+ private:
+ LayerSetsNeedsFilterContext() : needs_context_(false) {}
+ virtual ~LayerSetsNeedsFilterContext() {}
+
+ bool needs_context_;
+};
+
+class LayerTreeHostTestOffscreenContext : public LayerTreeHostTest {
+ protected:
+ virtual void SetupTree() OVERRIDE {
+ scoped_refptr<LayerSetsNeedsFilterContext> root =
+ LayerSetsNeedsFilterContext::Create();
+ root->SetIsDrawable(true);
+ root->SetAnchorPoint(gfx::PointF());
+ root->SetBounds(gfx::Size(10, 10));
+ root->set_needs_context(with_context_);
+ layer_tree_host()->SetRootLayer(root);
+ LayerTreeHostTest::SetupTree();
+ }
+
+ virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
+
+ virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
+ bool expect_context = with_context_;
+ if (delegating_renderer())
+ expect_context = false;
+ EXPECT_EQ(expect_context, !!host_impl->offscreen_context_provider());
+ EndTest();
+ }
+
+ virtual void AfterTest() OVERRIDE {}
+
+ bool with_context_;
+};
+
+class LayerTreeHostTestOffscreenContext_NoContext
+ : public LayerTreeHostTestOffscreenContext {
+ protected:
+ LayerTreeHostTestOffscreenContext_NoContext() { with_context_ = false; }
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestOffscreenContext_NoContext);
+
+class LayerTreeHostTestOffscreenContext_WithContext
+ : public LayerTreeHostTestOffscreenContext {
+ protected:
+ LayerTreeHostTestOffscreenContext_WithContext() { with_context_ = true; }
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestOffscreenContext_WithContext);
+
+class LayerTreeHostTestNoQuadsForEmptyLayer : public LayerTreeHostTest {
+ protected:
+ virtual void SetupTree() OVERRIDE {
+ LayerTreeHostTest::SetupTree();
+ root_layer_ = FakeContentLayer::Create(&client_);
+ root_layer_->SetBounds(gfx::Size(10, 10));
+ root_layer_->SetIsDrawable(false);
+ root_layer_->SetHaveWheelEventHandlers(true);
+ layer_tree_host()->SetRootLayer(root_layer_);
+ LayerTreeHostTest::SetupTree();
+ }
+
+ virtual void BeginTest() OVERRIDE {
+ PostSetNeedsCommitToMainThread();
+ }
+
+ virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
+ FakeContentLayerImpl* layer_impl =
+ static_cast<FakeContentLayerImpl*>(impl->RootLayer());
+ EXPECT_FALSE(layer_impl->DrawsContent());
+ EXPECT_EQ(0u, layer_impl->append_quads_count());
+ }
+
+ virtual void DidCommit() OVERRIDE {
+ // The layer is not drawable, so it should not be updated.
+ EXPECT_EQ(0u, root_layer_->update_count());
+ EndTest();
+ }
+ virtual void AfterTest() OVERRIDE {}
+
+ private:
+ FakeContentLayerClient client_;
+ scoped_refptr<FakeContentLayer> root_layer_;
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestNoQuadsForEmptyLayer);
+
} // namespace
+class LayerTreeHostTestSetMemoryPolicyOnLostOutputSurface
+ : public LayerTreeHostTest {
+ protected:
+ LayerTreeHostTestSetMemoryPolicyOnLostOutputSurface()
+ : first_output_surface_memory_limit_(4321234),
+ second_output_surface_memory_limit_(1234321) {}
+
+ virtual scoped_ptr<OutputSurface> CreateOutputSurface(bool fallback)
+ OVERRIDE {
+ if (!first_context_provider_) {
+ first_context_provider_ = TestContextProvider::Create();
+ } else {
+ EXPECT_FALSE(second_context_provider_);
+ second_context_provider_ = TestContextProvider::Create();
+ }
+
+ scoped_ptr<FakeOutputSurface> output_surface(
+ FakeOutputSurface::Create3d(
+ second_context_provider_ ?
+ second_context_provider_ :
+ first_context_provider_));
+ output_surface->SetMemoryPolicyToSetAtBind(make_scoped_ptr(
+ new ManagedMemoryPolicy(
+ second_context_provider_ ?
+ second_output_surface_memory_limit_ :
+ first_output_surface_memory_limit_,
+ gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE,
+ ManagedMemoryPolicy::kDefaultNumResourcesLimit)));
+ return output_surface.PassAs<OutputSurface>();
+ }
+
+ virtual void SetupTree() OVERRIDE {
+ root_ = FakeContentLayer::Create(&client_);
+ root_->SetBounds(gfx::Size(20, 20));
+ layer_tree_host()->SetRootLayer(root_);
+ LayerTreeHostTest::SetupTree();
+ }
+
+ virtual void BeginTest() OVERRIDE {
+ PostSetNeedsCommitToMainThread();
+ }
+
+ virtual void DidCommitAndDrawFrame() OVERRIDE {
+ // Lost context sometimes takes two frames to recreate. The third frame
+ // is sometimes aborted, so wait until the fourth frame to verify that
+ // the memory has been set, and the fifth frame to end the test.
+ if (layer_tree_host()->source_frame_number() < 5) {
+ layer_tree_host()->SetNeedsCommit();
+ } else if (layer_tree_host()->source_frame_number() == 5) {
+ EndTest();
+ }
+ }
+
+ virtual void SwapBuffersOnThread(LayerTreeHostImpl *impl, bool result)
+ OVERRIDE {
+ switch (impl->active_tree()->source_frame_number()) {
+ case 1:
+ EXPECT_EQ(first_output_surface_memory_limit_,
+ impl->memory_allocation_limit_bytes());
+ // Lose the output surface.
+ first_context_provider_->TestContext3d()->loseContextCHROMIUM(
+ GL_GUILTY_CONTEXT_RESET_ARB,
+ GL_INNOCENT_CONTEXT_RESET_ARB);
+ break;
+ case 4:
+ EXPECT_EQ(second_output_surface_memory_limit_,
+ impl->memory_allocation_limit_bytes());
+ break;
+ }
+ }
+
+ virtual void AfterTest() OVERRIDE {}
+
+ scoped_refptr<TestContextProvider> first_context_provider_;
+ scoped_refptr<TestContextProvider> second_context_provider_;
+ size_t first_output_surface_memory_limit_;
+ size_t second_output_surface_memory_limit_;
+ FakeContentLayerClient client_;
+ scoped_refptr<FakeContentLayer> root_;
+};
+
+// No output to copy for delegated renderers.
+SINGLE_AND_MULTI_THREAD_TEST_F(
+ LayerTreeHostTestSetMemoryPolicyOnLostOutputSurface);
+
+struct TestSwapPromiseResult {
+ TestSwapPromiseResult() : did_swap_called(false),
+ did_not_swap_called(false),
+ dtor_called(false),
+ reason(SwapPromise::DID_NOT_SWAP_UNKNOWN) {
+ }
+
+ bool did_swap_called;
+ bool did_not_swap_called;
+ bool dtor_called;
+ SwapPromise::DidNotSwapReason reason;
+ base::Lock lock;
+};
+
+class TestSwapPromise : public SwapPromise {
+ public:
+ explicit TestSwapPromise(TestSwapPromiseResult* result)
+ : result_(result) {
+ }
+
+ virtual ~TestSwapPromise() {
+ base::AutoLock lock(result_->lock);
+ result_->dtor_called = true;
+ }
+
+ virtual void DidSwap(CompositorFrameMetadata* metadata) OVERRIDE {
+ base::AutoLock lock(result_->lock);
+ EXPECT_FALSE(result_->did_swap_called);
+ EXPECT_FALSE(result_->did_not_swap_called);
+ result_->did_swap_called = true;
+ }
+
+ virtual void DidNotSwap(DidNotSwapReason reason) OVERRIDE {
+ base::AutoLock lock(result_->lock);
+ EXPECT_FALSE(result_->did_swap_called);
+ EXPECT_FALSE(result_->did_not_swap_called);
+ result_->did_not_swap_called = true;
+ result_->reason = reason;
+ }
+
+ private:
+ // Not owned.
+ TestSwapPromiseResult* result_;
+};
+
+class LayerTreeHostTestBreakSwapPromise
+ : public LayerTreeHostTest {
+ protected:
+ LayerTreeHostTestBreakSwapPromise()
+ : commit_count_(0), commit_complete_count_(0) {
+ }
+
+ virtual void WillBeginMainFrame() OVERRIDE {
+ ASSERT_LE(commit_count_, 2);
+ scoped_ptr<SwapPromise> swap_promise(new TestSwapPromise(
+ &swap_promise_result_[commit_count_]));
+ layer_tree_host()->QueueSwapPromise(swap_promise.Pass());
+ }
+
+ virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
+
+ virtual void DidCommit() OVERRIDE {
+ commit_count_++;
+ if (commit_count_ == 2) {
+ // This commit will finish.
+ layer_tree_host()->SetNeedsCommit();
+ }
+ }
+
+ virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
+ commit_complete_count_++;
+ if (commit_complete_count_ == 1) {
+ // This commit will be aborted because no actual update.
+ PostSetNeedsUpdateLayersToMainThread();
+ } else {
+ EndTest();
+ }
+ }
+
+ virtual void AfterTest() OVERRIDE {
+ // 3 commits are scheduled. 2 completes. 1 is aborted.
+ EXPECT_EQ(commit_count_, 3);
+ EXPECT_EQ(commit_complete_count_, 2);
+
+ {
+ // The first commit completes and causes swap buffer which finishes
+ // the promise.
+ base::AutoLock lock(swap_promise_result_[0].lock);
+ EXPECT_TRUE(swap_promise_result_[0].did_swap_called);
+ EXPECT_FALSE(swap_promise_result_[0].did_not_swap_called);
+ EXPECT_TRUE(swap_promise_result_[0].dtor_called);
+ }
+
+ {
+ // The second commit aborts.
+ base::AutoLock lock(swap_promise_result_[1].lock);
+ EXPECT_FALSE(swap_promise_result_[1].did_swap_called);
+ EXPECT_TRUE(swap_promise_result_[1].did_not_swap_called);
+ EXPECT_EQ(SwapPromise::COMMIT_FAILS, swap_promise_result_[1].reason);
+ EXPECT_TRUE(swap_promise_result_[1].dtor_called);
+ }
+
+ {
+ // The last commit completes but it does not cause swap buffer because
+ // there is no damage in the frame data.
+ base::AutoLock lock(swap_promise_result_[2].lock);
+ EXPECT_FALSE(swap_promise_result_[2].did_swap_called);
+ EXPECT_TRUE(swap_promise_result_[2].did_not_swap_called);
+ EXPECT_EQ(SwapPromise::SWAP_FAILS, swap_promise_result_[2].reason);
+ EXPECT_TRUE(swap_promise_result_[2].dtor_called);
+ }
+ }
+
+ int commit_count_;
+ int commit_complete_count_;
+ TestSwapPromiseResult swap_promise_result_[3];
+};
+
+MULTI_THREAD_TEST_F(LayerTreeHostTestBreakSwapPromise);
+
+
+class SimpleSwapPromiseMonitor : public SwapPromiseMonitor {
+ public:
+ SimpleSwapPromiseMonitor(LayerTreeHost* layer_tree_host,
+ LayerTreeHostImpl* layer_tree_host_impl,
+ int* set_needs_commit_count,
+ int* set_needs_redraw_count)
+ : SwapPromiseMonitor(layer_tree_host, layer_tree_host_impl),
+ set_needs_commit_count_(set_needs_commit_count),
+ set_needs_redraw_count_(set_needs_redraw_count) {}
+
+ virtual ~SimpleSwapPromiseMonitor() {}
+
+ virtual void OnSetNeedsCommitOnMain() OVERRIDE {
+ (*set_needs_commit_count_)++;
+ }
+
+ virtual void OnSetNeedsRedrawOnImpl() OVERRIDE {
+ (*set_needs_redraw_count_)++;
+ }
+
+ private:
+ int* set_needs_commit_count_;
+ int* set_needs_redraw_count_;
+};
+
+class LayerTreeHostTestSimpleSwapPromiseMonitor
+ : public LayerTreeHostTest {
+
+ virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
+
+ virtual void WillBeginMainFrame() OVERRIDE {
+ int set_needs_commit_count = 0;
+ int set_needs_redraw_count = 0;
+
+ {
+ scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
+ new SimpleSwapPromiseMonitor(layer_tree_host(),
+ NULL,
+ &set_needs_commit_count,
+ &set_needs_redraw_count));
+ layer_tree_host()->SetNeedsCommit();
+ EXPECT_EQ(1, set_needs_commit_count);
+ EXPECT_EQ(0, set_needs_redraw_count);
+ }
+
+ // Now the monitor is destroyed, SetNeedsCommit() is no longer being
+ // monitored.
+ layer_tree_host()->SetNeedsCommit();
+ EXPECT_EQ(1, set_needs_commit_count);
+ EXPECT_EQ(0, set_needs_redraw_count);
+
+ {
+ scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
+ new SimpleSwapPromiseMonitor(layer_tree_host(),
+ NULL,
+ &set_needs_commit_count,
+ &set_needs_redraw_count));
+ layer_tree_host()->SetNeedsUpdateLayers();
+ EXPECT_EQ(2, set_needs_commit_count);
+ EXPECT_EQ(0, set_needs_redraw_count);
+ }
+
+ {
+ scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
+ new SimpleSwapPromiseMonitor(layer_tree_host(),
+ NULL,
+ &set_needs_commit_count,
+ &set_needs_redraw_count));
+ layer_tree_host()->SetNeedsAnimate();
+ EXPECT_EQ(3, set_needs_commit_count);
+ EXPECT_EQ(0, set_needs_redraw_count);
+ }
+
+ EndTest();
+ }
+
+ virtual void AfterTest() OVERRIDE {}
+};
+
+MULTI_THREAD_TEST_F(LayerTreeHostTestSimpleSwapPromiseMonitor);
+
} // 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 70e2a9ec6d8..22c8965a5fd 100644
--- a/chromium/cc/trees/layer_tree_host_unittest_animation.cc
+++ b/chromium/cc/trees/layer_tree_host_unittest_animation.cc
@@ -6,6 +6,7 @@
#include "cc/animation/animation_curve.h"
#include "cc/animation/layer_animation_controller.h"
+#include "cc/animation/scroll_offset_animation_curve.h"
#include "cc/animation/timing_function.h"
#include "cc/layers/layer.h"
#include "cc/layers/layer_impl.h"
@@ -115,8 +116,7 @@ class LayerTreeHostAnimationTestAddAnimation
public:
LayerTreeHostAnimationTestAddAnimation()
: num_animates_(0),
- received_animation_started_notification_(false),
- start_time_(0.0) {
+ received_animation_started_notification_(false) {
}
virtual void BeginTest() OVERRIDE {
@@ -135,7 +135,7 @@ class LayerTreeHostAnimationTestAddAnimation
}
if (received_animation_started_notification_) {
- EXPECT_LT(0.0, start_time_);
+ EXPECT_LT(base::TimeTicks(), start_time_);
LayerAnimationController* controller_impl =
host_impl->active_tree()->root_layer()->layer_animation_controller();
@@ -148,11 +148,14 @@ class LayerTreeHostAnimationTestAddAnimation
}
}
- virtual void NotifyAnimationStarted(double wall_clock_time) OVERRIDE {
+ virtual void NotifyAnimationStarted(
+ double wall_clock_time,
+ base::TimeTicks monotonic_time,
+ Animation::TargetProperty target_property) OVERRIDE {
received_animation_started_notification_ = true;
- start_time_ = wall_clock_time;
+ start_time_ = monotonic_time;
if (num_animates_) {
- EXPECT_LT(0.0, start_time_);
+ EXPECT_LT(base::TimeTicks(), start_time_);
LayerAnimationController* controller =
layer_tree_host()->root_layer()->layer_animation_controller();
@@ -170,7 +173,7 @@ class LayerTreeHostAnimationTestAddAnimation
private:
int num_animates_;
bool received_animation_started_notification_;
- double start_time_;
+ base::TimeTicks start_time_;
};
SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestAddAnimation);
@@ -239,7 +242,10 @@ class LayerTreeHostAnimationTestAnimationsGetDeleted
EndTest();
}
- virtual void NotifyAnimationFinished(double time) OVERRIDE {
+ virtual void NotifyAnimationFinished(
+ double wall_clock_time,
+ base::TimeTicks monotonic_time,
+ Animation::TargetProperty target_property) OVERRIDE {
// Animations on the impl-side controller only get deleted during a commit,
// so we need to schedule a commit.
layer_tree_host()->SetNeedsCommit();
@@ -261,7 +267,7 @@ class LayerTreeHostAnimationTestTickAnimationWhileBackgrounded
: num_animates_(0) {}
virtual void BeginTest() OVERRIDE {
- PostAddAnimationToMainThread(layer_tree_host()->root_layer());
+ PostAddLongAnimationToMainThread(layer_tree_host()->root_layer());
}
// Use WillAnimateLayers to set visible false before the animation runs and
@@ -309,7 +315,10 @@ class LayerTreeHostAnimationTestNoBackgroundTickingWithoutActiveTree
PostAddAnimationToMainThread(layer_tree_host()->root_layer());
}
- virtual void NotifyAnimationFinished(double time) OVERRIDE {
+ virtual void NotifyAnimationFinished(
+ double wall_clock_time,
+ base::TimeTicks monotonic_time,
+ Animation::TargetProperty target_property) OVERRIDE {
// Replace animated commits with an empty tree.
layer_tree_host()->SetRootLayer(make_scoped_refptr<Layer>(NULL));
}
@@ -375,14 +384,17 @@ class LayerTreeHostAnimationTestNoBackgroundTickingWithoutActiveTree
// Verify that commits are actually alternating with empty / non-empty
// trees.
- switch (host_impl->active_tree()->source_frame_number()) {
+ int frame_number = host_impl->active_tree()->source_frame_number();
+ switch (frame_number) {
case 0:
case 2:
- EXPECT_TRUE(host_impl->active_tree()->root_layer());
+ EXPECT_TRUE(host_impl->active_tree()->root_layer())
+ << "frame: " << frame_number;
break;
case 1:
case 3:
- EXPECT_FALSE(host_impl->active_tree()->root_layer());
+ EXPECT_FALSE(host_impl->active_tree()->root_layer())
+ << "frame: " << frame_number;
break;
}
@@ -496,7 +508,10 @@ class LayerTreeHostAnimationTestSynchronizeAnimationStartTimes
PostAddAnimationToMainThread(content_.get());
}
- virtual void NotifyAnimationStarted(double time) OVERRIDE {
+ virtual void NotifyAnimationStarted(
+ double wall_clock_time,
+ base::TimeTicks monotonic_time,
+ Animation::TargetProperty target_property) OVERRIDE {
LayerAnimationController* controller =
layer_tree_host()->root_layer()->children()[0]->
layer_animation_controller();
@@ -551,7 +566,10 @@ class LayerTreeHostAnimationTestAnimationFinishedEvents
PostAddInstantAnimationToMainThread(layer_tree_host()->root_layer());
}
- virtual void NotifyAnimationFinished(double time) OVERRIDE {
+ virtual void NotifyAnimationFinished(
+ double wall_clock_time,
+ base::TimeTicks monotonic_time,
+ Animation::TargetProperty target_property) OVERRIDE {
LayerAnimationController* controller =
layer_tree_host()->root_layer()->layer_animation_controller();
Animation* animation =
@@ -767,11 +785,17 @@ class LayerTreeHostAnimationTestRunAnimationWhenNotCanDraw
PostAddAnimationToMainThread(content_.get());
}
- virtual void NotifyAnimationStarted(double wall_clock_time) OVERRIDE {
+ virtual void NotifyAnimationStarted(
+ double wall_clock_time,
+ base::TimeTicks monotonic_time,
+ Animation::TargetProperty target_property) OVERRIDE {
started_times_++;
}
- virtual void NotifyAnimationFinished(double wall_clock_time) OVERRIDE {
+ virtual void NotifyAnimationFinished(
+ double wall_clock_time,
+ base::TimeTicks monotonic_time,
+ Animation::TargetProperty target_property) OVERRIDE {
EndTest();
}
@@ -813,12 +837,18 @@ class LayerTreeHostAnimationTestRunAnimationWhenNotVisible
layer_tree_host()->SetVisible(false);
}
- virtual void NotifyAnimationStarted(double wall_clock_time) OVERRIDE {
+ virtual void NotifyAnimationStarted(
+ double wall_clock_time,
+ base::TimeTicks monotonic_time,
+ Animation::TargetProperty target_property) OVERRIDE {
EXPECT_FALSE(visible_);
started_times_++;
}
- virtual void NotifyAnimationFinished(double wall_clock_time) OVERRIDE {
+ virtual void NotifyAnimationFinished(
+ double wall_clock_time,
+ base::TimeTicks monotonic_time,
+ Animation::TargetProperty target_property) OVERRIDE {
EXPECT_FALSE(visible_);
EXPECT_EQ(1, started_times_);
EndTest();
@@ -863,13 +893,6 @@ class LayerTreeHostAnimationTestCheckerboardDoesntStartAnimations
PostSetNeedsCommitToMainThread();
}
- virtual void DispatchAddInstantAnimation(Layer* layer_to_receive_animation)
- OVERRIDE {
- LayerTreeHostAnimationTest::DispatchAddInstantAnimation(
- layer_to_receive_animation);
- added_animations_++;
- }
-
virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
LayerTreeHostImpl::FrameData* frame_data,
bool result) OVERRIDE {
@@ -897,13 +920,19 @@ class LayerTreeHostAnimationTestCheckerboardDoesntStartAnimations
}
}
- virtual void NotifyAnimationStarted(double wall_clock_time) OVERRIDE {
+ virtual void NotifyAnimationStarted(
+ double wall_clock_time,
+ base::TimeTicks monotonic_time,
+ Animation::TargetProperty target_property) OVERRIDE {
if (TestEnded())
return;
started_times_++;
}
- virtual void NotifyAnimationFinished(double wall_clock_time) OVERRIDE {
+ virtual void NotifyAnimationFinished(
+ double wall_clock_time,
+ base::TimeTicks monotonic_time,
+ Animation::TargetProperty target_property) OVERRIDE {
// We should be checkerboarding already, but it should still finish the
// first animation.
EXPECT_EQ(2, added_animations_);
@@ -932,5 +961,57 @@ class LayerTreeHostAnimationTestCheckerboardDoesntStartAnimations
MULTI_THREAD_TEST_F(
LayerTreeHostAnimationTestCheckerboardDoesntStartAnimations);
+// Verifies that when scroll offset is animated on the impl thread, updates
+// are sent back to the main thread.
+class LayerTreeHostAnimationTestScrollOffsetChangesArePropagated
+ : public LayerTreeHostAnimationTest {
+ public:
+ LayerTreeHostAnimationTestScrollOffsetChangesArePropagated() {}
+
+ virtual void SetupTree() OVERRIDE {
+ LayerTreeHostAnimationTest::SetupTree();
+
+ scroll_layer_ = FakeContentLayer::Create(&client_);
+ scroll_layer_->SetScrollable(true);
+ scroll_layer_->SetBounds(gfx::Size(1000, 1000));
+ scroll_layer_->SetScrollOffset(gfx::Vector2d(10, 20));
+ layer_tree_host()->root_layer()->AddChild(scroll_layer_);
+ }
+
+ virtual void BeginTest() OVERRIDE {
+ PostSetNeedsCommitToMainThread();
+ }
+
+ virtual void DidCommit() OVERRIDE {
+ switch (layer_tree_host()->source_frame_number()) {
+ case 1: {
+ scoped_ptr<ScrollOffsetAnimationCurve> curve(
+ ScrollOffsetAnimationCurve::Create(
+ gfx::Vector2dF(500.f, 550.f),
+ EaseInOutTimingFunction::Create()));
+ scoped_ptr<Animation> animation(Animation::Create(
+ curve.PassAs<AnimationCurve>(), 1, 0, Animation::ScrollOffset));
+ animation->set_needs_synchronized_start_time(true);
+ scroll_layer_->AddAnimation(animation.Pass());
+ break;
+ }
+ default:
+ if (scroll_layer_->scroll_offset().x() > 10 &&
+ scroll_layer_->scroll_offset().y() > 20)
+ EndTest();
+ }
+ }
+
+ virtual void AfterTest() OVERRIDE {}
+
+ private:
+ FakeContentLayerClient client_;
+ scoped_refptr<FakeContentLayer> scroll_layer_;
+};
+
+// SingleThreadProxy doesn't send scroll updates from LayerTreeHostImpl to
+// LayerTreeHost.
+MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestScrollOffsetChangesArePropagated);
+
} // 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 18683e826b6..7112436595d 100644
--- a/chromium/cc/trees/layer_tree_host_unittest_context.cc
+++ b/chromium/cc/trees/layer_tree_host_unittest_context.cc
@@ -5,9 +5,9 @@
#include "cc/trees/layer_tree_host.h"
#include "base/basictypes.h"
-#include "cc/debug/test_context_provider.h"
-#include "cc/debug/test_web_graphics_context_3d.h"
#include "cc/layers/content_layer.h"
+#include "cc/layers/delegated_frame_provider.h"
+#include "cc/layers/delegated_frame_resource_collection.h"
#include "cc/layers/heads_up_display_layer.h"
#include "cc/layers/io_surface_layer.h"
#include "cc/layers/layer_impl.h"
@@ -25,12 +25,15 @@
#include "cc/test/fake_delegated_renderer_layer_impl.h"
#include "cc/test/fake_layer_tree_host_client.h"
#include "cc/test/fake_output_surface.h"
+#include "cc/test/fake_output_surface_client.h"
#include "cc/test/fake_painted_scrollbar_layer.h"
#include "cc/test/fake_scoped_ui_resource.h"
#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/test_context_provider.h"
+#include "cc/test/test_web_graphics_context_3d.h"
#include "cc/trees/layer_tree_host_impl.h"
#include "cc/trees/layer_tree_impl.h"
#include "cc/trees/single_thread_proxy.h"
@@ -38,7 +41,7 @@
#include "media/base/media.h"
using media::VideoFrame;
-using WebKit::WebGraphicsContext3D;
+using blink::WebGraphicsContext3D;
namespace cc {
namespace {
@@ -50,13 +53,9 @@ class LayerTreeHostContextTest : public LayerTreeTest {
: LayerTreeTest(),
context3d_(NULL),
times_to_fail_create_(0),
- times_to_fail_initialize_(0),
- times_to_lose_on_create_(0),
times_to_lose_during_commit_(0),
times_to_lose_during_draw_(0),
times_to_fail_recreate_(0),
- times_to_fail_reinitialize_(0),
- times_to_lose_on_recreate_(0),
times_to_fail_create_offscreen_(0),
times_to_fail_recreate_offscreen_(0),
times_to_expect_create_failed_(0),
@@ -94,19 +93,6 @@ class LayerTreeHostContextTest : public LayerTreeTest {
context3d_->set_have_extension_egl_image(true);
}
- if (times_to_fail_initialize_ && !(fallback && fallback_context_works_)) {
- --times_to_fail_initialize_;
- // Make the context get lost during reinitialization.
- // The number of times MakeCurrent succeeds is not important, and
- // can be changed if needed to make this pass with future changes.
- context3d_->set_times_make_current_succeeds(2);
- ExpectCreateToFail();
- } else if (times_to_lose_on_create_) {
- --times_to_lose_on_create_;
- LoseContext();
- ExpectCreateToFail();
- }
-
if (delegating_renderer()) {
return FakeOutputSurface::CreateDelegating3d(context3d.Pass())
.PassAs<OutputSurface>();
@@ -135,35 +121,13 @@ class LayerTreeHostContextTest : public LayerTreeTest {
return offscreen_context3d.Pass();
}
- virtual scoped_refptr<cc::ContextProvider>
- OffscreenContextProviderForMainThread() OVERRIDE {
- DCHECK(!HasImplThread());
-
- if (!offscreen_contexts_main_thread_.get() ||
- offscreen_contexts_main_thread_->DestroyedOnMainThread()) {
- offscreen_contexts_main_thread_ =
- TestContextProvider::Create(
- base::Bind(&LayerTreeHostContextTest::CreateOffscreenContext3d,
- base::Unretained(this)));
- if (offscreen_contexts_main_thread_ &&
- !offscreen_contexts_main_thread_->BindToCurrentThread())
- offscreen_contexts_main_thread_ = NULL;
- }
- return offscreen_contexts_main_thread_;
- }
-
- virtual scoped_refptr<cc::ContextProvider>
- OffscreenContextProviderForCompositorThread() OVERRIDE {
- DCHECK(HasImplThread());
-
- if (!offscreen_contexts_compositor_thread_.get() ||
- offscreen_contexts_compositor_thread_->DestroyedOnMainThread()) {
- offscreen_contexts_compositor_thread_ =
- TestContextProvider::Create(
- base::Bind(&LayerTreeHostContextTest::CreateOffscreenContext3d,
- base::Unretained(this)));
+ virtual scoped_refptr<ContextProvider> OffscreenContextProvider() OVERRIDE {
+ if (!offscreen_contexts_.get() ||
+ offscreen_contexts_->DestroyedOnMainThread()) {
+ offscreen_contexts_ =
+ TestContextProvider::Create(CreateOffscreenContext3d());
}
- return offscreen_contexts_compositor_thread_;
+ return offscreen_contexts_;
}
virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
@@ -174,14 +138,10 @@ class LayerTreeHostContextTest : public LayerTreeTest {
return result;
--times_to_lose_during_draw_;
- context3d_->set_times_make_current_succeeds(0);
+ LoseContext();
times_to_fail_create_ = times_to_fail_recreate_;
times_to_fail_recreate_ = 0;
- times_to_fail_initialize_ = times_to_fail_reinitialize_;
- times_to_fail_reinitialize_ = 0;
- times_to_lose_on_create_ = times_to_lose_on_recreate_;
- times_to_lose_on_recreate_ = 0;
times_to_fail_create_offscreen_ = times_to_fail_recreate_offscreen_;
times_to_fail_recreate_offscreen_ = 0;
@@ -198,10 +158,6 @@ class LayerTreeHostContextTest : public LayerTreeTest {
times_to_fail_create_ = times_to_fail_recreate_;
times_to_fail_recreate_ = 0;
- times_to_fail_initialize_ = times_to_fail_reinitialize_;
- times_to_fail_reinitialize_ = 0;
- times_to_lose_on_create_ = times_to_lose_on_recreate_;
- times_to_lose_on_recreate_ = 0;
times_to_fail_create_offscreen_ = times_to_fail_recreate_offscreen_;
times_to_fail_recreate_offscreen_ = 0;
}
@@ -222,13 +178,9 @@ class LayerTreeHostContextTest : public LayerTreeTest {
protected:
TestWebGraphicsContext3D* context3d_;
int times_to_fail_create_;
- int times_to_fail_initialize_;
- int times_to_lose_on_create_;
int times_to_lose_during_commit_;
int times_to_lose_during_draw_;
int times_to_fail_recreate_;
- int times_to_fail_reinitialize_;
- int times_to_lose_on_recreate_;
int times_to_fail_create_offscreen_;
int times_to_fail_recreate_offscreen_;
int times_to_expect_create_failed_;
@@ -238,8 +190,7 @@ class LayerTreeHostContextTest : public LayerTreeTest {
bool context_should_support_io_surface_;
bool fallback_context_works_;
- scoped_refptr<TestContextProvider> offscreen_contexts_main_thread_;
- scoped_refptr<TestContextProvider> offscreen_contexts_compositor_thread_;
+ scoped_refptr<TestContextProvider> offscreen_contexts_;
};
class LayerTreeHostContextTestLostContextSucceeds
@@ -249,6 +200,7 @@ class LayerTreeHostContextTestLostContextSucceeds
: LayerTreeHostContextTest(),
test_case_(0),
num_losses_(0),
+ num_losses_last_test_case_(-1),
recovered_context_(true),
first_initialized_(false) {}
@@ -267,10 +219,7 @@ class LayerTreeHostContextTestLostContextSucceeds
recovered_context_ = true;
}
- virtual void AfterTest() OVERRIDE {
- EXPECT_EQ(11u, test_case_);
- EXPECT_EQ(8 + 10 + 10 + 1, num_losses_);
- }
+ virtual void AfterTest() OVERRIDE { EXPECT_EQ(9u, test_case_); }
virtual void DidCommitAndDrawFrame() OVERRIDE {
// If the last frame had a context loss, then we'll commit again to
@@ -301,65 +250,37 @@ class LayerTreeHostContextTestLostContextSucceeds
// immediately) a small number of times should succeed.
{ 1, // times_to_lose_during_commit
0, // times_to_lose_during_draw
- 3, // times_to_fail_reinitialize
0, // times_to_fail_recreate
- 0, // times_to_lose_on_recreate
0, // times_to_fail_recreate_offscreen
false, // fallback_context_works
},
{ 0, // times_to_lose_during_commit
1, // times_to_lose_during_draw
- 3, // times_to_fail_reinitialize
0, // times_to_fail_recreate
- 0, // times_to_lose_on_recreate
0, // times_to_fail_recreate_offscreen
false, // fallback_context_works
},
{ 1, // times_to_lose_during_commit
0, // times_to_lose_during_draw
- 0, // times_to_fail_reinitialize
3, // times_to_fail_recreate
- 0, // times_to_lose_on_recreate
0, // times_to_fail_recreate_offscreen
false, // fallback_context_works
},
{ 0, // times_to_lose_during_commit
1, // times_to_lose_during_draw
- 0, // times_to_fail_reinitialize
3, // times_to_fail_recreate
- 0, // times_to_lose_on_recreate
0, // times_to_fail_recreate_offscreen
false, // fallback_context_works
},
{ 1, // times_to_lose_during_commit
0, // times_to_lose_during_draw
- 0, // times_to_fail_reinitialize
- 0, // times_to_fail_recreate
- 3, // times_to_lose_on_recreate
- 0, // times_to_fail_recreate_offscreen
- false, // fallback_context_works
- },
- { 0, // times_to_lose_during_commit
- 1, // times_to_lose_during_draw
- 0, // times_to_fail_reinitialize
0, // times_to_fail_recreate
- 3, // times_to_lose_on_recreate
- 0, // times_to_fail_recreate_offscreen
- false, // fallback_context_works
- },
- { 1, // times_to_lose_during_commit
- 0, // times_to_lose_during_draw
- 0, // times_to_fail_reinitialize
- 0, // times_to_fail_recreate
- 0, // times_to_lose_on_recreate
3, // times_to_fail_recreate_offscreen
false, // fallback_context_works
},
{ 0, // times_to_lose_during_commit
1, // times_to_lose_during_draw
- 0, // times_to_fail_reinitialize
0, // times_to_fail_recreate
- 0, // times_to_lose_on_recreate
3, // times_to_fail_recreate_offscreen
false, // fallback_context_works
},
@@ -367,17 +288,13 @@ class LayerTreeHostContextTestLostContextSucceeds
// succeed.
{ 10, // times_to_lose_during_commit
0, // times_to_lose_during_draw
- 0, // times_to_fail_reinitialize
0, // times_to_fail_recreate
- 0, // times_to_lose_on_recreate
0, // times_to_fail_recreate_offscreen
false, // fallback_context_works
},
{ 0, // times_to_lose_during_commit
10, // times_to_lose_during_draw
- 0, // times_to_fail_reinitialize
0, // times_to_fail_recreate
- 0, // times_to_lose_on_recreate
0, // times_to_fail_recreate_offscreen
false, // fallback_context_works
},
@@ -385,9 +302,7 @@ class LayerTreeHostContextTestLostContextSucceeds
// context should work.
{ 0, // times_to_lose_during_commit
1, // times_to_lose_during_draw
- 10, // times_to_fail_reinitialize
0, // times_to_fail_recreate
- 0, // times_to_lose_on_recreate
0, // times_to_fail_recreate_offscreen
true, // fallback_context_works
},
@@ -395,14 +310,16 @@ class LayerTreeHostContextTestLostContextSucceeds
if (test_case_ >= arraysize(kTests))
return false;
+ // Make sure that we lost our context at least once in the last test run so
+ // the test did something.
+ EXPECT_GT(num_losses_, num_losses_last_test_case_);
+ num_losses_last_test_case_ = num_losses_;
times_to_lose_during_commit_ =
kTests[test_case_].times_to_lose_during_commit;
times_to_lose_during_draw_ =
kTests[test_case_].times_to_lose_during_draw;
- times_to_fail_reinitialize_ = kTests[test_case_].times_to_fail_reinitialize;
times_to_fail_recreate_ = kTests[test_case_].times_to_fail_recreate;
- times_to_lose_on_recreate_ = kTests[test_case_].times_to_lose_on_recreate;
times_to_fail_recreate_offscreen_ =
kTests[test_case_].times_to_fail_recreate_offscreen;
fallback_context_works_ = kTests[test_case_].fallback_context_works;
@@ -413,9 +330,7 @@ class LayerTreeHostContextTestLostContextSucceeds
struct TestCase {
int times_to_lose_during_commit;
int times_to_lose_during_draw;
- int times_to_fail_reinitialize;
int times_to_fail_recreate;
- int times_to_lose_on_recreate;
int times_to_fail_recreate_offscreen;
bool fallback_context_works;
};
@@ -423,6 +338,7 @@ class LayerTreeHostContextTestLostContextSucceeds
protected:
size_t test_case_;
int num_losses_;
+ int num_losses_last_test_case_;
bool recovered_context_;
bool first_initialized_;
};
@@ -476,7 +392,7 @@ class LayerTreeHostContextTestLostContextSucceedsWithContent
// the active context.
EXPECT_TRUE(content_impl->HaveResourceForTileAt(0, 0));
- cc::ContextProvider* contexts = host_impl->offscreen_context_provider();
+ ContextProvider* contexts = host_impl->offscreen_context_provider();
if (use_surface_) {
ASSERT_TRUE(contexts);
EXPECT_TRUE(contexts->Context3d());
@@ -491,13 +407,11 @@ class LayerTreeHostContextTestLostContextSucceedsWithContent
LayerTreeHostContextTestLostContextSucceeds::AfterTest();
if (use_surface_) {
// 1 create to start with +
- // 6 from test cases that fail on initializing the renderer (after the
- // offscreen context is created) +
- // 6 from test cases that lose the offscreen context directly +
- // 4 from test cases that create a fallback +
+ // 4 from test cases that lose the offscreen context directly +
+ // 2 from test cases that create a fallback +
// All the test cases that recreate both contexts only once
// per time it is lost.
- EXPECT_EQ(6 + 6 + 1 + 4 + num_losses_, times_offscreen_created_);
+ EXPECT_EQ(4 + 1 + 2 + num_losses_, times_offscreen_created_);
} else {
EXPECT_EQ(0, times_offscreen_created_);
}
@@ -529,23 +443,11 @@ TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent,
}
TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent,
- NoSurface_MultiThread_DirectRenderer_ImplSidePaint) {
- use_surface_ = false;
- RunTest(true, false, true);
-}
-
-TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent,
NoSurface_MultiThread_DelegatingRenderer_MainThreadPaint) {
use_surface_ = false;
RunTest(true, true, false);
}
-TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent,
- NoSurface_MultiThread_DelegatingRenderer_ImplSidePaint) {
- use_surface_ = false;
- RunTest(true, true, true);
-}
-
// Surfaces don't exist with a delegating renderer.
TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent,
WithSurface_SingleThread_DirectRenderer) {
@@ -559,12 +461,6 @@ TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent,
RunTest(true, false, false);
}
-TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent,
- WithSurface_MultiThread_DirectRenderer_ImplSidePaint) {
- use_surface_ = true;
- RunTest(true, false, true);
-}
-
class LayerTreeHostContextTestOffscreenContextFails
: public LayerTreeHostContextTest {
public:
@@ -597,7 +493,7 @@ class LayerTreeHostContextTestOffscreenContextFails
}
virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
- cc::ContextProvider* contexts = host_impl->offscreen_context_provider();
+ ContextProvider* contexts = host_impl->offscreen_context_provider();
EXPECT_FALSE(contexts);
// This did not lead to create failure.
@@ -663,180 +559,6 @@ class LayerTreeHostContextTestLostContextFails
bool first_initialized_;
};
-TEST_F(LayerTreeHostContextTestLostContextFails,
- FailReinitialize100_SingleThread_DirectRenderer) {
- times_to_fail_reinitialize_ = 100;
- times_to_fail_recreate_ = 0;
- times_to_lose_on_recreate_ = 0;
- RunTest(false, false, false);
-}
-
-TEST_F(LayerTreeHostContextTestLostContextFails,
- FailReinitialize100_SingleThread_DelegatingRenderer) {
- times_to_fail_reinitialize_ = 100;
- times_to_fail_recreate_ = 0;
- times_to_lose_on_recreate_ = 0;
- RunTest(false, true, false);
-}
-
-TEST_F(LayerTreeHostContextTestLostContextFails,
- FailReinitialize100_MultiThread_DirectRenderer_MainThreadPaint) {
- times_to_fail_reinitialize_ = 100;
- times_to_fail_recreate_ = 0;
- times_to_lose_on_recreate_ = 0;
- RunTest(true, false, false);
-}
-
-TEST_F(LayerTreeHostContextTestLostContextFails,
- FailReinitialize100_MultiThread_DirectRenderer_ImplSidePaint) {
- times_to_fail_reinitialize_ = 100;
- times_to_fail_recreate_ = 0;
- times_to_lose_on_recreate_ = 0;
- RunTest(true, false, true);
-}
-
-TEST_F(LayerTreeHostContextTestLostContextFails,
- FailReinitialize100_MultiThread_DelegatingRenderer_MainThreadPaint) {
- times_to_fail_reinitialize_ = 100;
- times_to_fail_recreate_ = 0;
- times_to_lose_on_recreate_ = 0;
- RunTest(true, true, false);
-}
-
-TEST_F(LayerTreeHostContextTestLostContextFails,
- FailReinitialize100_MultiThread_DelegatingRenderer_ImplSidePaint) {
- times_to_fail_reinitialize_ = 100;
- times_to_fail_recreate_ = 0;
- times_to_lose_on_recreate_ = 0;
- RunTest(true, true, true);
-}
-
-TEST_F(LayerTreeHostContextTestLostContextFails,
- FailRecreate100_SingleThread_DirectRenderer) {
- times_to_fail_reinitialize_ = 0;
- times_to_fail_recreate_ = 100;
- times_to_lose_on_recreate_ = 0;
- RunTest(false, false, false);
-}
-
-TEST_F(LayerTreeHostContextTestLostContextFails,
- FailRecreate100_SingleThread_DelegatingRenderer) {
- times_to_fail_reinitialize_ = 0;
- times_to_fail_recreate_ = 100;
- times_to_lose_on_recreate_ = 0;
- RunTest(false, true, false);
-}
-
-TEST_F(LayerTreeHostContextTestLostContextFails,
- FailRecreate100_MultiThread_DirectRenderer_MainThreadPaint) {
- times_to_fail_reinitialize_ = 0;
- times_to_fail_recreate_ = 100;
- times_to_lose_on_recreate_ = 0;
- RunTest(true, false, false);
-}
-
-TEST_F(LayerTreeHostContextTestLostContextFails,
- FailRecreate100_MultiThread_DirectRenderer_ImplSidePaint) {
- times_to_fail_reinitialize_ = 0;
- times_to_fail_recreate_ = 100;
- times_to_lose_on_recreate_ = 0;
- RunTest(true, false, true);
-}
-
-TEST_F(LayerTreeHostContextTestLostContextFails,
- FailRecreate100_MultiThread_DelegatingRenderer_MainThreadPaint) {
- times_to_fail_reinitialize_ = 0;
- times_to_fail_recreate_ = 100;
- times_to_lose_on_recreate_ = 0;
- RunTest(true, true, false);
-}
-
-TEST_F(LayerTreeHostContextTestLostContextFails,
- FailRecreate100_MultiThread_DelegatingRenderer_ImplSidePaint) {
- times_to_fail_reinitialize_ = 0;
- times_to_fail_recreate_ = 100;
- times_to_lose_on_recreate_ = 0;
- RunTest(true, true, true);
-}
-
-TEST_F(LayerTreeHostContextTestLostContextFails,
- LoseOnRecreate100_SingleThread_DirectRenderer) {
- times_to_fail_reinitialize_ = 0;
- times_to_fail_recreate_ = 0;
- times_to_lose_on_recreate_ = 100;
- RunTest(false, false, false);
-}
-
-TEST_F(LayerTreeHostContextTestLostContextFails,
- LoseOnRecreate100_SingleThread_DelegatingRenderer) {
- times_to_fail_reinitialize_ = 0;
- times_to_fail_recreate_ = 0;
- times_to_lose_on_recreate_ = 100;
- RunTest(false, true, false);
-}
-
-TEST_F(LayerTreeHostContextTestLostContextFails,
- LoseOnRecreate100_MultiThread_DirectRenderer_MainThreadPaint) {
- times_to_fail_reinitialize_ = 0;
- times_to_fail_recreate_ = 0;
- times_to_lose_on_recreate_ = 100;
- RunTest(true, false, false);
-}
-
-TEST_F(LayerTreeHostContextTestLostContextFails,
- LoseOnRecreate100_MultiThread_DirectRenderer_ImplSidePaint) {
- times_to_fail_reinitialize_ = 0;
- times_to_fail_recreate_ = 0;
- times_to_lose_on_recreate_ = 100;
- RunTest(true, false, true);
-}
-
-TEST_F(LayerTreeHostContextTestLostContextFails,
- LoseOnRecreate100_MultiThread_DelegatingRenderer_MainThreadPaint) {
- times_to_fail_reinitialize_ = 0;
- times_to_fail_recreate_ = 0;
- times_to_lose_on_recreate_ = 100;
- RunTest(true, true, false);
-}
-
-TEST_F(LayerTreeHostContextTestLostContextFails,
- LoseOnRecreate100_MultiThread_DelegatingRenderer_ImplSidePaint) {
- times_to_fail_reinitialize_ = 0;
- times_to_fail_recreate_ = 0;
- times_to_lose_on_recreate_ = 100;
- RunTest(true, true, true);
-}
-
-class LayerTreeHostContextTestFinishAllRenderingAfterLoss
- : public LayerTreeHostContextTest {
- public:
- virtual void BeginTest() OVERRIDE {
- // Lose the context until the compositor gives up on it.
- first_initialized_ = false;
- times_to_lose_during_commit_ = 1;
- times_to_fail_reinitialize_ = 10;
- PostSetNeedsCommitToMainThread();
- }
-
- virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE {
- if (first_initialized_) {
- EXPECT_FALSE(succeeded);
- layer_tree_host()->FinishAllRendering();
- EndTest();
- } else {
- first_initialized_ = true;
- }
- }
-
- virtual void AfterTest() OVERRIDE {}
-
- private:
- bool first_initialized_;
-};
-
-SINGLE_AND_MULTI_THREAD_TEST_F(
- LayerTreeHostContextTestFinishAllRenderingAfterLoss);
-
class LayerTreeHostContextTestLostContextAndEvictTextures
: public LayerTreeHostContextTest {
public:
@@ -927,19 +649,14 @@ TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
}
TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
- LoseAfterEvict_MultiThread_DirectRenderer_ImplSidePaint) {
- lose_after_evict_ = true;
- RunTest(true, false, true);
-}
-
-TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
LoseAfterEvict_MultiThread_DelegatingRenderer_MainThreadPaint) {
lose_after_evict_ = true;
RunTest(true, true, false);
}
+// Flaky on all platforms, http://crbug.com/310979
TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
- LoseAfterEvict_MultiThread_DelegatingRenderer_ImplSidePaint) {
+ DISABLED_LoseAfterEvict_MultiThread_DelegatingRenderer_ImplSidePaint) {
lose_after_evict_ = true;
RunTest(true, true, true);
}
@@ -1017,8 +734,8 @@ class LayerTreeHostContextTestLostContextWhileUpdatingResources
PostSetNeedsCommitToMainThread();
}
- virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
- LayerTreeHostContextTest::CommitCompleteOnThread(impl);
+ virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
+ EXPECT_EQ(0, times_to_lose_on_end_query_);
EndTest();
}
@@ -1037,7 +754,7 @@ class LayerTreeHostContextTestLostContextWhileUpdatingResources
int times_to_lose_on_end_query_;
};
-SINGLE_AND_MULTI_THREAD_TEST_F(
+SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F(
LayerTreeHostContextTestLostContextWhileUpdatingResources);
class LayerTreeHostContextTestLayersNotified
@@ -1084,25 +801,9 @@ class LayerTreeHostContextTestLayersNotified
times_to_fail_create_ = 1;
break;
case 2:
- EXPECT_EQ(1u, root->lost_output_surface_count());
- EXPECT_EQ(1u, child->lost_output_surface_count());
- EXPECT_EQ(1u, grandchild->lost_output_surface_count());
- // Lose the context and again during recreate.
- LoseContext();
- times_to_lose_on_create_ = 1;
- break;
- case 3:
- EXPECT_EQ(3u, root->lost_output_surface_count());
- EXPECT_EQ(3u, child->lost_output_surface_count());
- EXPECT_EQ(3u, grandchild->lost_output_surface_count());
- // Lose the context and again during reinitialization.
- LoseContext();
- times_to_fail_initialize_ = 1;
- break;
- case 4:
- EXPECT_EQ(5u, root->lost_output_surface_count());
- EXPECT_EQ(5u, child->lost_output_surface_count());
- EXPECT_EQ(5u, grandchild->lost_output_surface_count());
+ EXPECT_GE(1u, root->lost_output_surface_count());
+ EXPECT_GE(1u, child->lost_output_surface_count());
+ EXPECT_GE(1u, grandchild->lost_output_surface_count());
EndTest();
break;
default:
@@ -1126,72 +827,165 @@ SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestLayersNotified);
class LayerTreeHostContextTestDontUseLostResources
: public LayerTreeHostContextTest {
public:
- virtual void SetupTree() OVERRIDE {
- scoped_refptr<Layer> root_ = Layer::Create();
- root_->SetBounds(gfx::Size(10, 10));
- root_->SetAnchorPoint(gfx::PointF());
- root_->SetIsDrawable(true);
+ LayerTreeHostContextTestDontUseLostResources()
+ : lost_context_(false) {
+ context_should_support_io_surface_ = true;
- scoped_refptr<FakeDelegatedRendererLayer> delegated_ =
- FakeDelegatedRendererLayer::Create(NULL);
- delegated_->SetBounds(gfx::Size(10, 10));
- delegated_->SetAnchorPoint(gfx::PointF());
- delegated_->SetIsDrawable(true);
- root_->AddChild(delegated_);
+ child_output_surface_ = FakeOutputSurface::Create3d();
+ child_output_surface_->BindToClient(&output_surface_client_);
+ child_resource_provider_ =
+ ResourceProvider::Create(child_output_surface_.get(),
+ NULL,
+ 0,
+ false,
+ 1);
+ }
- scoped_refptr<ContentLayer> content_ = ContentLayer::Create(&client_);
- content_->SetBounds(gfx::Size(10, 10));
- content_->SetAnchorPoint(gfx::PointF());
- content_->SetIsDrawable(true);
- root_->AddChild(content_);
+ static void EmptyReleaseCallback(unsigned sync_point, bool lost) {}
- scoped_refptr<TextureLayer> texture_ = TextureLayer::Create(NULL);
- texture_->SetBounds(gfx::Size(10, 10));
- texture_->SetAnchorPoint(gfx::PointF());
- texture_->SetIsDrawable(true);
- root_->AddChild(texture_);
+ virtual void SetupTree() OVERRIDE {
+ blink::WebGraphicsContext3D* context3d =
+ child_output_surface_->context_provider()->Context3d();
+
+ scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
+
+ scoped_ptr<TestRenderPass> pass_for_quad = TestRenderPass::Create();
+ pass_for_quad->SetNew(
+ // AppendOneOfEveryQuadType() makes a RenderPass quad with this id.
+ RenderPass::Id(2, 1),
+ gfx::Rect(0, 0, 10, 10),
+ gfx::Rect(0, 0, 10, 10),
+ gfx::Transform());
+
+ scoped_ptr<TestRenderPass> pass = TestRenderPass::Create();
+ pass->SetNew(RenderPass::Id(1, 1),
+ gfx::Rect(0, 0, 10, 10),
+ gfx::Rect(0, 0, 10, 10),
+ gfx::Transform());
+ pass->AppendOneOfEveryQuadType(child_resource_provider_.get(),
+ RenderPass::Id(2, 1));
+
+ frame_data->render_pass_list.push_back(pass_for_quad.PassAs<RenderPass>());
+ frame_data->render_pass_list.push_back(pass.PassAs<RenderPass>());
+
+ delegated_resource_collection_ = new DelegatedFrameResourceCollection;
+ delegated_frame_provider_ = new DelegatedFrameProvider(
+ delegated_resource_collection_.get(), frame_data.Pass());
+
+ ResourceProvider::ResourceId resource =
+ child_resource_provider_->CreateResource(
+ gfx::Size(4, 4),
+ GL_CLAMP_TO_EDGE,
+ ResourceProvider::TextureUsageAny,
+ RGBA_8888);
+ ResourceProvider::ScopedWriteLockGL lock(child_resource_provider_.get(),
+ resource);
+
+ gpu::Mailbox mailbox;
+ context3d->genMailboxCHROMIUM(mailbox.name);
+ unsigned sync_point = context3d->insertSyncPoint();
- scoped_refptr<ContentLayer> mask_ = ContentLayer::Create(&client_);
- mask_->SetBounds(gfx::Size(10, 10));
- mask_->SetAnchorPoint(gfx::PointF());
+ scoped_refptr<Layer> root = Layer::Create();
+ root->SetBounds(gfx::Size(10, 10));
+ root->SetAnchorPoint(gfx::PointF());
+ root->SetIsDrawable(true);
- scoped_refptr<ContentLayer> content_with_mask_ =
+ scoped_refptr<FakeDelegatedRendererLayer> delegated =
+ FakeDelegatedRendererLayer::Create(delegated_frame_provider_.get());
+ delegated->SetBounds(gfx::Size(10, 10));
+ delegated->SetAnchorPoint(gfx::PointF());
+ delegated->SetIsDrawable(true);
+ root->AddChild(delegated);
+
+ scoped_refptr<ContentLayer> content = ContentLayer::Create(&client_);
+ content->SetBounds(gfx::Size(10, 10));
+ content->SetAnchorPoint(gfx::PointF());
+ content->SetIsDrawable(true);
+ root->AddChild(content);
+
+ scoped_refptr<TextureLayer> texture = TextureLayer::CreateForMailbox(NULL);
+ texture->SetBounds(gfx::Size(10, 10));
+ texture->SetAnchorPoint(gfx::PointF());
+ texture->SetIsDrawable(true);
+ texture->SetTextureMailbox(
+ TextureMailbox(mailbox, sync_point),
+ SingleReleaseCallback::Create(base::Bind(
+ &LayerTreeHostContextTestDontUseLostResources::
+ EmptyReleaseCallback)));
+ root->AddChild(texture);
+
+ scoped_refptr<ContentLayer> mask = ContentLayer::Create(&client_);
+ mask->SetBounds(gfx::Size(10, 10));
+ mask->SetAnchorPoint(gfx::PointF());
+
+ scoped_refptr<ContentLayer> content_with_mask =
ContentLayer::Create(&client_);
- content_with_mask_->SetBounds(gfx::Size(10, 10));
- content_with_mask_->SetAnchorPoint(gfx::PointF());
- content_with_mask_->SetIsDrawable(true);
- content_with_mask_->SetMaskLayer(mask_.get());
- root_->AddChild(content_with_mask_);
-
- scoped_refptr<VideoLayer> video_color_ = VideoLayer::Create(
- &color_frame_provider_);
- video_color_->SetBounds(gfx::Size(10, 10));
- video_color_->SetAnchorPoint(gfx::PointF());
- video_color_->SetIsDrawable(true);
- root_->AddChild(video_color_);
-
- scoped_refptr<VideoLayer> video_hw_ = VideoLayer::Create(
- &hw_frame_provider_);
- video_hw_->SetBounds(gfx::Size(10, 10));
- video_hw_->SetAnchorPoint(gfx::PointF());
- video_hw_->SetIsDrawable(true);
- root_->AddChild(video_hw_);
-
- scoped_refptr<VideoLayer> video_scaled_hw_ = VideoLayer::Create(
- &scaled_hw_frame_provider_);
- video_scaled_hw_->SetBounds(gfx::Size(10, 10));
- video_scaled_hw_->SetAnchorPoint(gfx::PointF());
- video_scaled_hw_->SetIsDrawable(true);
- root_->AddChild(video_scaled_hw_);
+ content_with_mask->SetBounds(gfx::Size(10, 10));
+ content_with_mask->SetAnchorPoint(gfx::PointF());
+ content_with_mask->SetIsDrawable(true);
+ content_with_mask->SetMaskLayer(mask.get());
+ root->AddChild(content_with_mask);
+
+ scoped_refptr<VideoLayer> video_color =
+ VideoLayer::Create(&color_frame_provider_);
+ video_color->SetBounds(gfx::Size(10, 10));
+ video_color->SetAnchorPoint(gfx::PointF());
+ video_color->SetIsDrawable(true);
+ root->AddChild(video_color);
+
+ scoped_refptr<VideoLayer> video_hw =
+ VideoLayer::Create(&hw_frame_provider_);
+ video_hw->SetBounds(gfx::Size(10, 10));
+ video_hw->SetAnchorPoint(gfx::PointF());
+ video_hw->SetIsDrawable(true);
+ root->AddChild(video_hw);
+
+ scoped_refptr<VideoLayer> video_scaled_hw =
+ VideoLayer::Create(&scaled_hw_frame_provider_);
+ video_scaled_hw->SetBounds(gfx::Size(10, 10));
+ video_scaled_hw->SetAnchorPoint(gfx::PointF());
+ video_scaled_hw->SetIsDrawable(true);
+ root->AddChild(video_scaled_hw);
+
+ color_video_frame_ = VideoFrame::CreateColorFrame(
+ gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
+ hw_video_frame_ = VideoFrame::WrapNativeTexture(
+ make_scoped_ptr(new VideoFrame::MailboxHolder(
+ mailbox,
+ sync_point,
+ VideoFrame::MailboxHolder::TextureNoLongerNeededCallback())),
+ GL_TEXTURE_2D,
+ gfx::Size(4, 4),
+ gfx::Rect(0, 0, 4, 4),
+ gfx::Size(4, 4),
+ base::TimeDelta(),
+ VideoFrame::ReadPixelsCB(),
+ base::Closure());
+ scaled_hw_video_frame_ = VideoFrame::WrapNativeTexture(
+ make_scoped_ptr(new VideoFrame::MailboxHolder(
+ mailbox,
+ sync_point,
+ VideoFrame::MailboxHolder::TextureNoLongerNeededCallback())),
+ GL_TEXTURE_2D,
+ gfx::Size(4, 4),
+ gfx::Rect(0, 0, 3, 2),
+ gfx::Size(4, 4),
+ base::TimeDelta(),
+ VideoFrame::ReadPixelsCB(),
+ base::Closure());
+
+ color_frame_provider_.set_frame(color_video_frame_);
+ hw_frame_provider_.set_frame(hw_video_frame_);
+ scaled_hw_frame_provider_.set_frame(scaled_hw_video_frame_);
if (!delegating_renderer()) {
// TODO(danakj): IOSurface layer can not be transported. crbug.com/239335
- scoped_refptr<IOSurfaceLayer> io_surface_ = IOSurfaceLayer::Create();
- io_surface_->SetBounds(gfx::Size(10, 10));
- io_surface_->SetAnchorPoint(gfx::PointF());
- io_surface_->SetIsDrawable(true);
- io_surface_->SetIOSurfaceProperties(1, gfx::Size(10, 10));
- root_->AddChild(io_surface_);
+ scoped_refptr<IOSurfaceLayer> io_surface = IOSurfaceLayer::Create();
+ io_surface->SetBounds(gfx::Size(10, 10));
+ io_surface->SetAnchorPoint(gfx::PointF());
+ io_surface->SetIsDrawable(true);
+ io_surface->SetIOSurfaceProperties(1, gfx::Size(10, 10));
+ root->AddChild(io_surface);
}
// Enable the hud.
@@ -1199,109 +993,23 @@ class LayerTreeHostContextTestDontUseLostResources
debug_state.show_property_changed_rects = true;
layer_tree_host()->SetDebugState(debug_state);
- scoped_refptr<PaintedScrollbarLayer> scrollbar_ =
+ scoped_refptr<PaintedScrollbarLayer> scrollbar =
PaintedScrollbarLayer::Create(
- scoped_ptr<Scrollbar>(new FakeScrollbar).Pass(), content_->id());
- scrollbar_->SetBounds(gfx::Size(10, 10));
- scrollbar_->SetAnchorPoint(gfx::PointF());
- scrollbar_->SetIsDrawable(true);
- root_->AddChild(scrollbar_);
+ scoped_ptr<Scrollbar>(new FakeScrollbar).Pass(), content->id());
+ scrollbar->SetBounds(gfx::Size(10, 10));
+ scrollbar->SetAnchorPoint(gfx::PointF());
+ scrollbar->SetIsDrawable(true);
+ root->AddChild(scrollbar);
- layer_tree_host()->SetRootLayer(root_);
+ layer_tree_host()->SetRootLayer(root);
LayerTreeHostContextTest::SetupTree();
}
- virtual void BeginTest() OVERRIDE {
- context_should_support_io_surface_ = true;
- PostSetNeedsCommitToMainThread();
- }
+ virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
LayerTreeHostContextTest::CommitCompleteOnThread(host_impl);
- ResourceProvider* resource_provider = host_impl->resource_provider();
- ContextProvider* context_provider =
- host_impl->output_surface()->context_provider();
-
- DCHECK(context_provider);
-
- if (host_impl->active_tree()->source_frame_number() == 0) {
- // Set up impl resources on the first commit.
-
- scoped_ptr<TestRenderPass> pass_for_quad = TestRenderPass::Create();
- pass_for_quad->SetNew(
- // AppendOneOfEveryQuadType() makes a RenderPass quad with this id.
- RenderPass::Id(1, 1),
- gfx::Rect(0, 0, 10, 10),
- gfx::Rect(0, 0, 10, 10),
- gfx::Transform());
-
- scoped_ptr<TestRenderPass> pass = TestRenderPass::Create();
- pass->SetNew(
- RenderPass::Id(2, 1),
- gfx::Rect(0, 0, 10, 10),
- gfx::Rect(0, 0, 10, 10),
- gfx::Transform());
- pass->AppendOneOfEveryQuadType(resource_provider, RenderPass::Id(2, 1));
-
- ScopedPtrVector<RenderPass> pass_list;
- pass_list.push_back(pass_for_quad.PassAs<RenderPass>());
- pass_list.push_back(pass.PassAs<RenderPass>());
-
- // First child is the delegated layer.
- FakeDelegatedRendererLayerImpl* delegated_impl =
- static_cast<FakeDelegatedRendererLayerImpl*>(
- host_impl->active_tree()->root_layer()->children()[0]);
- delegated_impl->SetFrameDataForRenderPasses(&pass_list);
- EXPECT_TRUE(pass_list.empty());
-
- // Third child is the texture layer.
- TextureLayerImpl* texture_impl =
- static_cast<TextureLayerImpl*>(
- host_impl->active_tree()->root_layer()->children()[2]);
- texture_impl->set_texture_id(
- context_provider->Context3d()->createTexture());
-
- ResourceProvider::ResourceId texture = resource_provider->CreateResource(
- gfx::Size(4, 4),
- GL_CLAMP_TO_EDGE,
- ResourceProvider::TextureUsageAny,
- RGBA_8888);
- ResourceProvider::ScopedWriteLockGL lock(resource_provider, texture);
-
- gpu::Mailbox mailbox;
- context_provider->Context3d()->genMailboxCHROMIUM(mailbox.name);
- unsigned sync_point = context_provider->Context3d()->insertSyncPoint();
-
- color_video_frame_ = VideoFrame::CreateColorFrame(
- gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
- hw_video_frame_ = VideoFrame::WrapNativeTexture(
- new VideoFrame::MailboxHolder(
- mailbox,
- sync_point,
- VideoFrame::MailboxHolder::TextureNoLongerNeededCallback()),
- GL_TEXTURE_2D,
- gfx::Size(4, 4), gfx::Rect(0, 0, 4, 4), gfx::Size(4, 4),
- base::TimeDelta(),
- VideoFrame::ReadPixelsCB(),
- base::Closure());
- scaled_hw_video_frame_ = VideoFrame::WrapNativeTexture(
- new VideoFrame::MailboxHolder(
- mailbox,
- sync_point,
- VideoFrame::MailboxHolder::TextureNoLongerNeededCallback()),
- GL_TEXTURE_2D,
- gfx::Size(4, 4), gfx::Rect(0, 0, 3, 2), gfx::Size(4, 4),
- base::TimeDelta(),
- VideoFrame::ReadPixelsCB(),
- base::Closure());
-
- color_frame_provider_.set_frame(color_video_frame_);
- hw_frame_provider_.set_frame(hw_video_frame_);
- scaled_hw_frame_provider_.set_frame(scaled_hw_video_frame_);
- return;
- }
-
if (host_impl->active_tree()->source_frame_number() == 3) {
// On the third commit we're recovering from context loss. Hardware
// video frames should not be reused by the VideoFrameProvider, but
@@ -1317,37 +1025,46 @@ class LayerTreeHostContextTestDontUseLostResources
if (host_impl->active_tree()->source_frame_number() == 2) {
// Lose the context during draw on the second commit. This will cause
// a third commit to recover.
- if (context3d_)
- context3d_->set_times_bind_texture_succeeds(4);
+ context3d_->set_times_bind_texture_succeeds(0);
}
return true;
}
+ virtual scoped_ptr<OutputSurface> CreateOutputSurface(
+ bool fallback) OVERRIDE {
+ if (layer_tree_host()) {
+ lost_context_ = true;
+ EXPECT_EQ(layer_tree_host()->source_frame_number(), 3);
+ }
+ return LayerTreeHostContextTest::CreateOutputSurface(fallback);
+ }
+
virtual void DidCommitAndDrawFrame() OVERRIDE {
ASSERT_TRUE(layer_tree_host()->hud_layer());
// End the test once we know the 3nd frame drew.
- if (layer_tree_host()->source_frame_number() == 4)
- EndTest();
- else
+ if (layer_tree_host()->source_frame_number() < 4) {
+ layer_tree_host()->root_layer()->SetNeedsDisplay();
layer_tree_host()->SetNeedsCommit();
+ } else {
+ EndTest();
+ }
}
- virtual void AfterTest() OVERRIDE {}
+ virtual void AfterTest() OVERRIDE {
+ EXPECT_TRUE(lost_context_);
+ }
private:
FakeContentLayerClient client_;
+ bool lost_context_;
- scoped_refptr<Layer> root_;
- scoped_refptr<DelegatedRendererLayer> delegated_;
- scoped_refptr<ContentLayer> content_;
- scoped_refptr<TextureLayer> texture_;
- scoped_refptr<ContentLayer> mask_;
- scoped_refptr<ContentLayer> content_with_mask_;
- scoped_refptr<VideoLayer> video_color_;
- scoped_refptr<VideoLayer> video_hw_;
- scoped_refptr<VideoLayer> video_scaled_hw_;
- scoped_refptr<IOSurfaceLayer> io_surface_;
- scoped_refptr<PaintedScrollbarLayer> scrollbar_;
+ FakeOutputSurfaceClient output_surface_client_;
+ scoped_ptr<FakeOutputSurface> child_output_surface_;
+ scoped_ptr<ResourceProvider> child_resource_provider_;
+
+ scoped_refptr<DelegatedFrameResourceCollection>
+ delegated_resource_collection_;
+ scoped_refptr<DelegatedFrameProvider> delegated_frame_provider_;
scoped_refptr<VideoFrame> color_video_frame_;
scoped_refptr<VideoFrame> hw_video_frame_;
@@ -1360,73 +1077,6 @@ class LayerTreeHostContextTestDontUseLostResources
SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestDontUseLostResources);
-class LayerTreeHostContextTestLosesFirstOutputSurface
- : public LayerTreeHostContextTest {
- public:
- LayerTreeHostContextTestLosesFirstOutputSurface() {
- // Always fail. This needs to be set before LayerTreeHost is created.
- times_to_lose_on_create_ = 1000;
- }
-
- virtual void BeginTest() OVERRIDE {
- PostSetNeedsCommitToMainThread();
- }
-
- virtual void AfterTest() OVERRIDE {}
-
- virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE {
- EXPECT_FALSE(succeeded);
-
- // If we make it this far without crashing, we pass!
- EndTest();
- }
-
- virtual void DidCommitAndDrawFrame() OVERRIDE {
- EXPECT_TRUE(false);
- }
-};
-
-SINGLE_AND_MULTI_THREAD_TEST_F(
- LayerTreeHostContextTestLosesFirstOutputSurface);
-
-class LayerTreeHostContextTestRetriesFirstInitializationAndSucceeds
- : public LayerTreeHostContextTest {
- public:
- virtual void AfterTest() OVERRIDE {}
-
- virtual void BeginTest() OVERRIDE {
- times_to_fail_initialize_ = 2;
- PostSetNeedsCommitToMainThread();
- }
-
- virtual void DidCommitAndDrawFrame() OVERRIDE {
- EndTest();
- }
-};
-
-SINGLE_AND_MULTI_THREAD_TEST_F(
- LayerTreeHostContextTestRetriesFirstInitializationAndSucceeds);
-
-class LayerTreeHostContextTestRetryWorksWithForcedInit
- : public LayerTreeHostContextTestRetriesFirstInitializationAndSucceeds {
- public:
- virtual void DidFailToInitializeOutputSurface() OVERRIDE {
- LayerTreeHostContextTestRetriesFirstInitializationAndSucceeds
- ::DidFailToInitializeOutputSurface();
-
- if (times_create_failed_ == 1) {
- // CompositeAndReadback force recreates the output surface, which should
- // fail.
- char pixels[4];
- EXPECT_FALSE(layer_tree_host()->CompositeAndReadback(
- &pixels, gfx::Rect(1, 1)));
- }
- }
-};
-
-SINGLE_AND_MULTI_THREAD_TEST_F(
- LayerTreeHostContextTestRetryWorksWithForcedInit);
-
class LayerTreeHostContextTestCompositeAndReadbackBeforeOutputSurfaceInit
: public LayerTreeHostContextTest {
public:
@@ -1437,13 +1087,16 @@ class LayerTreeHostContextTestCompositeAndReadbackBeforeOutputSurfaceInit
times_output_surface_created_ = 0;
+ // Post the SetNeedsCommit before the readback to make sure it is run
+ // on the main thread before the readback's replacement commit when
+ // we have a threaded compositor.
+ PostSetNeedsCommitToMainThread();
+
char pixels[4];
bool result = layer_tree_host()->CompositeAndReadback(
&pixels, gfx::Rect(1, 1));
EXPECT_EQ(!delegating_renderer(), result);
EXPECT_EQ(1, times_output_surface_created_);
-
- PostSetNeedsCommitToMainThread();
}
virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE {
@@ -1576,7 +1229,6 @@ class LayerTreeHostContextTestReadbackWithForcedDrawAndOutputSurfaceInit
protected:
static const int kFirstOutputSurfaceInitSourceFrameNumber = 0;
static const int kReadbackSourceFrameNumber = 1;
- static const int kReadbackReplacementSourceFrameNumber = 2;
static const int kForcedDrawCommitSourceFrameNumber = 2;
static const int kSecondOutputSurfaceInitSourceFrameNumber = 2;
@@ -1753,42 +1405,6 @@ class ScrollbarLayerLostContext : public LayerTreeHostContextTest {
SINGLE_AND_MULTI_THREAD_TEST_F(ScrollbarLayerLostContext);
-class LayerTreeHostContextTestFailsToCreateSurface
- : public LayerTreeHostContextTest {
- public:
- LayerTreeHostContextTestFailsToCreateSurface()
- : LayerTreeHostContextTest(),
- failure_count_(0) {
- times_to_lose_on_create_ = 10;
- }
-
- virtual void BeginTest() OVERRIDE {
- PostSetNeedsCommitToMainThread();
- }
-
- virtual void AfterTest() OVERRIDE {}
-
- virtual void DidInitializeOutputSurface(bool success) OVERRIDE {
- EXPECT_FALSE(success);
- EXPECT_EQ(0, failure_count_);
- times_to_lose_on_create_ = 0;
- failure_count_++;
- // Normally, the embedder should stop trying to use the compositor at
- // this point, but let's force it back into action when we shouldn't.
- char pixels[4];
- EXPECT_FALSE(
- layer_tree_host()->CompositeAndReadback(pixels, gfx::Rect(1, 1)));
- // If we've made it this far without crashing, we've succeeded.
- EndTest();
- }
-
- private:
- int failure_count_;
-};
-
-SINGLE_AND_MULTI_THREAD_TEST_F(
- LayerTreeHostContextTestFailsToCreateSurface);
-
// Not reusing LayerTreeTest because it expects creating LTH to always succeed.
class LayerTreeHostTestCannotCreateIfCannotCreateOutputSurface
: public testing::Test,
@@ -1806,20 +1422,20 @@ class LayerTreeHostTestCannotCreateIfCannotCreateOutputSurface
void RunTest(bool threaded,
bool delegating_renderer,
bool impl_side_painting) {
- scoped_ptr<base::Thread> impl_thread;
+ LayerTreeSettings settings;
+ settings.impl_side_painting = impl_side_painting;
if (threaded) {
- impl_thread.reset(new base::Thread("LayerTreeTest"));
+ scoped_ptr<base::Thread> impl_thread(new base::Thread("LayerTreeTest"));
ASSERT_TRUE(impl_thread->Start());
ASSERT_TRUE(impl_thread->message_loop_proxy().get());
+ scoped_ptr<LayerTreeHost> layer_tree_host = LayerTreeHost::CreateThreaded(
+ this, NULL, settings, impl_thread->message_loop_proxy());
+ EXPECT_FALSE(layer_tree_host);
+ } else {
+ scoped_ptr<LayerTreeHost> layer_tree_host =
+ LayerTreeHost::CreateSingleThreaded(this, this, NULL, settings);
+ EXPECT_FALSE(layer_tree_host);
}
-
- LayerTreeSettings settings;
- settings.impl_side_painting = impl_side_painting;
- scoped_ptr<LayerTreeHost> layer_tree_host = LayerTreeHost::Create(
- this,
- settings,
- impl_thread ? impl_thread->message_loop_proxy() : NULL);
- EXPECT_FALSE(layer_tree_host);
}
};
@@ -1829,6 +1445,9 @@ SINGLE_AND_MULTI_THREAD_TEST_F(
class UIResourceLostTest : public LayerTreeHostContextTest {
public:
UIResourceLostTest() : time_step_(0) {}
+ virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
+ settings->texture_id_allocation_chunk_size = 1;
+ }
virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
virtual void AfterTest() OVERRIDE {}
@@ -2250,5 +1869,74 @@ class UIResourceLostEviction : public UIResourceLostTestSimple {
SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostEviction);
+class LayerTreeHostContextTestSurfaceCreateCallback
+ : public LayerTreeHostContextTest {
+ public:
+ LayerTreeHostContextTestSurfaceCreateCallback()
+ : LayerTreeHostContextTest(),
+ layer_(FakeContentLayer::Create(&client_)),
+ num_commits_(0) {}
+
+ virtual void SetupTree() OVERRIDE {
+ layer_->SetBounds(gfx::Size(10, 20));
+ layer_tree_host()->SetRootLayer(layer_);
+ LayerTreeHostContextTest::SetupTree();
+ }
+
+ virtual void BeginTest() OVERRIDE {
+ PostSetNeedsCommitToMainThread();
+ }
+
+ virtual void DidCommit() OVERRIDE {
+ switch (num_commits_) {
+ case 0:
+ EXPECT_EQ(1u, layer_->output_surface_created_count());
+ layer_tree_host()->SetNeedsCommit();
+ break;
+ case 1:
+ EXPECT_EQ(1u, layer_->output_surface_created_count());
+ layer_tree_host()->SetNeedsCommit();
+ break;
+ case 2:
+ EXPECT_EQ(1u, layer_->output_surface_created_count());
+ break;
+ case 3:
+ EXPECT_EQ(2u, layer_->output_surface_created_count());
+ layer_tree_host()->SetNeedsCommit();
+ break;
+ }
+ ++num_commits_;
+ }
+
+ virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
+ LayerTreeHostContextTest::CommitCompleteOnThread(impl);
+ switch (num_commits_) {
+ case 0:
+ break;
+ case 1:
+ break;
+ case 2:
+ LoseContext();
+ break;
+ case 3:
+ EndTest();
+ break;
+ }
+ }
+
+ virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE {
+ EXPECT_TRUE(succeeded);
+ }
+
+ virtual void AfterTest() OVERRIDE {}
+
+ protected:
+ FakeContentLayerClient client_;
+ scoped_refptr<FakeContentLayer> layer_;
+ int num_commits_;
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestSurfaceCreateCallback);
+
} // namespace
} // namespace cc
diff --git a/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc b/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc
new file mode 100644
index 00000000000..c06f345ef17
--- /dev/null
+++ b/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc
@@ -0,0 +1,908 @@
+// 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/copy_output_request.h"
+#include "cc/output/copy_output_result.h"
+#include "cc/test/fake_content_layer.h"
+#include "cc/test/fake_content_layer_client.h"
+#include "cc/test/fake_output_surface.h"
+#include "cc/test/layer_tree_test.h"
+#include "cc/trees/layer_tree_impl.h"
+#include "gpu/GLES2/gl2extchromium.h"
+
+namespace cc {
+namespace {
+
+// These tests only use direct rendering, as there is no output to copy for
+// delegated renderers.
+class LayerTreeHostCopyRequestTest : public LayerTreeTest {};
+
+class LayerTreeHostCopyRequestTestMultipleRequests
+ : public LayerTreeHostCopyRequestTest {
+ protected:
+ virtual void SetupTree() OVERRIDE {
+ root = FakeContentLayer::Create(&client_);
+ root->SetBounds(gfx::Size(20, 20));
+
+ child = FakeContentLayer::Create(&client_);
+ child->SetBounds(gfx::Size(10, 10));
+ root->AddChild(child);
+
+ layer_tree_host()->SetRootLayer(root);
+ LayerTreeHostCopyRequestTest::SetupTree();
+ }
+
+ virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
+
+ virtual void DidCommitAndDrawFrame() OVERRIDE { WaitForCallback(); }
+
+ void WaitForCallback() {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&LayerTreeHostCopyRequestTestMultipleRequests::NextStep,
+ base::Unretained(this)));
+ }
+
+ void NextStep() {
+ int frame = layer_tree_host()->source_frame_number();
+ switch (frame) {
+ case 1:
+ child->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
+ base::Bind(&LayerTreeHostCopyRequestTestMultipleRequests::
+ CopyOutputCallback,
+ base::Unretained(this))));
+ EXPECT_EQ(0u, callbacks_.size());
+ break;
+ case 2:
+ if (callbacks_.size() < 1u) {
+ WaitForCallback();
+ return;
+ }
+ EXPECT_EQ(1u, callbacks_.size());
+ EXPECT_EQ(gfx::Size(10, 10).ToString(), callbacks_[0].ToString());
+
+ child->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
+ base::Bind(&LayerTreeHostCopyRequestTestMultipleRequests::
+ CopyOutputCallback,
+ base::Unretained(this))));
+ root->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
+ base::Bind(&LayerTreeHostCopyRequestTestMultipleRequests::
+ CopyOutputCallback,
+ base::Unretained(this))));
+ child->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
+ base::Bind(&LayerTreeHostCopyRequestTestMultipleRequests::
+ CopyOutputCallback,
+ base::Unretained(this))));
+ EXPECT_EQ(1u, callbacks_.size());
+ break;
+ case 3:
+ if (callbacks_.size() < 4u) {
+ WaitForCallback();
+ return;
+ }
+ EXPECT_EQ(4u, callbacks_.size());
+ // The child was copied to a bitmap and passed back twice.
+ EXPECT_EQ(gfx::Size(10, 10).ToString(), callbacks_[1].ToString());
+ EXPECT_EQ(gfx::Size(10, 10).ToString(), callbacks_[2].ToString());
+ // The root was copied to a bitmap and passed back also.
+ EXPECT_EQ(gfx::Size(20, 20).ToString(), callbacks_[3].ToString());
+ EndTest();
+ break;
+ }
+ }
+
+ void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
+ EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
+ EXPECT_TRUE(result->HasBitmap());
+ scoped_ptr<SkBitmap> bitmap = result->TakeBitmap().Pass();
+ EXPECT_EQ(result->size().ToString(),
+ gfx::Size(bitmap->width(), bitmap->height()).ToString());
+ callbacks_.push_back(result->size());
+ }
+
+ virtual void AfterTest() OVERRIDE { EXPECT_EQ(4u, callbacks_.size()); }
+
+ virtual scoped_ptr<OutputSurface> CreateOutputSurface(bool fallback)
+ OVERRIDE {
+ scoped_ptr<FakeOutputSurface> output_surface;
+ if (use_gl_renderer_) {
+ output_surface = FakeOutputSurface::Create3d().Pass();
+ } else {
+ output_surface = FakeOutputSurface::CreateSoftware(
+ make_scoped_ptr(new SoftwareOutputDevice)).Pass();
+ }
+ return output_surface.PassAs<OutputSurface>();
+ }
+
+ bool use_gl_renderer_;
+ std::vector<gfx::Size> callbacks_;
+ FakeContentLayerClient client_;
+ scoped_refptr<FakeContentLayer> root;
+ scoped_refptr<FakeContentLayer> child;
+};
+
+// Readback can't be done with a delegating renderer.
+TEST_F(LayerTreeHostCopyRequestTestMultipleRequests,
+ GLRenderer_RunSingleThread) {
+ use_gl_renderer_ = true;
+ RunTest(false, false, false);
+}
+
+TEST_F(LayerTreeHostCopyRequestTestMultipleRequests,
+ GLRenderer_RunMultiThread_MainThreadPainting) {
+ use_gl_renderer_ = true;
+ RunTest(true, false, false);
+}
+
+TEST_F(LayerTreeHostCopyRequestTestMultipleRequests,
+ SoftwareRenderer_RunSingleThread) {
+ use_gl_renderer_ = false;
+ RunTest(false, false, false);
+}
+
+TEST_F(LayerTreeHostCopyRequestTestMultipleRequests,
+ SoftwareRenderer_RunMultiThread_MainThreadPainting) {
+ use_gl_renderer_ = false;
+ RunTest(true, false, false);
+}
+
+class LayerTreeHostCopyRequestTestLayerDestroyed
+ : public LayerTreeHostCopyRequestTest {
+ protected:
+ virtual void SetupTree() OVERRIDE {
+ root_ = FakeContentLayer::Create(&client_);
+ root_->SetBounds(gfx::Size(20, 20));
+
+ main_destroyed_ = FakeContentLayer::Create(&client_);
+ main_destroyed_->SetBounds(gfx::Size(15, 15));
+ root_->AddChild(main_destroyed_);
+
+ impl_destroyed_ = FakeContentLayer::Create(&client_);
+ impl_destroyed_->SetBounds(gfx::Size(10, 10));
+ root_->AddChild(impl_destroyed_);
+
+ layer_tree_host()->SetRootLayer(root_);
+ LayerTreeHostCopyRequestTest::SetupTree();
+ }
+
+ virtual void BeginTest() OVERRIDE {
+ callback_count_ = 0;
+ PostSetNeedsCommitToMainThread();
+ }
+
+ virtual void DidCommit() OVERRIDE {
+ int frame = layer_tree_host()->source_frame_number();
+ switch (frame) {
+ case 1:
+ main_destroyed_->RequestCopyOfOutput(
+ CopyOutputRequest::CreateBitmapRequest(base::Bind(
+ &LayerTreeHostCopyRequestTestLayerDestroyed::CopyOutputCallback,
+ base::Unretained(this))));
+ impl_destroyed_->RequestCopyOfOutput(
+ CopyOutputRequest::CreateBitmapRequest(base::Bind(
+ &LayerTreeHostCopyRequestTestLayerDestroyed::CopyOutputCallback,
+ base::Unretained(this))));
+ EXPECT_EQ(0, callback_count_);
+
+ // Destroy the main thread layer right away.
+ main_destroyed_->RemoveFromParent();
+ main_destroyed_ = NULL;
+
+ // Should callback with a NULL bitmap.
+ EXPECT_EQ(1, callback_count_);
+
+ // Prevent drawing so we can't make a copy of the impl_destroyed layer.
+ layer_tree_host()->SetViewportSize(gfx::Size());
+ break;
+ case 2:
+ // Flush the message loops and make sure the callbacks run.
+ layer_tree_host()->SetNeedsCommit();
+ break;
+ case 3:
+ // No drawing means no readback yet.
+ EXPECT_EQ(1, callback_count_);
+
+ // Destroy the impl thread layer.
+ impl_destroyed_->RemoveFromParent();
+ impl_destroyed_ = NULL;
+
+ // No callback yet because it's on the impl side.
+ EXPECT_EQ(1, callback_count_);
+ break;
+ case 4:
+ // Flush the message loops and make sure the callbacks run.
+ layer_tree_host()->SetNeedsCommit();
+ break;
+ case 5:
+ // We should get another callback with a NULL bitmap.
+ EXPECT_EQ(2, callback_count_);
+ EndTest();
+ break;
+ }
+ }
+
+ void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
+ EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
+ EXPECT_TRUE(result->IsEmpty());
+ ++callback_count_;
+ }
+
+ virtual void AfterTest() OVERRIDE {}
+
+ int callback_count_;
+ FakeContentLayerClient client_;
+ scoped_refptr<FakeContentLayer> root_;
+ scoped_refptr<FakeContentLayer> main_destroyed_;
+ scoped_refptr<FakeContentLayer> impl_destroyed_;
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostCopyRequestTestLayerDestroyed);
+
+class LayerTreeHostCopyRequestTestInHiddenSubtree
+ : public LayerTreeHostCopyRequestTest {
+ protected:
+ virtual void SetupTree() OVERRIDE {
+ root_ = FakeContentLayer::Create(&client_);
+ root_->SetBounds(gfx::Size(20, 20));
+
+ grand_parent_layer_ = FakeContentLayer::Create(&client_);
+ grand_parent_layer_->SetBounds(gfx::Size(15, 15));
+ root_->AddChild(grand_parent_layer_);
+
+ // parent_layer_ owns a render surface.
+ parent_layer_ = FakeContentLayer::Create(&client_);
+ parent_layer_->SetBounds(gfx::Size(15, 15));
+ parent_layer_->SetForceRenderSurface(true);
+ grand_parent_layer_->AddChild(parent_layer_);
+
+ copy_layer_ = FakeContentLayer::Create(&client_);
+ copy_layer_->SetBounds(gfx::Size(10, 10));
+ parent_layer_->AddChild(copy_layer_);
+
+ layer_tree_host()->SetRootLayer(root_);
+ LayerTreeHostCopyRequestTest::SetupTree();
+ }
+
+ void AddCopyRequest(Layer* layer) {
+ layer->RequestCopyOfOutput(
+ CopyOutputRequest::CreateBitmapRequest(base::Bind(
+ &LayerTreeHostCopyRequestTestInHiddenSubtree::CopyOutputCallback,
+ base::Unretained(this))));
+ }
+
+ virtual void BeginTest() OVERRIDE {
+ callback_count_ = 0;
+ PostSetNeedsCommitToMainThread();
+
+ AddCopyRequest(copy_layer_.get());
+ }
+
+ void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
+ ++callback_count_;
+ EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
+ EXPECT_EQ(copy_layer_->bounds().ToString(), result->size().ToString())
+ << callback_count_;
+ switch (callback_count_) {
+ case 1:
+ // Hide the copy request layer.
+ grand_parent_layer_->SetHideLayerAndSubtree(false);
+ parent_layer_->SetHideLayerAndSubtree(false);
+ copy_layer_->SetHideLayerAndSubtree(true);
+ AddCopyRequest(copy_layer_.get());
+ break;
+ case 2:
+ // Hide the copy request layer's parent only.
+ grand_parent_layer_->SetHideLayerAndSubtree(false);
+ parent_layer_->SetHideLayerAndSubtree(true);
+ copy_layer_->SetHideLayerAndSubtree(false);
+ AddCopyRequest(copy_layer_.get());
+ break;
+ case 3:
+ // Hide the copy request layer's grand parent only.
+ grand_parent_layer_->SetHideLayerAndSubtree(true);
+ parent_layer_->SetHideLayerAndSubtree(false);
+ copy_layer_->SetHideLayerAndSubtree(false);
+ AddCopyRequest(copy_layer_.get());
+ break;
+ case 4:
+ // Hide the copy request layer's parent and grandparent.
+ grand_parent_layer_->SetHideLayerAndSubtree(true);
+ parent_layer_->SetHideLayerAndSubtree(true);
+ copy_layer_->SetHideLayerAndSubtree(false);
+ AddCopyRequest(copy_layer_.get());
+ break;
+ case 5:
+ // Hide the copy request layer as well as its parent and grandparent.
+ grand_parent_layer_->SetHideLayerAndSubtree(true);
+ parent_layer_->SetHideLayerAndSubtree(true);
+ copy_layer_->SetHideLayerAndSubtree(true);
+ AddCopyRequest(copy_layer_.get());
+ break;
+ case 6:
+ EndTest();
+ break;
+ }
+ }
+
+ virtual void AfterTest() OVERRIDE {}
+
+ int callback_count_;
+ FakeContentLayerClient client_;
+ scoped_refptr<FakeContentLayer> root_;
+ scoped_refptr<FakeContentLayer> grand_parent_layer_;
+ scoped_refptr<FakeContentLayer> parent_layer_;
+ scoped_refptr<FakeContentLayer> copy_layer_;
+};
+
+SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F(
+ LayerTreeHostCopyRequestTestInHiddenSubtree);
+
+class LayerTreeHostTestHiddenSurfaceNotAllocatedForSubtreeCopyRequest
+ : public LayerTreeHostCopyRequestTest {
+ protected:
+ virtual void SetupTree() OVERRIDE {
+ root_ = FakeContentLayer::Create(&client_);
+ root_->SetBounds(gfx::Size(20, 20));
+
+ grand_parent_layer_ = FakeContentLayer::Create(&client_);
+ grand_parent_layer_->SetBounds(gfx::Size(15, 15));
+ grand_parent_layer_->SetHideLayerAndSubtree(true);
+ root_->AddChild(grand_parent_layer_);
+
+ // parent_layer_ owns a render surface.
+ parent_layer_ = FakeContentLayer::Create(&client_);
+ parent_layer_->SetBounds(gfx::Size(15, 15));
+ parent_layer_->SetForceRenderSurface(true);
+ grand_parent_layer_->AddChild(parent_layer_);
+
+ copy_layer_ = FakeContentLayer::Create(&client_);
+ copy_layer_->SetBounds(gfx::Size(10, 10));
+ parent_layer_->AddChild(copy_layer_);
+
+ layer_tree_host()->SetRootLayer(root_);
+ LayerTreeHostCopyRequestTest::SetupTree();
+ }
+
+ virtual void BeginTest() OVERRIDE {
+ did_draw_ = false;
+ PostSetNeedsCommitToMainThread();
+
+ copy_layer_->RequestCopyOfOutput(
+ CopyOutputRequest::CreateBitmapRequest(base::Bind(
+ &LayerTreeHostTestHiddenSurfaceNotAllocatedForSubtreeCopyRequest::
+ CopyOutputCallback,
+ base::Unretained(this))));
+ }
+
+ void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
+ EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
+ EXPECT_EQ(copy_layer_->bounds().ToString(), result->size().ToString());
+ EndTest();
+ }
+
+ virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
+ Renderer* renderer = host_impl->renderer();
+
+ LayerImpl* root = host_impl->active_tree()->root_layer();
+ LayerImpl* grand_parent = root->children()[0];
+ LayerImpl* parent = grand_parent->children()[0];
+ LayerImpl* copy_layer = parent->children()[0];
+
+ // |parent| owns a surface, but it was hidden and not part of the copy
+ // request so it should not allocate any resource.
+ EXPECT_FALSE(renderer->HasAllocatedResourcesForTesting(
+ parent->render_surface()->RenderPassId()));
+
+ // |copy_layer| should have been rendered to a texture since it was needed
+ // for a copy request.
+ EXPECT_TRUE(renderer->HasAllocatedResourcesForTesting(
+ copy_layer->render_surface()->RenderPassId()));
+
+ did_draw_ = true;
+ }
+
+ virtual void AfterTest() OVERRIDE { EXPECT_TRUE(did_draw_); }
+
+ FakeContentLayerClient client_;
+ bool did_draw_;
+ scoped_refptr<FakeContentLayer> root_;
+ scoped_refptr<FakeContentLayer> grand_parent_layer_;
+ scoped_refptr<FakeContentLayer> parent_layer_;
+ scoped_refptr<FakeContentLayer> copy_layer_;
+};
+
+// No output to copy for delegated renderers.
+SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
+ LayerTreeHostTestHiddenSurfaceNotAllocatedForSubtreeCopyRequest);
+
+class LayerTreeHostCopyRequestTestClippedOut
+ : public LayerTreeHostCopyRequestTest {
+ protected:
+ virtual void SetupTree() OVERRIDE {
+ root_ = FakeContentLayer::Create(&client_);
+ root_->SetBounds(gfx::Size(20, 20));
+
+ parent_layer_ = FakeContentLayer::Create(&client_);
+ parent_layer_->SetBounds(gfx::Size(15, 15));
+ parent_layer_->SetMasksToBounds(true);
+ root_->AddChild(parent_layer_);
+
+ copy_layer_ = FakeContentLayer::Create(&client_);
+ copy_layer_->SetPosition(gfx::Point(15, 15));
+ copy_layer_->SetBounds(gfx::Size(10, 10));
+ parent_layer_->AddChild(copy_layer_);
+
+ layer_tree_host()->SetRootLayer(root_);
+ LayerTreeHostCopyRequestTest::SetupTree();
+ }
+
+ virtual void BeginTest() OVERRIDE {
+ PostSetNeedsCommitToMainThread();
+
+ copy_layer_->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
+ base::Bind(&LayerTreeHostCopyRequestTestClippedOut::CopyOutputCallback,
+ base::Unretained(this))));
+ }
+
+ void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
+ // We should still get a callback with no output if the copy requested layer
+ // was completely clipped away.
+ EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
+ EXPECT_EQ(gfx::Size().ToString(), result->size().ToString());
+ EndTest();
+ }
+
+ virtual void AfterTest() OVERRIDE {}
+
+ FakeContentLayerClient client_;
+ scoped_refptr<FakeContentLayer> root_;
+ scoped_refptr<FakeContentLayer> parent_layer_;
+ scoped_refptr<FakeContentLayer> copy_layer_;
+};
+
+SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
+ LayerTreeHostCopyRequestTestClippedOut);
+
+class LayerTreeHostTestAsyncTwoReadbacksWithoutDraw
+ : public LayerTreeHostCopyRequestTest {
+ protected:
+ virtual void SetupTree() OVERRIDE {
+ root_ = FakeContentLayer::Create(&client_);
+ root_->SetBounds(gfx::Size(20, 20));
+
+ copy_layer_ = FakeContentLayer::Create(&client_);
+ copy_layer_->SetBounds(gfx::Size(10, 10));
+ root_->AddChild(copy_layer_);
+
+ layer_tree_host()->SetRootLayer(root_);
+ LayerTreeHostCopyRequestTest::SetupTree();
+ }
+
+ void AddCopyRequest(Layer* layer) {
+ layer->RequestCopyOfOutput(
+ CopyOutputRequest::CreateBitmapRequest(base::Bind(
+ &LayerTreeHostTestAsyncTwoReadbacksWithoutDraw::CopyOutputCallback,
+ base::Unretained(this))));
+ }
+
+ virtual void BeginTest() OVERRIDE {
+ saw_copy_request_ = false;
+ callback_count_ = 0;
+ PostSetNeedsCommitToMainThread();
+
+ // Prevent drawing.
+ layer_tree_host()->SetViewportSize(gfx::Size(0, 0));
+
+ AddCopyRequest(copy_layer_.get());
+ }
+
+ virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
+ if (impl->active_tree()->source_frame_number() == 0) {
+ LayerImpl* root = impl->active_tree()->root_layer();
+ EXPECT_TRUE(root->children()[0]->HasCopyRequest());
+ saw_copy_request_ = true;
+ }
+ }
+
+ virtual void DidCommit() OVERRIDE {
+ if (layer_tree_host()->source_frame_number() == 1) {
+ // Allow drawing.
+ layer_tree_host()->SetViewportSize(gfx::Size(root_->bounds()));
+
+ AddCopyRequest(copy_layer_.get());
+ }
+ }
+
+ void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
+ EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
+ EXPECT_EQ(copy_layer_->bounds().ToString(), result->size().ToString());
+ ++callback_count_;
+
+ if (callback_count_ == 2)
+ EndTest();
+ }
+
+ virtual void AfterTest() OVERRIDE { EXPECT_TRUE(saw_copy_request_); }
+
+ bool saw_copy_request_;
+ int callback_count_;
+ FakeContentLayerClient client_;
+ scoped_refptr<FakeContentLayer> root_;
+ scoped_refptr<FakeContentLayer> copy_layer_;
+};
+
+SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F(
+ LayerTreeHostTestAsyncTwoReadbacksWithoutDraw);
+
+class LayerTreeHostCopyRequestTestLostOutputSurface
+ : public LayerTreeHostCopyRequestTest {
+ protected:
+ virtual scoped_ptr<OutputSurface> CreateOutputSurface(bool fallback)
+ OVERRIDE {
+ if (!first_context_provider_.get()) {
+ first_context_provider_ = TestContextProvider::Create();
+ return FakeOutputSurface::Create3d(first_context_provider_)
+ .PassAs<OutputSurface>();
+ }
+
+ EXPECT_FALSE(second_context_provider_.get());
+ second_context_provider_ = TestContextProvider::Create();
+ return FakeOutputSurface::Create3d(second_context_provider_)
+ .PassAs<OutputSurface>();
+ }
+
+ virtual void SetupTree() OVERRIDE {
+ root_ = FakeContentLayer::Create(&client_);
+ root_->SetBounds(gfx::Size(20, 20));
+
+ copy_layer_ = FakeContentLayer::Create(&client_);
+ copy_layer_->SetBounds(gfx::Size(10, 10));
+ root_->AddChild(copy_layer_);
+
+ layer_tree_host()->SetRootLayer(root_);
+ LayerTreeHostCopyRequestTest::SetupTree();
+ }
+
+ virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
+
+ void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
+ EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
+ EXPECT_EQ(gfx::Size(10, 10).ToString(), result->size().ToString());
+ EXPECT_TRUE(result->HasTexture());
+
+ // Save the result for later.
+ EXPECT_FALSE(result_);
+ result_ = result.Pass();
+
+ // Post a commit to lose the output surface.
+ layer_tree_host()->SetNeedsCommit();
+ }
+
+ virtual void DidCommitAndDrawFrame() OVERRIDE {
+ switch (layer_tree_host()->source_frame_number()) {
+ case 1:
+ // The layers have been pushed to the impl side. The layer textures have
+ // been allocated.
+
+ // Request a copy of the layer. This will use another texture.
+ copy_layer_->RequestCopyOfOutput(CopyOutputRequest::CreateRequest(
+ base::Bind(&LayerTreeHostCopyRequestTestLostOutputSurface::
+ CopyOutputCallback,
+ base::Unretained(this))));
+ break;
+ case 4:
+ // With SingleThreadProxy it takes two commits to finally swap after a
+ // context loss.
+ case 5:
+ // Now destroy the CopyOutputResult, releasing the texture inside back
+ // to the compositor.
+ EXPECT_TRUE(result_);
+ result_.reset();
+
+ // Check that it is released.
+ ImplThreadTaskRunner()->PostTask(
+ FROM_HERE,
+ base::Bind(&LayerTreeHostCopyRequestTestLostOutputSurface::
+ CheckNumTextures,
+ base::Unretained(this),
+ num_textures_after_loss_ - 1));
+ break;
+ }
+ }
+
+ virtual void SwapBuffersOnThread(LayerTreeHostImpl* impl,
+ bool result) OVERRIDE {
+ switch (impl->active_tree()->source_frame_number()) {
+ case 0:
+ // The layers have been drawn, so their textures have been allocated.
+ EXPECT_FALSE(result_);
+ num_textures_without_readback_ =
+ first_context_provider_->TestContext3d()->NumTextures();
+ break;
+ case 1:
+ // We did a readback, so there will be a readback texture around now.
+ EXPECT_LT(num_textures_without_readback_,
+ first_context_provider_->TestContext3d()->NumTextures());
+ break;
+ case 2:
+ // The readback texture is collected.
+ EXPECT_TRUE(result_);
+
+ // Lose the output surface.
+ first_context_provider_->TestContext3d()->loseContextCHROMIUM(
+ GL_GUILTY_CONTEXT_RESET_ARB, GL_INNOCENT_CONTEXT_RESET_ARB);
+ break;
+ case 3:
+ // With SingleThreadProxy it takes two commits to finally swap after a
+ // context loss.
+ case 4:
+ // The output surface has been recreated.
+ EXPECT_TRUE(second_context_provider_.get());
+
+ num_textures_after_loss_ =
+ first_context_provider_->TestContext3d()->NumTextures();
+ break;
+ }
+ }
+
+ void CheckNumTextures(size_t expected_num_textures) {
+ EXPECT_EQ(expected_num_textures,
+ first_context_provider_->TestContext3d()->NumTextures());
+ EndTest();
+ }
+
+ virtual void AfterTest() OVERRIDE {}
+
+ scoped_refptr<TestContextProvider> first_context_provider_;
+ scoped_refptr<TestContextProvider> second_context_provider_;
+ size_t num_textures_without_readback_;
+ size_t num_textures_after_loss_;
+ FakeContentLayerClient client_;
+ scoped_refptr<FakeContentLayer> root_;
+ scoped_refptr<FakeContentLayer> copy_layer_;
+ scoped_ptr<CopyOutputResult> result_;
+};
+
+SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F(
+ LayerTreeHostCopyRequestTestLostOutputSurface);
+
+class LayerTreeHostCopyRequestTestCountTextures
+ : public LayerTreeHostCopyRequestTest {
+ protected:
+ virtual scoped_ptr<OutputSurface> CreateOutputSurface(bool fallback)
+ OVERRIDE {
+ context_provider_ = TestContextProvider::Create();
+ return FakeOutputSurface::Create3d(context_provider_)
+ .PassAs<OutputSurface>();
+ }
+
+ virtual void SetupTree() OVERRIDE {
+ root_ = FakeContentLayer::Create(&client_);
+ root_->SetBounds(gfx::Size(20, 20));
+
+ copy_layer_ = FakeContentLayer::Create(&client_);
+ copy_layer_->SetBounds(gfx::Size(10, 10));
+ root_->AddChild(copy_layer_);
+
+ layer_tree_host()->SetRootLayer(root_);
+ LayerTreeHostCopyRequestTest::SetupTree();
+ }
+
+ virtual void BeginTest() OVERRIDE {
+ num_textures_without_readback_ = 0;
+ num_textures_with_readback_ = 0;
+ waited_sync_point_after_readback_ = 0;
+ PostSetNeedsCommitToMainThread();
+ }
+
+ virtual void RequestCopy(Layer* layer) = 0;
+
+ virtual void DidCommitAndDrawFrame() OVERRIDE {
+ switch (layer_tree_host()->source_frame_number()) {
+ case 1:
+ // The layers have been pushed to the impl side. The layer textures have
+ // been allocated.
+ RequestCopy(copy_layer_.get());
+ break;
+ }
+ }
+
+ virtual void SwapBuffersOnThread(LayerTreeHostImpl* impl,
+ bool result) OVERRIDE {
+ switch (impl->active_tree()->source_frame_number()) {
+ case 0:
+ // The layers have been drawn, so their textures have been allocated.
+ num_textures_without_readback_ =
+ context_provider_->TestContext3d()->NumTextures();
+ break;
+ case 1:
+ // We did a readback, so there will be a readback texture around now.
+ num_textures_with_readback_ =
+ context_provider_->TestContext3d()->NumTextures();
+ waited_sync_point_after_readback_ =
+ context_provider_->TestContext3d()->last_waited_sync_point();
+
+ MainThreadTaskRunner()->PostTask(
+ FROM_HERE,
+ base::Bind(&LayerTreeHostCopyRequestTestCountTextures::DoEndTest,
+ base::Unretained(this)));
+ break;
+ }
+ }
+
+ virtual void DoEndTest() { EndTest(); }
+
+ scoped_refptr<TestContextProvider> context_provider_;
+ size_t num_textures_without_readback_;
+ size_t num_textures_with_readback_;
+ unsigned waited_sync_point_after_readback_;
+ FakeContentLayerClient client_;
+ scoped_refptr<FakeContentLayer> root_;
+ scoped_refptr<FakeContentLayer> copy_layer_;
+};
+
+class LayerTreeHostCopyRequestTestCreatesTexture
+ : public LayerTreeHostCopyRequestTestCountTextures {
+ protected:
+ virtual void RequestCopy(Layer* layer) OVERRIDE {
+ // Request a normal texture copy. This should create a new texture.
+ copy_layer_->RequestCopyOfOutput(
+ CopyOutputRequest::CreateRequest(base::Bind(
+ &LayerTreeHostCopyRequestTestCreatesTexture::CopyOutputCallback,
+ base::Unretained(this))));
+ }
+
+ void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
+ EXPECT_FALSE(result->IsEmpty());
+ EXPECT_TRUE(result->HasTexture());
+
+ TextureMailbox mailbox;
+ scoped_ptr<SingleReleaseCallback> release;
+ result->TakeTexture(&mailbox, &release);
+ EXPECT_TRUE(release);
+
+ release->Run(0, false);
+ }
+
+ virtual void AfterTest() OVERRIDE {
+ // No sync point was needed.
+ EXPECT_EQ(0u, waited_sync_point_after_readback_);
+ // Except the copy to have made another texture.
+ EXPECT_EQ(num_textures_without_readback_ + 1, num_textures_with_readback_);
+ }
+};
+
+SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F(
+ LayerTreeHostCopyRequestTestCreatesTexture);
+
+class LayerTreeHostCopyRequestTestProvideTexture
+ : public LayerTreeHostCopyRequestTestCountTextures {
+ protected:
+ virtual void BeginTest() OVERRIDE {
+ external_context_provider_ = TestContextProvider::Create();
+ EXPECT_TRUE(external_context_provider_->BindToCurrentThread());
+ LayerTreeHostCopyRequestTestCountTextures::BeginTest();
+ }
+
+ void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
+ EXPECT_FALSE(result->IsEmpty());
+ EXPECT_TRUE(result->HasTexture());
+
+ TextureMailbox mailbox;
+ scoped_ptr<SingleReleaseCallback> release;
+ result->TakeTexture(&mailbox, &release);
+ EXPECT_FALSE(release);
+ }
+
+ virtual void RequestCopy(Layer* layer) OVERRIDE {
+ // Request a copy to a provided texture. This should not create a new
+ // texture.
+ scoped_ptr<CopyOutputRequest> request =
+ CopyOutputRequest::CreateRequest(base::Bind(
+ &LayerTreeHostCopyRequestTestProvideTexture::CopyOutputCallback,
+ base::Unretained(this)));
+
+ gpu::Mailbox mailbox;
+ external_context_provider_->Context3d()->genMailboxCHROMIUM(mailbox.name);
+ sync_point_ = external_context_provider_->Context3d()->insertSyncPoint();
+ request->SetTextureMailbox(TextureMailbox(mailbox, sync_point_));
+ EXPECT_TRUE(request->has_texture_mailbox());
+
+ copy_layer_->RequestCopyOfOutput(request.Pass());
+ }
+
+ virtual void AfterTest() OVERRIDE {
+ // Expect the compositor to have waited for the sync point in the provided
+ // TextureMailbox.
+ EXPECT_EQ(sync_point_, waited_sync_point_after_readback_);
+ // Except the copy to have *not* made another texture.
+ EXPECT_EQ(num_textures_without_readback_, num_textures_with_readback_);
+ }
+
+ scoped_refptr<TestContextProvider> external_context_provider_;
+ unsigned sync_point_;
+};
+
+SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F(
+ LayerTreeHostCopyRequestTestProvideTexture);
+
+class LayerTreeHostCopyRequestTestDestroyBeforeCopy
+ : public LayerTreeHostCopyRequestTest {
+ protected:
+ virtual void SetupTree() OVERRIDE {
+ root_ = FakeContentLayer::Create(&client_);
+ root_->SetBounds(gfx::Size(20, 20));
+
+ copy_layer_ = FakeContentLayer::Create(&client_);
+ copy_layer_->SetBounds(gfx::Size(10, 10));
+ root_->AddChild(copy_layer_);
+
+ layer_tree_host()->SetRootLayer(root_);
+ LayerTreeHostCopyRequestTest::SetupTree();
+ }
+
+ virtual void BeginTest() OVERRIDE {
+ callback_count_ = 0;
+ PostSetNeedsCommitToMainThread();
+ }
+
+ void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
+ EXPECT_TRUE(result->IsEmpty());
+ ++callback_count_;
+ }
+
+ virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
+ MainThreadTaskRunner()->PostTask(
+ FROM_HERE,
+ base::Bind(&LayerTreeHostCopyRequestTestDestroyBeforeCopy::DidActivate,
+ base::Unretained(this)));
+ }
+
+ void DidActivate() {
+ switch (layer_tree_host()->source_frame_number()) {
+ case 1: {
+ EXPECT_EQ(0, callback_count_);
+ // Put a copy request on the layer, but then don't allow any
+ // drawing to take place.
+ scoped_ptr<CopyOutputRequest> request =
+ CopyOutputRequest::CreateRequest(
+ base::Bind(&LayerTreeHostCopyRequestTestDestroyBeforeCopy::
+ CopyOutputCallback,
+ base::Unretained(this)));
+ copy_layer_->RequestCopyOfOutput(request.Pass());
+
+ layer_tree_host()->SetViewportSize(gfx::Size());
+ break;
+ }
+ case 2:
+ EXPECT_EQ(0, callback_count_);
+ // Remove the copy layer before we were able to draw.
+ copy_layer_->RemoveFromParent();
+ break;
+ case 3:
+ EXPECT_EQ(1, callback_count_);
+ // Allow us to draw now.
+ layer_tree_host()->SetViewportSize(
+ layer_tree_host()->root_layer()->bounds());
+ break;
+ case 4:
+ EXPECT_EQ(1, callback_count_);
+ // We should not have crashed.
+ EndTest();
+ }
+ }
+
+ virtual void AfterTest() OVERRIDE {}
+
+ int callback_count_;
+ FakeContentLayerClient client_;
+ scoped_refptr<FakeContentLayer> root_;
+ scoped_refptr<FakeContentLayer> copy_layer_;
+};
+
+SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
+ LayerTreeHostCopyRequestTestDestroyBeforeCopy);
+
+} // namespace
+} // namespace cc
diff --git a/chromium/cc/trees/layer_tree_host_unittest_damage.cc b/chromium/cc/trees/layer_tree_host_unittest_damage.cc
index 64c7d4b7c30..7f008b46808 100644
--- a/chromium/cc/trees/layer_tree_host_unittest_damage.cc
+++ b/chromium/cc/trees/layer_tree_host_unittest_damage.cc
@@ -23,103 +23,6 @@ namespace {
// These tests deal with damage tracking.
class LayerTreeHostDamageTest : public LayerTreeTest {};
-// Changing visibility alone does not cause drawing.
-class LayerTreeHostDamageTestSetVisibleDoesNotDraw
- : public LayerTreeHostDamageTest {
- virtual void BeginTest() OVERRIDE {
- step_ = 0;
- PostSetNeedsCommitToMainThread();
- }
-
- virtual void SetupTree() OVERRIDE {
- // Viewport is 10x10.
- scoped_refptr<FakeContentLayer> root = FakeContentLayer::Create(&client_);
- root->SetBounds(gfx::Size(10, 10));
-
- layer_tree_host()->SetRootLayer(root);
- LayerTreeHostDamageTest::SetupTree();
- }
-
- virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* impl,
- LayerTreeHostImpl::FrameData* frame_data,
- bool result) OVERRIDE {
- EXPECT_TRUE(result);
-
- RenderSurfaceImpl* root_surface =
- impl->active_tree()->root_layer()->render_surface();
- gfx::RectF root_damage =
- root_surface->damage_tracker()->current_damage_rect();
-
- switch (step_) {
- case 0:
- // The first frame has full damage.
- EXPECT_EQ(gfx::RectF(10.f, 10.f).ToString(), root_damage.ToString());
-
- // No evictions when we become not-visible.
- impl->SetMemoryPolicy(ManagedMemoryPolicy(
- 1000 * 1000 * 1000,
- ManagedMemoryPolicy::CUTOFF_ALLOW_EVERYTHING,
- 1000 * 1000 * 1000,
- ManagedMemoryPolicy::CUTOFF_ALLOW_EVERYTHING,
- ManagedMemoryPolicy::kDefaultNumResourcesLimit));
-
- PostSetVisibleToMainThread(false);
- break;
- case 1:
- // The compositor has been set not-visible.
- EXPECT_FALSE(impl->visible());
- // This frame not visible, so not drawn.
- NOTREACHED();
- break;
- case 2:
- // The compositor has been set visible again.
- EXPECT_TRUE(impl->visible());
- // But it still does not draw.
- NOTREACHED();
- break;
- case 3:
- // Finally we force a draw, but it will have no damage.
- EXPECT_EQ(gfx::RectF().ToString(), root_damage.ToString());
- EndTest();
- break;
- case 4:
- NOTREACHED();
- }
- return result;
- }
-
- virtual void DidSetVisibleOnImplTree(LayerTreeHostImpl* impl,
- bool visible) OVERRIDE {
- if (!visible) {
- EXPECT_EQ(0, step_);
- PostSetVisibleToMainThread(true);
- } else {
- EXPECT_EQ(1, step_);
-
- base::MessageLoopProxy::current()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&LayerTreeHostDamageTestSetVisibleDoesNotDraw::Redraw,
- base::Unretained(this),
- impl),
- base::TimeDelta::FromMilliseconds(10));
- }
- ++step_;
- }
-
- void Redraw(LayerTreeHostImpl* impl) {
- EXPECT_EQ(2, step_);
- impl->SetNeedsRedraw();
- ++step_;
- }
-
- virtual void AfterTest() OVERRIDE {}
-
- int step_;
- FakeContentLayerClient client_;
-};
-
-SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDamageTestSetVisibleDoesNotDraw);
-
// LayerTreeHost::SetNeedsRedraw should damage the whole viewport.
class LayerTreeHostDamageTestSetNeedsRedraw
: public LayerTreeHostDamageTest {
@@ -331,7 +234,8 @@ class LayerTreeHostDamageTestNoDamageDoesNotSwap
int did_swap_and_succeed_;
};
-SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDamageTestNoDamageDoesNotSwap);
+SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F(
+ LayerTreeHostDamageTestNoDamageDoesNotSwap);
class LayerTreeHostDamageTestNoDamageReadbackDoesDraw
: public LayerTreeHostDamageTest {
@@ -459,18 +363,24 @@ class LayerTreeHostDamageTestForcedFullDamage : public LayerTreeHostDamageTest {
child_damage_rect_ = gfx::RectF(10, 11, 12, 13);
break;
case 3:
- if (!delegating_renderer() &&
- !host_impl->settings().impl_side_painting) {
- // The update rect in the child should be damaged.
- // TODO(danakj): Remove this when impl side painting is always on.
- EXPECT_EQ(gfx::RectF(100+10, 100+11, 12, 13).ToString(),
- root_damage.ToString());
- } else {
+ // 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());
+
+ // TODO(danakj): Remove this when impl side painting is always on.
+ if (delegating_renderer() ||
+ host_impl->settings().impl_side_painting) {
// When using a delegating renderer, or using impl side painting, the
// entire child is considered damaged as we need to replace its
- // resources with newly created ones.
- EXPECT_EQ(gfx::RectF(child_->position(), child_->bounds()).ToString(),
- root_damage.ToString());
+ // resources with newly created ones. The damaged area is kept as it
+ // is, but entire child is painted.
+
+ // The paint rect should match the layer bounds.
+ gfx::RectF paint_rect = child_->LastPaintRect();
+ paint_rect.set_origin(child_->position());
+ EXPECT_EQ(gfx::RectF(100, 100, 30, 30).ToString(),
+ paint_rect.ToString());
}
EXPECT_FALSE(frame_data->has_no_damage);
@@ -509,12 +419,13 @@ class LayerTreeHostDamageTestForcedFullDamage : public LayerTreeHostDamageTest {
gfx::RectF child_damage_rect_;
};
-SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDamageTestForcedFullDamage);
+SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F(LayerTreeHostDamageTestForcedFullDamage);
class LayerTreeHostScrollbarDamageTest : public LayerTreeHostDamageTest {
virtual void SetupTree() OVERRIDE {
scoped_refptr<Layer> root_layer = Layer::Create();
root_layer->SetBounds(gfx::Size(400, 400));
+ root_layer->SetMasksToBounds(true);
layer_tree_host()->SetRootLayer(root_layer);
scoped_refptr<Layer> content_layer = FakeContentLayer::Create(&client_);
@@ -614,7 +525,7 @@ class LayerTreeHostDamageTestScrollbarDoesDamage
MULTI_THREAD_TEST_F(LayerTreeHostDamageTestScrollbarDoesDamage);
-class DISABLED_LayerTreeHostDamageTestScrollbarCommitDoesNoDamage
+class LayerTreeHostDamageTestScrollbarCommitDoesNoDamage
: public LayerTreeHostScrollbarDamageTest {
virtual void BeginTest() OVERRIDE {
did_swaps_ = 0;
@@ -687,8 +598,7 @@ class DISABLED_LayerTreeHostDamageTestScrollbarCommitDoesNoDamage
int did_swaps_;
};
-MULTI_THREAD_TEST_F(
- DISABLED_LayerTreeHostDamageTestScrollbarCommitDoesNoDamage);
+MULTI_THREAD_TEST_F(LayerTreeHostDamageTestScrollbarCommitDoesNoDamage);
class LayerTreeHostDamageTestVisibleTilesStillTriggerDraws
: public LayerTreeHostDamageTest {
diff --git a/chromium/cc/trees/layer_tree_host_unittest_delegated.cc b/chromium/cc/trees/layer_tree_host_unittest_delegated.cc
index 012f6f82fdf..195a4acdfa5 100644
--- a/chromium/cc/trees/layer_tree_host_unittest_delegated.cc
+++ b/chromium/cc/trees/layer_tree_host_unittest_delegated.cc
@@ -11,8 +11,9 @@
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread.h"
#include "base/time/time.h"
+#include "cc/layers/delegated_frame_provider.h"
+#include "cc/layers/delegated_frame_resource_collection.h"
#include "cc/layers/delegated_renderer_layer.h"
-#include "cc/layers/delegated_renderer_layer_client.h"
#include "cc/layers/delegated_renderer_layer_impl.h"
#include "cc/output/compositor_frame.h"
#include "cc/output/compositor_frame_ack.h"
@@ -134,6 +135,7 @@ class LayerTreeHostDelegatedTest : public LayerTreeTest {
ResourceProvider::ResourceId resource_id) {
TransferableResource resource;
resource.id = resource_id;
+ resource.target = GL_TEXTURE_2D;
frame->resource_list.push_back(resource);
}
@@ -183,18 +185,11 @@ class LayerTreeHostDelegatedTest : public LayerTreeTest {
damage_rect,
gfx::Rect(0, 0, 1, 1), // mask_uv_rect
filters,
- skia::RefPtr<SkImageFilter>(),
background_filters);
frame->render_pass_list[0]->shared_quad_state_list.push_back(sqs.Pass());
frame->render_pass_list[0]->quad_list.push_back(quad.PassAs<DrawQuad>());
}
- scoped_ptr<DelegatedFrameData> CreateEmptyFrameData() {
- scoped_ptr<DelegatedFrameData> frame(new DelegatedFrameData);
- return frame.Pass();
- }
-
-
static ResourceProvider::ResourceId AppendResourceId(
std::vector<ResourceProvider::ResourceId>* resources_in_last_sent_frame,
ResourceProvider::ResourceId resource_id) {
@@ -209,13 +204,9 @@ class LayerTreeHostDelegatedTest : public LayerTreeTest {
return;
std::vector<ResourceProvider::ResourceId> resources_in_last_sent_frame;
- for (size_t i = 0; i < delegated_frame_data->render_pass_list.size(); ++i) {
- RenderPass* pass = delegated_frame_data->render_pass_list.at(i);
- for (size_t j = 0; j < pass->quad_list.size(); ++j) {
- DrawQuad* quad = pass->quad_list[j];
- quad->IterateResources(base::Bind(&AppendResourceId,
- &resources_in_last_sent_frame));
- }
+ for (size_t i = 0; i < delegated_frame_data->resource_list.size(); ++i) {
+ resources_in_last_sent_frame.push_back(
+ delegated_frame_data->resource_list[i].id);
}
std::vector<ResourceProvider::ResourceId> resources_to_return;
@@ -246,68 +237,80 @@ class LayerTreeHostDelegatedTest : public LayerTreeTest {
class LayerTreeHostDelegatedTestCaseSingleDelegatedLayer
: public LayerTreeHostDelegatedTest,
- public DelegatedRendererLayerClient {
+ public DelegatedFrameResourceCollectionClient {
public:
+ LayerTreeHostDelegatedTestCaseSingleDelegatedLayer()
+ : resource_collection_(new DelegatedFrameResourceCollection),
+ available_(false) {
+ resource_collection_->SetClient(this);
+ }
+
virtual void SetupTree() OVERRIDE {
root_ = Layer::Create();
root_->SetAnchorPoint(gfx::PointF());
root_->SetBounds(gfx::Size(10, 10));
- delegated_ = FakeDelegatedRendererLayer::Create(this);
- delegated_->SetAnchorPoint(gfx::PointF());
- delegated_->SetBounds(gfx::Size(10, 10));
- delegated_->SetIsDrawable(true);
-
- root_->AddChild(delegated_);
layer_tree_host()->SetRootLayer(root_);
LayerTreeHostDelegatedTest::SetupTree();
}
virtual void BeginTest() OVERRIDE {
+ resource_collection_->SetClient(this);
PostSetNeedsCommitToMainThread();
}
- virtual void AfterTest() OVERRIDE {}
+ void SetFrameData(scoped_ptr<DelegatedFrameData> frame_data) {
+ RenderPass* root_pass = frame_data->render_pass_list.back();
+ gfx::Size frame_size = root_pass->output_rect.size();
- virtual void DidCommitFrameData() OVERRIDE {}
-
- protected:
- scoped_refptr<Layer> root_;
- scoped_refptr<DelegatedRendererLayer> delegated_;
-};
+ if (frame_provider_.get() && frame_size == frame_provider_->frame_size()) {
+ frame_provider_->SetFrameData(frame_data.Pass());
+ return;
+ }
-class LayerTreeHostDelegatedTestClientDidCommitCallback
- : public LayerTreeHostDelegatedTestCaseSingleDelegatedLayer {
- public:
- LayerTreeHostDelegatedTestClientDidCommitCallback()
- : LayerTreeHostDelegatedTestCaseSingleDelegatedLayer(),
- num_did_commit_frame_data_(0) {}
+ if (delegated_.get()) {
+ delegated_->RemoveFromParent();
+ delegated_ = NULL;
+ frame_provider_ = NULL;
+ }
- virtual void DidCommit() OVERRIDE {
- if (TestEnded())
- return;
+ frame_provider_ = new DelegatedFrameProvider(resource_collection_.get(),
+ frame_data.Pass());
- EXPECT_EQ(1, num_did_commit_frame_data_);
- EndTest();
+ delegated_ = CreateDelegatedLayer(frame_provider_.get());
}
- virtual void BeginTest() OVERRIDE {
- delegated_->SetFrameData(CreateFrameData(gfx::Rect(0, 0, 1, 1),
- gfx::Rect(0, 0, 1, 1)));
- PostSetNeedsCommitToMainThread();
+ scoped_refptr<DelegatedRendererLayer> CreateDelegatedLayer(
+ DelegatedFrameProvider* frame_provider) {
+ scoped_refptr<DelegatedRendererLayer> delegated =
+ FakeDelegatedRendererLayer::Create(frame_provider);
+ delegated->SetAnchorPoint(gfx::PointF());
+ delegated->SetBounds(gfx::Size(10, 10));
+ delegated->SetIsDrawable(true);
+
+ root_->AddChild(delegated);
+ return delegated;
}
- virtual void DidCommitFrameData() OVERRIDE {
- num_did_commit_frame_data_++;
+ virtual void AfterTest() OVERRIDE { resource_collection_->SetClient(NULL); }
+
+ // DelegatedFrameProviderClient implementation.
+ virtual void UnusedResourcesAreAvailable() OVERRIDE { available_ = true; }
+
+ bool TestAndResetAvailable() {
+ bool available = available_;
+ available_ = false;
+ return available;
}
protected:
- int num_did_commit_frame_data_;
+ scoped_refptr<DelegatedFrameResourceCollection> resource_collection_;
+ scoped_refptr<DelegatedFrameProvider> frame_provider_;
+ scoped_refptr<Layer> root_;
+ scoped_refptr<DelegatedRendererLayer> delegated_;
+ bool available_;
};
-SINGLE_AND_MULTI_THREAD_TEST_F(
- LayerTreeHostDelegatedTestClientDidCommitCallback);
-
class LayerTreeHostDelegatedTestCreateChildId
: public LayerTreeHostDelegatedTestCaseSingleDelegatedLayer {
public:
@@ -319,11 +322,13 @@ class LayerTreeHostDelegatedTestCreateChildId
virtual void DidCommit() OVERRIDE {
if (TestEnded())
return;
- delegated_->SetFrameData(CreateFrameData(gfx::Rect(0, 0, 1, 1),
- gfx::Rect(0, 0, 1, 1)));
+ SetFrameData(CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1)));
}
virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
+ if (host_impl->active_tree()->source_frame_number() < 1)
+ return;
+
LayerImpl* root_impl = host_impl->active_tree()->root_layer();
FakeDelegatedRendererLayerImpl* delegated_impl =
static_cast<FakeDelegatedRendererLayerImpl*>(root_impl->children()[0]);
@@ -365,8 +370,6 @@ class LayerTreeHostDelegatedTestCreateChildId
did_reset_child_id_ = true;
}
- virtual void AfterTest() OVERRIDE {}
-
protected:
int num_activates_;
bool did_reset_child_id_;
@@ -381,7 +384,7 @@ class LayerTreeHostDelegatedTestOffscreenContext_NoFilters
scoped_ptr<DelegatedFrameData> frame =
CreateFrameData(gfx::Rect(0, 0, 1, 1),
gfx::Rect(0, 0, 1, 1));
- delegated_->SetFrameData(frame.Pass());
+ SetFrameData(frame.Pass());
PostSetNeedsCommitToMainThread();
}
@@ -390,8 +393,6 @@ class LayerTreeHostDelegatedTestOffscreenContext_NoFilters
EXPECT_FALSE(host_impl->offscreen_context_provider());
EndTest();
}
-
- virtual void AfterTest() OVERRIDE {}
};
SINGLE_AND_MULTI_THREAD_TEST_F(
@@ -413,7 +414,7 @@ class LayerTreeHostDelegatedTestOffscreenContext_Filters
gfx::Rect(0, 0, 1, 1),
filters,
FilterOperations());
- delegated_->SetFrameData(frame.Pass());
+ SetFrameData(frame.Pass());
PostSetNeedsCommitToMainThread();
}
@@ -423,8 +424,6 @@ class LayerTreeHostDelegatedTestOffscreenContext_Filters
EXPECT_EQ(expect_context, !!host_impl->offscreen_context_provider());
EndTest();
}
-
- virtual void AfterTest() OVERRIDE {}
};
SINGLE_AND_MULTI_THREAD_TEST_F(
@@ -446,7 +445,7 @@ class LayerTreeHostDelegatedTestOffscreenContext_BackgroundFilters
gfx::Rect(0, 0, 1, 1),
FilterOperations(),
filters);
- delegated_->SetFrameData(frame.Pass());
+ SetFrameData(frame.Pass());
PostSetNeedsCommitToMainThread();
}
@@ -456,8 +455,6 @@ class LayerTreeHostDelegatedTestOffscreenContext_BackgroundFilters
EXPECT_EQ(expect_context, !!host_impl->offscreen_context_provider());
EndTest();
}
-
- virtual void AfterTest() OVERRIDE {}
};
SINGLE_AND_MULTI_THREAD_TEST_F(
@@ -467,21 +464,24 @@ class LayerTreeHostDelegatedTestOffscreenContext_Filters_AddedToTree
: public LayerTreeHostDelegatedTestCaseSingleDelegatedLayer {
protected:
virtual void BeginTest() OVERRIDE {
- scoped_ptr<DelegatedFrameData> frame =
- CreateFrameData(gfx::Rect(0, 0, 1, 1),
- gfx::Rect(0, 0, 1, 1));
+ scoped_ptr<DelegatedFrameData> frame_no_filters =
+ CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1));
+
+ scoped_ptr<DelegatedFrameData> frame_with_filters =
+ CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1));
FilterOperations filters;
filters.Append(FilterOperation::CreateGrayscaleFilter(0.5f));
- AddRenderPass(frame.get(),
+ AddRenderPass(frame_with_filters.get(),
RenderPass::Id(2, 1),
gfx::Rect(0, 0, 1, 1),
gfx::Rect(0, 0, 1, 1),
filters,
FilterOperations());
+ SetFrameData(frame_no_filters.Pass());
delegated_->RemoveFromParent();
- delegated_->SetFrameData(frame.Pass());
+ SetFrameData(frame_with_filters.Pass());
layer_tree_host()->root_layer()->AddChild(delegated_);
PostSetNeedsCommitToMainThread();
@@ -492,8 +492,6 @@ class LayerTreeHostDelegatedTestOffscreenContext_Filters_AddedToTree
EXPECT_EQ(expect_context, !!host_impl->offscreen_context_provider());
EndTest();
}
-
- virtual void AfterTest() OVERRIDE {}
};
SINGLE_AND_MULTI_THREAD_TEST_F(
@@ -512,101 +510,112 @@ class LayerTreeHostDelegatedTestLayerUsesFrameDamage
case 1:
// The first time the layer gets a frame the whole layer should be
// damaged.
- delegated_->SetFrameData(CreateFrameData(gfx::Rect(0, 0, 1, 1),
- gfx::Rect(0, 0, 1, 1)));
+ SetFrameData(
+ CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1)));
break;
case 2:
+ // A different frame size will damage the whole layer.
+ SetFrameData(
+ CreateFrameData(gfx::Rect(0, 0, 20, 20), gfx::Rect(0, 0, 0, 0)));
+ break;
+ case 3:
// Should create a total amount of gfx::Rect(2, 2, 10, 6) damage.
// The frame size is 20x20 while the layer is 10x10, so this should
// produce a gfx::Rect(1, 1, 5, 3) damage rect.
- delegated_->SetFrameData(CreateFrameData(gfx::Rect(0, 0, 20, 20),
- gfx::Rect(2, 2, 5, 5)));
- delegated_->SetFrameData(CreateFrameData(gfx::Rect(0, 0, 20, 20),
- gfx::Rect(7, 2, 5, 6)));
+ SetFrameData(
+ CreateFrameData(gfx::Rect(0, 0, 20, 20), gfx::Rect(2, 2, 5, 5)));
+ SetFrameData(
+ CreateFrameData(gfx::Rect(0, 0, 20, 20), gfx::Rect(7, 2, 5, 6)));
break;
- case 3:
+ case 4:
// Should create zero damage.
layer_tree_host()->SetNeedsCommit();
break;
- case 4:
+ case 5:
// Should damage the full viewport.
delegated_->SetBounds(gfx::Size(2, 2));
break;
- case 5:
+ case 6:
// Should create zero damage.
layer_tree_host()->SetNeedsCommit();
break;
- case 6:
- // Should damage the full layer.
+ case 7:
+ // Should damage the full layer, tho the frame size is not changing.
delegated_->SetBounds(gfx::Size(6, 6));
- delegated_->SetFrameData(CreateFrameData(gfx::Rect(0, 0, 5, 5),
- gfx::Rect(1, 1, 2, 2)));
+ SetFrameData(
+ CreateFrameData(gfx::Rect(0, 0, 20, 20), gfx::Rect(1, 1, 2, 2)));
break;
- case 7:
+ case 8:
// Should create zero damage.
layer_tree_host()->SetNeedsCommit();
break;
- case 8:
+ case 9:
// Should damage the full layer.
delegated_->SetDisplaySize(gfx::Size(10, 10));
break;
- case 9:
+ case 10:
// Should create zero damage.
layer_tree_host()->SetNeedsCommit();
break;
- case 10:
- // Setting an empty frame should damage the whole layer the
- // first time.
- delegated_->SetFrameData(CreateEmptyFrameData());
- break;
case 11:
- // Setting an empty frame shouldn't damage anything after the
- // first time.
- delegated_->SetFrameData(CreateEmptyFrameData());
+ // Changing the frame size damages the full layer.
+ SetFrameData(
+ CreateFrameData(gfx::Rect(0, 0, 5, 5), gfx::Rect(4, 4, 1, 1)));
break;
case 12:
- // Having valid content to display agains should damage the whole layer.
- delegated_->SetFrameData(CreateFrameData(gfx::Rect(0, 0, 10, 10),
- gfx::Rect(5, 5, 1, 1)));
- break;
- case 13:
// An invalid frame isn't used, so it should not cause damage.
- delegated_->SetFrameData(CreateInvalidFrameData(gfx::Rect(0, 0, 10, 10),
- gfx::Rect(5, 5, 1, 1)));
+ SetFrameData(CreateInvalidFrameData(gfx::Rect(0, 0, 5, 5),
+ gfx::Rect(4, 4, 1, 1)));
break;
- case 14:
+ case 13:
// Should create gfx::Rect(1, 1, 2, 2) of damage. The frame size is
// 5x5 and the display size is now set to 10x10, so this should result
// in a gfx::Rect(2, 2, 4, 4) damage rect.
- delegated_->SetFrameData(CreateFrameData(gfx::Rect(0, 0, 5, 5),
- gfx::Rect(1, 1, 2, 2)));
+ SetFrameData(
+ CreateFrameData(gfx::Rect(0, 0, 5, 5), gfx::Rect(1, 1, 2, 2)));
break;
- case 15:
+ case 14:
// Should create zero damage.
layer_tree_host()->SetNeedsCommit();
break;
- case 16:
+ case 15:
// Moving the layer out of the tree and back in will damage the whole
// impl layer.
delegated_->RemoveFromParent();
layer_tree_host()->root_layer()->AddChild(delegated_);
break;
- case 17:
+ case 16:
// Make a larger frame with lots of damage. Then a frame smaller than
// the first frame's damage. The entire layer should be damaged, but
// nothing more.
- delegated_->SetFrameData(CreateFrameData(gfx::Rect(0, 0, 10, 10),
- gfx::Rect(0, 0, 10, 10)));
- delegated_->SetFrameData(CreateFrameData(gfx::Rect(0, 0, 5, 5),
- gfx::Rect(1, 1, 2, 2)));
+ SetFrameData(
+ CreateFrameData(gfx::Rect(0, 0, 10, 10), gfx::Rect(0, 0, 10, 10)));
+ SetFrameData(
+ CreateFrameData(gfx::Rect(0, 0, 5, 5), gfx::Rect(1, 1, 2, 2)));
break;
- case 18:
- // Make a frame with lots of damage. Then replace it with an empty
- // frame. The entire layer should be damaged, but nothing more.
- delegated_->SetFrameData(CreateFrameData(gfx::Rect(0, 0, 10, 10),
- gfx::Rect(0, 0, 10, 10)));
- delegated_->SetFrameData(CreateEmptyFrameData());
+ case 17:
+ // Make a frame with lots of damage. Then replace it with a frame with
+ // no damage. The entire layer should be damaged, but nothing more.
+ SetFrameData(
+ CreateFrameData(gfx::Rect(0, 0, 10, 10), gfx::Rect(0, 0, 10, 10)));
+ SetFrameData(
+ CreateFrameData(gfx::Rect(0, 0, 10, 10), gfx::Rect(0, 0, 0, 0)));
break;
+ case 18:
+ // Make another layer that uses the same frame provider. The new layer
+ // should be damaged.
+ delegated_copy_ = CreateDelegatedLayer(frame_provider_);
+ delegated_copy_->SetPosition(gfx::Point(5, 0));
+
+ // Also set a new frame.
+ SetFrameData(
+ CreateFrameData(gfx::Rect(0, 0, 10, 10), gfx::Rect(4, 0, 1, 1)));
+ break;
+ case 19:
+ // Set another new frame, both layers should be damaged in the same
+ // ways.
+ SetFrameData(
+ CreateFrameData(gfx::Rect(0, 0, 10, 10), gfx::Rect(3, 3, 1, 1)));
}
first_draw_for_source_frame_ = true;
}
@@ -638,71 +647,76 @@ class LayerTreeHostDelegatedTestLayerUsesFrameDamage
damage_rect.ToString());
break;
case 2:
- EXPECT_EQ(gfx::RectF(1.f, 1.f, 5.f, 3.f).ToString(),
+ EXPECT_EQ(gfx::RectF(0.f, 0.f, 10.f, 10.f).ToString(),
damage_rect.ToString());
break;
case 3:
- EXPECT_EQ(gfx::RectF(0.f, 0.f, 0.f, 0.f).ToString(),
+ EXPECT_EQ(gfx::RectF(1.f, 1.f, 5.f, 3.f).ToString(),
damage_rect.ToString());
break;
case 4:
- EXPECT_EQ(gfx::RectF(0.f, 0.f, 10.f, 10.f).ToString(),
+ EXPECT_EQ(gfx::RectF(0.f, 0.f, 0.f, 0.f).ToString(),
damage_rect.ToString());
break;
case 5:
- EXPECT_EQ(gfx::RectF(0.f, 0.f, 0.f, 0.f).ToString(),
+ EXPECT_EQ(gfx::RectF(0.f, 0.f, 10.f, 10.f).ToString(),
damage_rect.ToString());
break;
case 6:
- EXPECT_EQ(gfx::RectF(0.f, 0.f, 6.f, 6.f).ToString(),
+ EXPECT_EQ(gfx::RectF(0.f, 0.f, 0.f, 0.f).ToString(),
damage_rect.ToString());
break;
case 7:
- EXPECT_EQ(gfx::RectF(0.f, 0.f, 0.f, 0.f).ToString(),
+ EXPECT_EQ(gfx::RectF(0.f, 0.f, 6.f, 6.f).ToString(),
damage_rect.ToString());
break;
case 8:
- EXPECT_EQ(gfx::RectF(0.f, 0.f, 6.f, 6.f).ToString(),
+ EXPECT_EQ(gfx::RectF(0.f, 0.f, 0.f, 0.f).ToString(),
damage_rect.ToString());
break;
case 9:
- EXPECT_EQ(gfx::RectF(0.f, 0.f, 0.f, 0.f).ToString(),
+ EXPECT_EQ(gfx::RectF(0.f, 0.f, 6.f, 6.f).ToString(),
damage_rect.ToString());
break;
case 10:
- EXPECT_EQ(gfx::RectF(0.f, 0.f, 6.f, 6.f).ToString(),
+ EXPECT_EQ(gfx::RectF(0.f, 0.f, 0.f, 0.f).ToString(),
damage_rect.ToString());
break;
case 11:
- EXPECT_EQ(gfx::RectF(0.f, 0.f, 0.f, 0.f).ToString(),
+ EXPECT_EQ(gfx::RectF(0.f, 0.f, 10.f, 10.f).ToString(),
damage_rect.ToString());
break;
case 12:
- EXPECT_EQ(gfx::RectF(0.f, 0.f, 6.f, 6.f).ToString(),
+ EXPECT_EQ(gfx::RectF(0.f, 0.f, 0.f, 0.f).ToString(),
damage_rect.ToString());
break;
case 13:
- EXPECT_EQ(gfx::RectF(0.f, 0.f, 0.f, 0.f).ToString(),
+ EXPECT_EQ(gfx::RectF(2.f, 2.f, 4.f, 4.f).ToString(),
damage_rect.ToString());
break;
case 14:
- EXPECT_EQ(gfx::RectF(2.f, 2.f, 4.f, 4.f).ToString(),
+ EXPECT_EQ(gfx::RectF(0.f, 0.f, 0.f, 0.f).ToString(),
damage_rect.ToString());
break;
case 15:
- EXPECT_EQ(gfx::RectF(0.f, 0.f, 0.f, 0.f).ToString(),
+ EXPECT_EQ(gfx::RectF(0.f, 0.f, 10.f, 10.f).ToString(),
damage_rect.ToString());
break;
case 16:
- EXPECT_EQ(gfx::RectF(0.f, 0.f, 6.f, 6.f).ToString(),
+ EXPECT_EQ(gfx::RectF(0.f, 0.f, 10.f, 10.f).ToString(),
damage_rect.ToString());
break;
case 17:
- EXPECT_EQ(gfx::RectF(0.f, 0.f, 6.f, 6.f).ToString(),
+ EXPECT_EQ(gfx::RectF(0.f, 0.f, 10.f, 10.f).ToString(),
damage_rect.ToString());
break;
case 18:
- EXPECT_EQ(gfx::RectF(0.f, 0.f, 6.f, 6.f).ToString(),
+ EXPECT_EQ(gfx::UnionRects(gfx::RectF(5.f, 0.f, 10.f, 10.f),
+ gfx::RectF(4.f, 0.f, 1.f, 1.f)).ToString(),
+ damage_rect.ToString());
+ break;
+ case 19:
+ EXPECT_EQ(gfx::RectF(3.f, 3.f, 6.f, 1.f).ToString(),
damage_rect.ToString());
EndTest();
break;
@@ -712,6 +726,7 @@ class LayerTreeHostDelegatedTestLayerUsesFrameDamage
}
protected:
+ scoped_refptr<DelegatedRendererLayer> delegated_copy_;
bool first_draw_for_source_frame_;
};
@@ -728,7 +743,7 @@ class LayerTreeHostDelegatedTestMergeResources
CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1));
AddTextureQuad(frame1.get(), 999);
AddTransferableResource(frame1.get(), 999);
- delegated_->SetFrameData(frame1.Pass());
+ SetFrameData(frame1.Pass());
// The second frame uses resource 999 still, but also adds 555.
scoped_ptr<DelegatedFrameData> frame2 =
@@ -737,15 +752,17 @@ class LayerTreeHostDelegatedTestMergeResources
AddTransferableResource(frame2.get(), 999);
AddTextureQuad(frame2.get(), 555);
AddTransferableResource(frame2.get(), 555);
- delegated_->SetFrameData(frame2.Pass());
+ SetFrameData(frame2.Pass());
// The resource 999 from frame1 is returned since it is still on the main
// thread.
ReturnedResourceArray returned_resources;
- delegated_->TakeUnusedResourcesForChildCompositor(&returned_resources);
+ resource_collection_->TakeUnusedResourcesForChildCompositor(
+ &returned_resources);
{
unsigned expected[] = {999};
EXPECT_RESOURCES(expected, returned_resources);
+ EXPECT_TRUE(TestAndResetAvailable());
}
PostSetNeedsCommitToMainThread();
@@ -771,8 +788,6 @@ class LayerTreeHostDelegatedTestMergeResources
EndTest();
}
-
- virtual void AfterTest() OVERRIDE {}
};
SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDelegatedTestMergeResources);
@@ -788,7 +803,7 @@ class LayerTreeHostDelegatedTestRemapResourcesInQuads
AddTransferableResource(frame.get(), 999);
AddTextureQuad(frame.get(), 555);
AddTransferableResource(frame.get(), 555);
- delegated_->SetFrameData(frame.Pass());
+ SetFrameData(frame.Pass());
PostSetNeedsCommitToMainThread();
}
@@ -822,8 +837,6 @@ class LayerTreeHostDelegatedTestRemapResourcesInQuads
EndTest();
}
-
- virtual void AfterTest() OVERRIDE {}
};
SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDelegatedTestRemapResourcesInQuads);
@@ -848,12 +861,13 @@ class LayerTreeHostDelegatedTestReturnUnusedResources
AddTransferableResource(frame.get(), 999);
AddTextureQuad(frame.get(), 555);
AddTransferableResource(frame.get(), 555);
- delegated_->SetFrameData(frame.Pass());
+ SetFrameData(frame.Pass());
break;
case 2:
// All of the resources are in use.
- delegated_->TakeUnusedResourcesForChildCompositor(&resources);
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
EXPECT_EQ(0u, resources.size());
+ EXPECT_FALSE(TestAndResetAvailable());
// Keep using 999 but stop using 555.
frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1));
@@ -861,19 +875,20 @@ class LayerTreeHostDelegatedTestReturnUnusedResources
AddTransferableResource(frame.get(), 999);
AddTextureQuad(frame.get(), 444);
AddTransferableResource(frame.get(), 444);
- delegated_->SetFrameData(frame.Pass());
+ SetFrameData(frame.Pass());
break;
case 3:
// 555 is no longer in use.
- delegated_->TakeUnusedResourcesForChildCompositor(&resources);
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
{
unsigned expected[] = {555};
EXPECT_RESOURCES(expected, resources);
+ EXPECT_TRUE(TestAndResetAvailable());
}
// Stop using any resources.
frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1));
- delegated_->SetFrameData(frame.Pass());
+ SetFrameData(frame.Pass());
break;
case 4:
// Postpone collecting resources for a frame. They should still be there
@@ -883,27 +898,28 @@ class LayerTreeHostDelegatedTestReturnUnusedResources
case 5:
// 444 and 999 are no longer in use. We sent two refs to 999, so we
// should get two back.
- delegated_->TakeUnusedResourcesForChildCompositor(&resources);
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
{
unsigned expected[] = {444, 999, 999};
EXPECT_RESOURCES(expected, resources);
+ EXPECT_TRUE(TestAndResetAvailable());
}
EndTest();
break;
}
- // Resource are never immediately released.
+ // Resources are never immediately released.
ReturnedResourceArray empty_resources;
- delegated_->TakeUnusedResourcesForChildCompositor(&empty_resources);
- EXPECT_TRUE(empty_resources.empty());
+ resource_collection_->TakeUnusedResourcesForChildCompositor(
+ &empty_resources);
+ EXPECT_EQ(0u, empty_resources.size());
+ EXPECT_FALSE(TestAndResetAvailable());
}
virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
bool result) OVERRIDE {
ReturnUnusedResourcesFromParent(host_impl);
}
-
- virtual void AfterTest() OVERRIDE {}
};
SINGLE_AND_MULTI_THREAD_TEST_F(
@@ -931,22 +947,24 @@ class LayerTreeHostDelegatedTestReusedResources
AddTransferableResource(frame.get(), 555);
AddTextureQuad(frame.get(), 444);
AddTransferableResource(frame.get(), 444);
- delegated_->SetFrameData(frame.Pass());
+ SetFrameData(frame.Pass());
break;
case 2:
// All of the resources are in use.
- delegated_->TakeUnusedResourcesForChildCompositor(&resources);
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
EXPECT_EQ(0u, resources.size());
+ EXPECT_FALSE(TestAndResetAvailable());
// Keep using 999 but stop using 555 and 444.
frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1));
AddTextureQuad(frame.get(), 999);
AddTransferableResource(frame.get(), 999);
- delegated_->SetFrameData(frame.Pass());
+ SetFrameData(frame.Pass());
// Resource are not immediately released.
- delegated_->TakeUnusedResourcesForChildCompositor(&resources);
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
EXPECT_EQ(0u, resources.size());
+ EXPECT_FALSE(TestAndResetAvailable());
// Now using 555 and 444 again, but not 999.
frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1));
@@ -954,15 +972,16 @@ class LayerTreeHostDelegatedTestReusedResources
AddTransferableResource(frame.get(), 555);
AddTextureQuad(frame.get(), 444);
AddTransferableResource(frame.get(), 444);
- delegated_->SetFrameData(frame.Pass());
+ SetFrameData(frame.Pass());
break;
case 3:
// The 999 resource is the only unused one. Two references were sent, so
// two should be returned.
- delegated_->TakeUnusedResourcesForChildCompositor(&resources);
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
{
unsigned expected[] = {999, 999};
EXPECT_RESOURCES(expected, resources);
+ EXPECT_TRUE(TestAndResetAvailable());
}
EndTest();
break;
@@ -973,8 +992,6 @@ class LayerTreeHostDelegatedTestReusedResources
bool result) OVERRIDE {
ReturnUnusedResourcesFromParent(host_impl);
}
-
- virtual void AfterTest() OVERRIDE {}
};
SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDelegatedTestReusedResources);
@@ -1001,30 +1018,33 @@ class LayerTreeHostDelegatedTestFrameBeforeAck
AddTransferableResource(frame.get(), 555);
AddTextureQuad(frame.get(), 444);
AddTransferableResource(frame.get(), 444);
- delegated_->SetFrameData(frame.Pass());
+ SetFrameData(frame.Pass());
break;
case 2:
// All of the resources are in use.
- delegated_->TakeUnusedResourcesForChildCompositor(&resources);
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
EXPECT_EQ(0u, resources.size());
+ EXPECT_FALSE(TestAndResetAvailable());
// Keep using 999 but stop using 555 and 444.
frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1));
AddTextureQuad(frame.get(), 999);
AddTransferableResource(frame.get(), 999);
- delegated_->SetFrameData(frame.Pass());
+ SetFrameData(frame.Pass());
// Resource are not immediately released.
- delegated_->TakeUnusedResourcesForChildCompositor(&resources);
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
EXPECT_EQ(0u, resources.size());
+ EXPECT_FALSE(TestAndResetAvailable());
// The parent compositor (this one) does a commit.
break;
case 3:
- delegated_->TakeUnusedResourcesForChildCompositor(&resources);
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
{
unsigned expected[] = {444, 555};
EXPECT_RESOURCES(expected, resources);
+ EXPECT_TRUE(TestAndResetAvailable());
}
// The child compositor sends a frame referring to resources not in the
@@ -1033,7 +1053,7 @@ class LayerTreeHostDelegatedTestFrameBeforeAck
AddTextureQuad(frame.get(), 999);
AddTextureQuad(frame.get(), 555);
AddTextureQuad(frame.get(), 444);
- delegated_->SetFrameData(frame.Pass());
+ SetFrameData(frame.Pass());
break;
}
}
@@ -1072,8 +1092,6 @@ class LayerTreeHostDelegatedTestFrameBeforeAck
bool result) OVERRIDE {
ReturnUnusedResourcesFromParent(host_impl);
}
-
- virtual void AfterTest() OVERRIDE {}
};
SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDelegatedTestFrameBeforeAck);
@@ -1100,22 +1118,24 @@ class LayerTreeHostDelegatedTestFrameBeforeTakeResources
AddTransferableResource(frame.get(), 555);
AddTextureQuad(frame.get(), 444);
AddTransferableResource(frame.get(), 444);
- delegated_->SetFrameData(frame.Pass());
+ SetFrameData(frame.Pass());
break;
case 2:
// All of the resources are in use.
- delegated_->TakeUnusedResourcesForChildCompositor(&resources);
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
EXPECT_EQ(0u, resources.size());
+ EXPECT_FALSE(TestAndResetAvailable());
// Keep using 999 but stop using 555 and 444.
frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1));
AddTextureQuad(frame.get(), 999);
AddTransferableResource(frame.get(), 999);
- delegated_->SetFrameData(frame.Pass());
+ SetFrameData(frame.Pass());
// Resource are not immediately released.
- delegated_->TakeUnusedResourcesForChildCompositor(&resources);
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
EXPECT_EQ(0u, resources.size());
+ EXPECT_FALSE(TestAndResetAvailable());
// The parent compositor (this one) does a commit.
break;
@@ -1130,19 +1150,21 @@ class LayerTreeHostDelegatedTestFrameBeforeTakeResources
AddTransferableResource(frame.get(), 555);
AddTextureQuad(frame.get(), 444);
AddTransferableResource(frame.get(), 444);
- delegated_->SetFrameData(frame.Pass());
+ SetFrameData(frame.Pass());
// The resources are used by the new frame but are returned anyway since
// we passed them again.
- delegated_->TakeUnusedResourcesForChildCompositor(&resources);
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
{
unsigned expected[] = {444, 555};
EXPECT_RESOURCES(expected, resources);
+ EXPECT_TRUE(TestAndResetAvailable());
}
break;
case 4:
- delegated_->TakeUnusedResourcesForChildCompositor(&resources);
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
EXPECT_EQ(0u, resources.size());
+ EXPECT_FALSE(TestAndResetAvailable());
EndTest();
break;
}
@@ -1189,8 +1211,6 @@ class LayerTreeHostDelegatedTestFrameBeforeTakeResources
bool result) OVERRIDE {
ReturnUnusedResourcesFromParent(host_impl);
}
-
- virtual void AfterTest() OVERRIDE {}
};
SINGLE_AND_MULTI_THREAD_TEST_F(
@@ -1216,12 +1236,13 @@ class LayerTreeHostDelegatedTestBadFrame
AddTransferableResource(frame.get(), 999);
AddTextureQuad(frame.get(), 555);
AddTransferableResource(frame.get(), 555);
- delegated_->SetFrameData(frame.Pass());
+ SetFrameData(frame.Pass());
break;
case 2:
// All of the resources are in use.
- delegated_->TakeUnusedResourcesForChildCompositor(&resources);
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
EXPECT_EQ(0u, resources.size());
+ EXPECT_FALSE(TestAndResetAvailable());
// Generate a bad frame with a resource the layer doesn't have. The
// 885 and 775 resources are unknown, while ownership of the legit 444
@@ -1233,29 +1254,35 @@ class LayerTreeHostDelegatedTestBadFrame
AddTextureQuad(frame.get(), 444);
AddTransferableResource(frame.get(), 444);
AddTextureQuad(frame.get(), 775);
- delegated_->SetFrameData(frame.Pass());
+ SetFrameData(frame.Pass());
// The parent compositor (this one) does a commit.
break;
case 3:
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
+ EXPECT_EQ(0u, resources.size());
+ EXPECT_FALSE(TestAndResetAvailable());
+
+ // Now send a good frame with 999 again.
+ frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1));
+ AddTextureQuad(frame.get(), 999);
+ SetFrameData(frame.Pass());
+
// The bad frame's resource is given back to the child compositor.
- delegated_->TakeUnusedResourcesForChildCompositor(&resources);
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
{
unsigned expected[] = {444};
EXPECT_RESOURCES(expected, resources);
+ EXPECT_TRUE(TestAndResetAvailable());
}
-
- // Now send a good frame with 999 again.
- frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1));
- AddTextureQuad(frame.get(), 999);
- delegated_->SetFrameData(frame.Pass());
break;
case 4:
// The unused 555 from the last good frame is now released.
- delegated_->TakeUnusedResourcesForChildCompositor(&resources);
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
{
unsigned expected[] = {555};
EXPECT_RESOURCES(expected, resources);
+ EXPECT_TRUE(TestAndResetAvailable());
}
EndTest();
@@ -1339,8 +1366,6 @@ class LayerTreeHostDelegatedTestBadFrame
}
}
}
-
- virtual void AfterTest() OVERRIDE {}
};
SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDelegatedTestBadFrame);
@@ -1364,14 +1389,23 @@ class LayerTreeHostDelegatedTestUnnamedResource
AddTransferableResource(frame.get(), 999);
AddTextureQuad(frame.get(), 555);
AddTransferableResource(frame.get(), 555);
- delegated_->SetFrameData(frame.Pass());
+ SetFrameData(frame.Pass());
break;
case 2:
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
+ EXPECT_EQ(0u, resources.size());
+ EXPECT_FALSE(TestAndResetAvailable());
+
+ // Now send an empty frame.
+ frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1));
+ SetFrameData(frame.Pass());
+
// The unused resource should be returned.
- delegated_->TakeUnusedResourcesForChildCompositor(&resources);
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
{
unsigned expected[] = {999};
EXPECT_RESOURCES(expected, resources);
+ EXPECT_TRUE(TestAndResetAvailable());
}
EndTest();
@@ -1398,8 +1432,6 @@ class LayerTreeHostDelegatedTestUnnamedResource
EXPECT_EQ(1u, delegated_impl->Resources().size());
EXPECT_EQ(1u, delegated_impl->Resources().count(555));
}
-
- virtual void AfterTest() OVERRIDE {}
};
SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDelegatedTestUnnamedResource);
@@ -1424,33 +1456,35 @@ class LayerTreeHostDelegatedTestDontLeakResource
AddTransferableResource(frame.get(), 999);
AddTextureQuad(frame.get(), 555);
AddTransferableResource(frame.get(), 555);
- delegated_->SetFrameData(frame.Pass());
+ SetFrameData(frame.Pass());
// But then we immediately stop using 999.
frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1));
AddTextureQuad(frame.get(), 555);
AddTransferableResource(frame.get(), 555);
- delegated_->SetFrameData(frame.Pass());
+ SetFrameData(frame.Pass());
break;
case 2:
// The unused resources should be returned. 555 is still used, but it's
// returned once to account for the first frame.
- delegated_->TakeUnusedResourcesForChildCompositor(&resources);
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
{
unsigned expected[] = {555, 999};
EXPECT_RESOURCES(expected, resources);
+ EXPECT_TRUE(TestAndResetAvailable());
}
// Send a frame with no resources in it.
frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1));
- delegated_->SetFrameData(frame.Pass());
+ SetFrameData(frame.Pass());
break;
case 3:
// The now unused resource 555 should be returned.
resources.clear();
- delegated_->TakeUnusedResourcesForChildCompositor(&resources);
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
{
unsigned expected[] = {555};
EXPECT_RESOURCES(expected, resources);
+ EXPECT_TRUE(TestAndResetAvailable());
}
EndTest();
break;
@@ -1481,8 +1515,6 @@ class LayerTreeHostDelegatedTestDontLeakResource
bool result) OVERRIDE {
ReturnUnusedResourcesFromParent(host_impl);
}
-
- virtual void AfterTest() OVERRIDE {}
};
SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDelegatedTestDontLeakResource);
@@ -1503,23 +1535,25 @@ class LayerTreeHostDelegatedTestResourceSentToParent
AddTransferableResource(frame.get(), 999);
AddTextureQuad(frame.get(), 555);
AddTransferableResource(frame.get(), 555);
- delegated_->SetFrameData(frame.Pass());
+ SetFrameData(frame.Pass());
break;
case 2:
- delegated_->TakeUnusedResourcesForChildCompositor(&resources);
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
EXPECT_EQ(0u, resources.size());
+ EXPECT_FALSE(TestAndResetAvailable());
// 999 is in use in the grandparent compositor, generate a frame without
// it present.
frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1));
AddTextureQuad(frame.get(), 555);
AddTransferableResource(frame.get(), 555);
- delegated_->SetFrameData(frame.Pass());
+ SetFrameData(frame.Pass());
break;
case 3:
// Since 999 is in the grandparent it is not returned.
- delegated_->TakeUnusedResourcesForChildCompositor(&resources);
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
EXPECT_EQ(0u, resources.size());
+ EXPECT_FALSE(TestAndResetAvailable());
// The impl side will get back the resource at some point.
ImplThreadTaskRunner()->PostTask(FROM_HERE,
@@ -1542,20 +1576,15 @@ class LayerTreeHostDelegatedTestResourceSentToParent
output_surface()->ReturnResource(map.find(999)->second, &ack);
host_impl->ReclaimResources(&ack);
host_impl->OnSwapBuffersComplete();
-
- // And then it should be released by the DelegatedRendererLayer.
- MainThreadTaskRunner()->PostTask(
- FROM_HERE,
- base::Bind(&LayerTreeHostDelegatedTestResourceSentToParent::
- DidReceiveResourceOnMainThread,
- base::Unretained(this)));
}
- void DidReceiveResourceOnMainThread() {
+ virtual void UnusedResourcesAreAvailable() OVERRIDE {
+ EXPECT_EQ(3, layer_tree_host()->source_frame_number());
+
ReturnedResourceArray resources;
// 999 was returned from the grandparent and could be released.
- delegated_->TakeUnusedResourcesForChildCompositor(&resources);
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
{
unsigned expected[] = {999};
EXPECT_RESOURCES(expected, resources);
@@ -1616,8 +1645,6 @@ class LayerTreeHostDelegatedTestResourceSentToParent
}
}
- virtual void AfterTest() OVERRIDE {}
-
base::Closure receive_resource_on_thread_;
};
@@ -1647,17 +1674,18 @@ class LayerTreeHostDelegatedTestCommitWithoutTake
AddTransferableResource(frame.get(), 555);
AddTextureQuad(frame.get(), 444);
AddTransferableResource(frame.get(), 444);
- delegated_->SetFrameData(frame.Pass());
+ SetFrameData(frame.Pass());
break;
case 2:
- delegated_->TakeUnusedResourcesForChildCompositor(&resources);
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
EXPECT_EQ(0u, resources.size());
+ EXPECT_FALSE(TestAndResetAvailable());
// Stop using 999 and 444 in this frame and commit.
frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1));
AddTextureQuad(frame.get(), 555);
AddTransferableResource(frame.get(), 555);
- delegated_->SetFrameData(frame.Pass());
+ SetFrameData(frame.Pass());
// 999 and 444 will be returned for frame 1, but not 555 since it's in
// the current frame.
break;
@@ -1668,27 +1696,29 @@ class LayerTreeHostDelegatedTestCommitWithoutTake
AddTransferableResource(frame.get(), 999);
AddTextureQuad(frame.get(), 555);
AddTransferableResource(frame.get(), 555);
- delegated_->SetFrameData(frame.Pass());
+ SetFrameData(frame.Pass());
break;
case 4:
// 555 from frame 1 and 2 isn't returned since it's still in use. 999
// from frame 1 is returned though.
- delegated_->TakeUnusedResourcesForChildCompositor(&resources);
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
{
unsigned expected[] = {444, 999};
EXPECT_RESOURCES(expected, resources);
+ EXPECT_TRUE(TestAndResetAvailable());
}
frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1));
- delegated_->SetFrameData(frame.Pass());
+ SetFrameData(frame.Pass());
// 555 will be returned 3 times for frames 1 2 and 3, and 999 will be
// returned once for frame 3.
break;
case 5:
- delegated_->TakeUnusedResourcesForChildCompositor(&resources);
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
{
unsigned expected[] = {555, 555, 555, 999};
EXPECT_RESOURCES(expected, resources);
+ EXPECT_TRUE(TestAndResetAvailable());
}
EndTest();
@@ -1737,8 +1767,6 @@ class LayerTreeHostDelegatedTestCommitWithoutTake
EXPECT_EQ(1u, delegated_impl->Resources().count(555));
}
}
-
- virtual void AfterTest() OVERRIDE {}
};
SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDelegatedTestCommitWithoutTake);
@@ -1748,7 +1776,8 @@ class DelegatedFrameIsActivatedDuringCommit
protected:
DelegatedFrameIsActivatedDuringCommit()
: wait_thread_("WAIT"),
- wait_event_(false, false) {
+ wait_event_(false, false),
+ returned_resource_count_(0) {
wait_thread_.Start();
}
@@ -1759,7 +1788,7 @@ class DelegatedFrameIsActivatedDuringCommit
CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1));
AddTextureQuad(frame.get(), 999);
AddTransferableResource(frame.get(), 999);
- delegated_->SetFrameData(frame.Pass());
+ SetFrameData(frame.Pass());
PostSetNeedsCommitToMainThread();
}
@@ -1797,7 +1826,7 @@ class DelegatedFrameIsActivatedDuringCommit
CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1));
AddTextureQuad(frame.get(), 555);
AddTransferableResource(frame.get(), 555);
- delegated_->SetFrameData(frame.Pass());
+ SetFrameData(frame.Pass());
// So this commit number should complete after the second activate.
EXPECT_EQ(1, layer_tree_host()->source_frame_number());
break;
@@ -1810,9 +1839,6 @@ class DelegatedFrameIsActivatedDuringCommit
// So this commit number should complete after the third activate.
EXPECT_EQ(2, layer_tree_host()->source_frame_number());
break;
- case 3:
- EndTest();
- break;
}
}
@@ -1828,22 +1854,433 @@ class DelegatedFrameIsActivatedDuringCommit
// The activate to remove the layer should have happened before now.
base::AutoLock lock(activate_lock_);
EXPECT_EQ(3, activate_count_);
+
+ scoped_ptr<DelegatedFrameData> frame =
+ CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1));
+ SetFrameData(frame.Pass());
break;
}
}
}
+ virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
+ bool result) OVERRIDE {
+ ReturnUnusedResourcesFromParent(host_impl);
+ }
- virtual void AfterTest() OVERRIDE {}
+ virtual void UnusedResourcesAreAvailable() OVERRIDE {
+ LayerTreeHostDelegatedTestCaseSingleDelegatedLayer::
+ UnusedResourcesAreAvailable();
+ ReturnedResourceArray resources;
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
+ EXPECT_TRUE(TestAndResetAvailable());
+ returned_resource_count_ += resources.size();
+ if (returned_resource_count_ == 2)
+ EndTest();
+ }
base::Thread wait_thread_;
base::WaitableEvent wait_event_;
base::Lock activate_lock_;
int activate_count_;
+ size_t returned_resource_count_;
};
SINGLE_AND_MULTI_THREAD_TEST_F(
DelegatedFrameIsActivatedDuringCommit);
+class LayerTreeHostDelegatedTestTwoImplLayers
+ : public LayerTreeHostDelegatedTestCaseSingleDelegatedLayer {
+ public:
+ virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
+
+ virtual void DidCommitAndDrawFrame() OVERRIDE {
+ scoped_ptr<DelegatedFrameData> frame;
+ ReturnedResourceArray resources;
+
+ int next_source_frame_number = layer_tree_host()->source_frame_number();
+ switch (next_source_frame_number) {
+ case 1:
+ frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1));
+ AddTextureQuad(frame.get(), 999);
+ AddTransferableResource(frame.get(), 999);
+ AddTextureQuad(frame.get(), 555);
+ AddTransferableResource(frame.get(), 555);
+ SetFrameData(frame.Pass());
+ break;
+ case 2:
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
+ EXPECT_EQ(0u, resources.size());
+ EXPECT_FALSE(TestAndResetAvailable());
+
+ // Remove the delegated layer and replace it with a new one. Use the
+ // same frame and resources for it.
+ delegated_->RemoveFromParent();
+ delegated_ = CreateDelegatedLayer(frame_provider_.get());
+ break;
+ case 3:
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
+ EXPECT_EQ(0u, resources.size());
+ EXPECT_FALSE(TestAndResetAvailable());
+
+ // Use a frame with no resources in it.
+ frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1));
+ SetFrameData(frame.Pass());
+ break;
+ case 4:
+ // We gave one frame to the frame provider, so we should get one
+ // ref back for each resource.
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
+ {
+ unsigned expected[] = {555, 999};
+ EXPECT_RESOURCES(expected, resources);
+ EXPECT_TRUE(TestAndResetAvailable());
+ }
+ EndTest();
+ break;
+ }
+ }
+
+ virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
+ bool result) OVERRIDE {
+ ReturnUnusedResourcesFromParent(host_impl);
+ }
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDelegatedTestTwoImplLayers);
+
+class LayerTreeHostDelegatedTestTwoImplLayersTwoFrames
+ : public LayerTreeHostDelegatedTestCaseSingleDelegatedLayer {
+ public:
+ virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
+
+ virtual void DidCommitAndDrawFrame() OVERRIDE {
+ scoped_ptr<DelegatedFrameData> frame;
+ ReturnedResourceArray resources;
+
+ int next_source_frame_number = layer_tree_host()->source_frame_number();
+ switch (next_source_frame_number) {
+ case 1:
+ frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1));
+ AddTextureQuad(frame.get(), 999);
+ AddTransferableResource(frame.get(), 999);
+ AddTextureQuad(frame.get(), 555);
+ AddTransferableResource(frame.get(), 555);
+ SetFrameData(frame.Pass());
+ break;
+ case 2:
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
+ EXPECT_EQ(0u, resources.size());
+ EXPECT_FALSE(TestAndResetAvailable());
+
+ frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1));
+ AddTextureQuad(frame.get(), 999);
+ AddTransferableResource(frame.get(), 999);
+ AddTextureQuad(frame.get(), 555);
+ AddTransferableResource(frame.get(), 555);
+
+ // Remove the delegated layer and replace it with a new one. Make a new
+ // frame but with the same resources for it.
+ delegated_->RemoveFromParent();
+ delegated_ = NULL;
+
+ frame_provider_->SetFrameData(frame.Pass());
+ delegated_ = CreateDelegatedLayer(frame_provider_.get());
+ break;
+ case 3:
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
+ EXPECT_EQ(0u, resources.size());
+ EXPECT_FALSE(TestAndResetAvailable());
+
+ // Use a frame with no resources in it.
+ frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1));
+ SetFrameData(frame.Pass());
+ break;
+ case 4:
+ // We gave two frames to the frame provider, so we should get two
+ // refs back for each resource.
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
+ {
+ unsigned expected[] = {555, 555, 999, 999};
+ EXPECT_RESOURCES(expected, resources);
+ EXPECT_TRUE(TestAndResetAvailable());
+ }
+ EndTest();
+ break;
+ }
+ }
+
+ virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
+ bool result) OVERRIDE {
+ ReturnUnusedResourcesFromParent(host_impl);
+ }
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(
+ LayerTreeHostDelegatedTestTwoImplLayersTwoFrames);
+
+class LayerTreeHostDelegatedTestTwoLayers
+ : public LayerTreeHostDelegatedTestCaseSingleDelegatedLayer {
+ public:
+ virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
+
+ virtual void DidCommitAndDrawFrame() OVERRIDE {
+ scoped_ptr<DelegatedFrameData> frame;
+ ReturnedResourceArray resources;
+
+ int next_source_frame_number = layer_tree_host()->source_frame_number();
+ switch (next_source_frame_number) {
+ case 1:
+ frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1));
+ AddTextureQuad(frame.get(), 999);
+ AddTransferableResource(frame.get(), 999);
+ AddTextureQuad(frame.get(), 555);
+ AddTransferableResource(frame.get(), 555);
+
+ // Create a DelegatedRendererLayer using the frame.
+ SetFrameData(frame.Pass());
+ break;
+ case 2:
+ // Create a second DelegatedRendererLayer using the same frame provider.
+ delegated_thief_ = CreateDelegatedLayer(frame_provider_.get());
+ root_->AddChild(delegated_thief_);
+
+ // And drop our ref on the frame provider so only the layers keep it
+ // alive.
+ frame_provider_ = NULL;
+ break;
+ case 3:
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
+ EXPECT_EQ(0u, resources.size());
+ EXPECT_FALSE(TestAndResetAvailable());
+
+ // Remove one delegated layer from the tree. No resources should be
+ // returned yet.
+ delegated_->RemoveFromParent();
+ break;
+ case 4:
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
+ EXPECT_EQ(0u, resources.size());
+ EXPECT_FALSE(TestAndResetAvailable());
+
+ // Put the first layer back, and remove the other layer and destroy it.
+ // No resources should be returned yet.
+ root_->AddChild(delegated_);
+ delegated_thief_->RemoveFromParent();
+ delegated_thief_ = NULL;
+ break;
+ case 5:
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
+ EXPECT_EQ(0u, resources.size());
+ EXPECT_FALSE(TestAndResetAvailable());
+
+ // Remove the first layer from the tree again. The resources are still
+ // held by the main thread layer.
+ delegated_->RemoveFromParent();
+ break;
+ case 6:
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
+ EXPECT_EQ(0u, resources.size());
+ EXPECT_FALSE(TestAndResetAvailable());
+
+ // Destroy the layer and the resources should be returned immediately.
+ delegated_ = NULL;
+
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
+ {
+ unsigned expected[] = {555, 999};
+ EXPECT_RESOURCES(expected, resources);
+ EXPECT_TRUE(TestAndResetAvailable());
+ }
+ EndTest();
+ break;
+ }
+ }
+
+ virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
+ bool result) OVERRIDE {
+ ReturnUnusedResourcesFromParent(host_impl);
+ }
+
+ scoped_refptr<DelegatedRendererLayer> delegated_thief_;
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDelegatedTestTwoLayers);
+
+class LayerTreeHostDelegatedTestRemoveAndAddToTree
+ : public LayerTreeHostDelegatedTestCaseSingleDelegatedLayer {
+ public:
+ virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
+
+ virtual void DidCommitAndDrawFrame() OVERRIDE {
+ scoped_ptr<DelegatedFrameData> frame;
+ ReturnedResourceArray resources;
+
+ int next_source_frame_number = layer_tree_host()->source_frame_number();
+ switch (next_source_frame_number) {
+ case 1:
+ frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1));
+ AddTextureQuad(frame.get(), 999);
+ AddTransferableResource(frame.get(), 999);
+ AddTextureQuad(frame.get(), 555);
+ AddTransferableResource(frame.get(), 555);
+
+ // Create a DelegatedRendererLayer using the frame.
+ SetFrameData(frame.Pass());
+ break;
+ case 2:
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
+ EXPECT_EQ(0u, resources.size());
+ EXPECT_FALSE(TestAndResetAvailable());
+
+ // Remove the layer from the tree. The resources should not be returned
+ // since they are still on the main thread layer.
+ delegated_->RemoveFromParent();
+ break;
+ case 3:
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
+ EXPECT_EQ(0u, resources.size());
+ EXPECT_FALSE(TestAndResetAvailable());
+
+ // Add the layer back to the tree.
+ layer_tree_host()->root_layer()->AddChild(delegated_);
+ break;
+ case 4:
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
+ EXPECT_EQ(0u, resources.size());
+ EXPECT_FALSE(TestAndResetAvailable());
+
+ // Set a new frame. Resources should be returned.
+ frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1));
+ AddTextureQuad(frame.get(), 888);
+ AddTransferableResource(frame.get(), 888);
+ AddTextureQuad(frame.get(), 777);
+ AddTransferableResource(frame.get(), 777);
+ SetFrameData(frame.Pass());
+ break;
+ case 5:
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
+ {
+ unsigned expected[] = {555, 999};
+ EXPECT_RESOURCES(expected, resources);
+ EXPECT_TRUE(TestAndResetAvailable());
+ }
+
+ // Destroy the layer.
+ delegated_->RemoveFromParent();
+ delegated_ = NULL;
+ break;
+ case 6:
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
+ EXPECT_EQ(0u, resources.size());
+ EXPECT_FALSE(TestAndResetAvailable());
+
+ // Destroy the frame provider. Resources should be returned.
+ frame_provider_ = NULL;
+
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
+ {
+ unsigned expected[] = {777, 888};
+ EXPECT_RESOURCES(expected, resources);
+ EXPECT_TRUE(TestAndResetAvailable());
+ }
+ EndTest();
+ break;
+ }
+ }
+
+ virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
+ bool result) OVERRIDE {
+ ReturnUnusedResourcesFromParent(host_impl);
+ }
+
+ scoped_refptr<DelegatedRendererLayer> delegated_thief_;
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDelegatedTestRemoveAndAddToTree);
+
+class LayerTreeHostDelegatedTestRemoveAndChangeResources
+ : public LayerTreeHostDelegatedTestCaseSingleDelegatedLayer {
+ public:
+ virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
+
+ virtual void DidCommitAndDrawFrame() OVERRIDE {
+ scoped_ptr<DelegatedFrameData> frame;
+ ReturnedResourceArray resources;
+
+ int next_source_frame_number = layer_tree_host()->source_frame_number();
+ switch (next_source_frame_number) {
+ case 1:
+ frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1));
+ AddTextureQuad(frame.get(), 999);
+ AddTransferableResource(frame.get(), 999);
+ AddTextureQuad(frame.get(), 555);
+ AddTransferableResource(frame.get(), 555);
+
+ // Create a DelegatedRendererLayer using the frame.
+ SetFrameData(frame.Pass());
+ break;
+ case 2:
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
+ EXPECT_EQ(0u, resources.size());
+ EXPECT_FALSE(TestAndResetAvailable());
+
+ // Remove the layer from the tree. The resources should not be returned
+ // since they are still on the main thread layer.
+ delegated_->RemoveFromParent();
+ break;
+ case 3:
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
+ EXPECT_EQ(0u, resources.size());
+ EXPECT_FALSE(TestAndResetAvailable());
+
+ // Set a new frame. Resources should be returned immediately.
+ frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1));
+ AddTextureQuad(frame.get(), 888);
+ AddTransferableResource(frame.get(), 888);
+ AddTextureQuad(frame.get(), 777);
+ AddTransferableResource(frame.get(), 777);
+ SetFrameData(frame.Pass());
+
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
+ {
+ unsigned expected[] = {555, 999};
+ EXPECT_RESOURCES(expected, resources);
+ EXPECT_TRUE(TestAndResetAvailable());
+ resources.clear();
+ }
+
+ // Destroy the frame provider.
+ frame_provider_ = NULL;
+
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
+ EXPECT_EQ(0u, resources.size());
+ EXPECT_FALSE(TestAndResetAvailable());
+
+ // Destroy the layer. Resources should be returned.
+ delegated_ = NULL;
+
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&resources);
+ {
+ unsigned expected[] = {777, 888};
+ EXPECT_RESOURCES(expected, resources);
+ EXPECT_TRUE(TestAndResetAvailable());
+ }
+ EndTest();
+ break;
+ }
+ }
+
+ virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
+ bool result) OVERRIDE {
+ ReturnUnusedResourcesFromParent(host_impl);
+ }
+
+ scoped_refptr<DelegatedRendererLayer> delegated_thief_;
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(
+ LayerTreeHostDelegatedTestRemoveAndChangeResources);
+
} // namespace
} // namespace cc
diff --git a/chromium/cc/trees/layer_tree_host_unittest_occlusion.cc b/chromium/cc/trees/layer_tree_host_unittest_occlusion.cc
index 155b8428dd8..621d23d360f 100644
--- a/chromium/cc/trees/layer_tree_host_unittest_occlusion.cc
+++ b/chromium/cc/trees/layer_tree_host_unittest_occlusion.cc
@@ -5,6 +5,8 @@
#include "cc/trees/layer_tree_host.h"
#include "cc/layers/layer.h"
+#include "cc/output/copy_output_request.h"
+#include "cc/output/copy_output_result.h"
#include "cc/test/layer_tree_test.h"
#include "cc/test/occlusion_tracker_test_common.h"
@@ -99,6 +101,10 @@ class LayerTreeHostOcclusionTest : public LayerTreeTest {
}
protected:
+ virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
+ settings->minimum_occlusion_tracking_size = gfx::Size();
+ }
+
scoped_refptr<TestLayer> root_;
scoped_refptr<TestLayer> child_;
scoped_refptr<TestLayer> child2_;
@@ -340,6 +346,74 @@ class LayerTreeHostOcclusionTestOcclusionOpacityBelowOcclusion
SINGLE_AND_MULTI_THREAD_TEST_F(
LayerTreeHostOcclusionTestOcclusionOpacityBelowOcclusion);
+class LayerTreeHostOcclusionTestOcclusionBlending
+ : public LayerTreeHostOcclusionTest {
+ public:
+ virtual void SetupTree() OVERRIDE {
+ // If the child layer has a blend mode, then it shouldn't
+ // contribute to occlusion on stuff below it
+ SetLayerPropertiesForTesting(
+ root_.get(), NULL, identity_matrix_,
+ gfx::PointF(0.f, 0.f), gfx::Size(200, 200), true);
+ SetLayerPropertiesForTesting(
+ child2_.get(), root_.get(), identity_matrix_,
+ gfx::PointF(20.f, 10.f), gfx::Size(10, 500), true);
+ SetLayerPropertiesForTesting(
+ child_.get(), root_.get(), identity_matrix_,
+ gfx::PointF(10.f, 10.f), gfx::Size(500, 500), true);
+ SetLayerPropertiesForTesting(
+ grand_child_.get(), child_.get(), identity_matrix_,
+ gfx::PointF(-10.f, -10.f), gfx::Size(20, 500), true);
+
+ child_->SetMasksToBounds(true);
+ child_->SetBlendMode(SkXfermode::kMultiply_Mode);
+ child_->SetForceRenderSurface(true);
+
+ child_->set_expected_occlusion(gfx::Rect(0, 0, 10, 190));
+ root_->set_expected_occlusion(gfx::Rect(20, 10, 10, 190));
+
+ layer_tree_host()->SetRootLayer(root_);
+ LayerTreeTest::SetupTree();
+ }
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostOcclusionTestOcclusionBlending);
+
+class LayerTreeHostOcclusionTestOcclusionBlendingBelowOcclusion
+ : public LayerTreeHostOcclusionTest {
+ public:
+ virtual void SetupTree() OVERRIDE {
+ // If the child layer with a blend mode is below child2, then
+ // child2 should contribute to occlusion on everything, and child shouldn't
+ // contribute to the root_.
+ SetLayerPropertiesForTesting(
+ root_.get(), NULL, identity_matrix_,
+ gfx::PointF(0.f, 0.f), gfx::Size(200, 200), true);
+ SetLayerPropertiesForTesting(
+ child_.get(), root_.get(), identity_matrix_,
+ gfx::PointF(10.f, 10.f), gfx::Size(500, 500), true);
+ SetLayerPropertiesForTesting(
+ grand_child_.get(), child_.get(), identity_matrix_,
+ gfx::PointF(-10.f, -10.f), gfx::Size(20, 500), true);
+ SetLayerPropertiesForTesting(
+ child2_.get(), root_.get(), identity_matrix_,
+ gfx::PointF(20.f, 10.f), gfx::Size(10, 500), true);
+
+ child_->SetMasksToBounds(true);
+ child_->SetBlendMode(SkXfermode::kMultiply_Mode);
+
+ grand_child_->set_expected_occlusion(gfx::Rect(10, 0, 10, 190));
+ child_->set_expected_occlusion(gfx::Rect(0, 0, 20, 190));
+ root_->set_expected_occlusion(gfx::Rect(20, 10, 10, 190));
+
+ layer_tree_host()->SetRootLayer(root_);
+ LayerTreeTest::SetupTree();
+ }
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(
+ LayerTreeHostOcclusionTestOcclusionBlendingBelowOcclusion);
+
class LayerTreeHostOcclusionTestOcclusionOpacityFilter
: public LayerTreeHostOcclusionTest {
public:
@@ -426,6 +500,78 @@ class LayerTreeHostOcclusionTestOcclusionBlurFilter
SINGLE_AND_MULTI_THREAD_TEST_F(
LayerTreeHostOcclusionTestOcclusionBlurFilter);
+class LayerTreeHostOcclusionTestOcclusionCopyRequest
+ : public LayerTreeHostOcclusionTest {
+ public:
+ static void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {}
+
+ virtual void SetupTree() OVERRIDE {
+ // If the child layer has copy request, and is below child2,
+ // then child should not inherit occlusion from outside its subtree.
+ // The child layer will still receive occlusion from inside, and
+ // the root layer will recive occlusion from child.
+ SetLayerPropertiesForTesting(
+ root_.get(), NULL, identity_matrix_,
+ gfx::PointF(), gfx::Size(100, 100), true);
+ SetLayerPropertiesForTesting(
+ child_.get(), root_.get(), identity_matrix_,
+ gfx::PointF(), gfx::Size(75, 75), true);
+ SetLayerPropertiesForTesting(
+ grand_child_.get(), child_.get(), identity_matrix_,
+ gfx::PointF(), gfx::Size(75, 50), true);
+ SetLayerPropertiesForTesting(
+ child2_.get(), root_.get(), identity_matrix_,
+ gfx::PointF(0.f, 25.f), gfx::Size(75, 75), true);
+
+ child_->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
+ base::Bind(&CopyOutputCallback)));
+ EXPECT_TRUE(child_->HasCopyRequest());
+
+ child_->set_expected_occlusion(gfx::Rect(0, 0, 75, 50));
+ root_->set_expected_occlusion(gfx::Rect(0, 0, 75, 100));
+
+ layer_tree_host()->SetRootLayer(root_);
+ LayerTreeTest::SetupTree();
+ }
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostOcclusionTestOcclusionCopyRequest);
+
+class LayerTreeHostOcclusionTestOcclusionReplica
+ : public LayerTreeHostOcclusionTest {
+ public:
+ virtual void SetupTree() OVERRIDE {
+ // If the child layer has copy request, and is below child2,
+ // then child should not inherit occlusion from outside its subtree.
+ // The child layer will still receive occlusion from inside, and
+ // the root layer will recive occlusion from child.
+ SetLayerPropertiesForTesting(
+ root_.get(), NULL, identity_matrix_,
+ gfx::PointF(), gfx::Size(100, 100), true);
+ SetLayerPropertiesForTesting(
+ child_.get(), root_.get(), identity_matrix_,
+ gfx::PointF(), gfx::Size(75, 75), true);
+ SetLayerPropertiesForTesting(
+ grand_child_.get(), child_.get(), identity_matrix_,
+ gfx::PointF(), gfx::Size(75, 50), true);
+ SetLayerPropertiesForTesting(
+ child2_.get(), root_.get(), identity_matrix_,
+ gfx::PointF(0.f, 25.f), gfx::Size(75, 75), true);
+
+ scoped_refptr<Layer> replica_layer(Layer::Create());
+ child_->SetReplicaLayer(replica_layer.get());
+ EXPECT_TRUE(child_->has_replica());
+
+ child_->set_expected_occlusion(gfx::Rect(0, 0, 75, 50));
+ root_->set_expected_occlusion(gfx::Rect(0, 0, 75, 100));
+
+ layer_tree_host()->SetRootLayer(root_);
+ LayerTreeTest::SetupTree();
+ }
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostOcclusionTestOcclusionReplica);
+
class LayerTreeHostOcclusionTestManySurfaces
: public LayerTreeHostOcclusionTest {
public:
diff --git a/chromium/cc/trees/layer_tree_host_unittest_scroll.cc b/chromium/cc/trees/layer_tree_host_unittest_scroll.cc
index ab87be1b5c5..38711545636 100644
--- a/chromium/cc/trees/layer_tree_host_unittest_scroll.cc
+++ b/chromium/cc/trees/layer_tree_host_unittest_scroll.cc
@@ -172,8 +172,8 @@ class LayerTreeHostScrollTestScrollAbortedCommit
impl_scroll_(-3, 2),
second_main_scroll_(14, -3),
impl_scale_(2.f),
- num_will_begin_frames_(0),
- num_did_begin_frames_(0),
+ num_will_begin_main_frames_(0),
+ num_did_begin_main_frames_(0),
num_will_commits_(0),
num_did_commits_(0),
num_impl_commits_(0),
@@ -194,10 +194,10 @@ class LayerTreeHostScrollTestScrollAbortedCommit
layer_tree_host()->SetPageScaleFactorAndLimits(1.f, 0.01f, 100.f);
}
- virtual void WillBeginFrame() OVERRIDE {
- num_will_begin_frames_++;
+ virtual void WillBeginMainFrame() OVERRIDE {
+ num_will_begin_main_frames_++;
Layer* root_scroll_layer = layer_tree_host()->root_layer()->children()[0];
- switch (num_will_begin_frames_) {
+ 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_);
@@ -239,7 +239,7 @@ class LayerTreeHostScrollTestScrollAbortedCommit
}
}
- virtual void DidBeginFrame() OVERRIDE { num_did_begin_frames_++; }
+ virtual void DidBeginMainFrame() OVERRIDE { num_did_begin_main_frames_++; }
virtual void WillCommit() OVERRIDE { num_will_commits_++; }
@@ -317,8 +317,8 @@ class LayerTreeHostScrollTestScrollAbortedCommit
virtual void AfterTest() OVERRIDE {
EXPECT_EQ(3, num_impl_scrolls_);
// Verify that the embedder sees aborted commits as real commits.
- EXPECT_EQ(4, num_will_begin_frames_);
- EXPECT_EQ(4, num_did_begin_frames_);
+ EXPECT_EQ(4, num_will_begin_main_frames_);
+ EXPECT_EQ(4, num_did_begin_main_frames_);
EXPECT_EQ(4, num_will_commits_);
EXPECT_EQ(4, num_did_commits_);
// ...but the compositor thread only sees two real ones.
@@ -330,8 +330,8 @@ class LayerTreeHostScrollTestScrollAbortedCommit
gfx::Vector2d impl_scroll_;
gfx::Vector2d second_main_scroll_;
float impl_scale_;
- int num_will_begin_frames_;
- int num_did_begin_frames_;
+ int num_will_begin_main_frames_;
+ int num_did_begin_main_frames_;
int num_will_commits_;
int num_did_commits_;
int num_impl_commits_;
@@ -1012,8 +1012,8 @@ TEST(LayerTreeHostFlingTest, DidStopFlingingThread) {
FakeLayerTreeHostClient client(FakeLayerTreeHostClient::DIRECT_3D);
ASSERT_TRUE(impl_thread.message_loop_proxy().get());
- scoped_ptr<LayerTreeHost> layer_tree_host = LayerTreeHost::Create(
- &client, settings, impl_thread.message_loop_proxy());
+ scoped_ptr<LayerTreeHost> layer_tree_host = LayerTreeHost::CreateThreaded(
+ &client, NULL, settings, impl_thread.message_loop_proxy());
impl_thread.message_loop_proxy()
->PostTask(FROM_HERE,
diff --git a/chromium/cc/trees/layer_tree_impl.cc b/chromium/cc/trees/layer_tree_impl.cc
index 280bdad8ee1..9f181cda458 100644
--- a/chromium/cc/trees/layer_tree_impl.cc
+++ b/chromium/cc/trees/layer_tree_impl.cc
@@ -7,11 +7,14 @@
#include "base/debug/trace_event.h"
#include "cc/animation/keyframed_animation_curve.h"
#include "cc/animation/scrollbar_animation_controller.h"
+#include "cc/base/math_util.h"
+#include "cc/base/util.h"
#include "cc/debug/traced_value.h"
#include "cc/layers/heads_up_display_layer_impl.h"
#include "cc/layers/layer.h"
#include "cc/layers/render_surface_impl.h"
#include "cc/layers/scrollbar_layer_impl_base.h"
+#include "cc/resources/ui_resource_request.h"
#include "cc/trees/layer_tree_host_common.h"
#include "cc/trees/layer_tree_host_impl.h"
#include "ui/gfx/size_conversions.h"
@@ -40,7 +43,8 @@ LayerTreeImpl::LayerTreeImpl(LayerTreeHostImpl* layer_tree_host_impl)
contents_textures_purged_(false),
viewport_size_invalid_(false),
needs_update_draw_properties_(true),
- needs_full_tree_sync_(true) {
+ needs_full_tree_sync_(true),
+ next_activation_forces_redraw_(false) {
}
LayerTreeImpl::~LayerTreeImpl() {
@@ -111,8 +115,13 @@ void LayerTreeImpl::PushPropertiesTo(LayerTreeImpl* target_tree) {
// The request queue should have been processed and does not require a push.
DCHECK_EQ(ui_resource_request_queue_.size(), 0u);
- target_tree->SetLatencyInfo(latency_info_);
- latency_info_.Clear();
+ if (next_activation_forces_redraw_) {
+ layer_tree_host_impl_->SetFullRootLayerDamage();
+ next_activation_forces_redraw_ = false;
+ }
+
+ target_tree->PassSwapPromises(&swap_promise_list_);
+
target_tree->SetPageScaleFactorAndLimits(
page_scale_factor(), min_page_scale_factor(), max_page_scale_factor());
target_tree->SetPageScaleDelta(
@@ -189,6 +198,11 @@ void LayerTreeImpl::SetPageScaleFactorAndLimits(float page_scale_factor,
min_page_scale_factor_ = min_page_scale_factor;
max_page_scale_factor_ = max_page_scale_factor;
page_scale_factor_ = page_scale_factor;
+
+ if (root_layer_scroll_offset_delegate_) {
+ root_layer_scroll_offset_delegate_->SetTotalPageScaleFactor(
+ total_page_scale_factor());
+ }
}
void LayerTreeImpl::SetPageScaleDelta(float delta) {
@@ -215,6 +229,11 @@ void LayerTreeImpl::SetPageScaleDelta(float delta) {
UpdateMaxScrollOffset();
set_needs_update_draw_properties();
+
+ if (root_layer_scroll_offset_delegate_) {
+ root_layer_scroll_offset_delegate_->SetTotalPageScaleFactor(
+ total_page_scale_factor());
+ }
}
gfx::SizeF LayerTreeImpl::ScrollableViewportSize() const {
@@ -222,6 +241,15 @@ gfx::SizeF LayerTreeImpl::ScrollableViewportSize() const {
1.0f / total_page_scale_factor());
}
+gfx::Rect LayerTreeImpl::RootScrollLayerDeviceViewportBounds() const {
+ if (!root_scroll_layer_ || root_scroll_layer_->children().empty())
+ return gfx::Rect();
+ LayerImpl* layer = root_scroll_layer_->children()[0];
+ return MathUtil::MapClippedRect(
+ layer->screen_space_transform(),
+ gfx::Rect(layer->content_bounds()));
+}
+
void LayerTreeImpl::UpdateMaxScrollOffset() {
LayerImpl* root_scroll = RootScrollLayer();
if (!root_scroll || !root_scroll->children().size())
@@ -255,17 +283,17 @@ void LayerTreeImpl::ApplySentScrollAndScaleDeltasFromAbortedCommit() {
root_layer(), base::Bind(&ApplySentScrollDeltasFromAbortedCommitTo));
}
-static void ApplyScrollDeltasSinceBeginFrameTo(LayerImpl* layer) {
- layer->ApplyScrollDeltasSinceBeginFrame();
+static void ApplyScrollDeltasSinceBeginMainFrameTo(LayerImpl* layer) {
+ layer->ApplyScrollDeltasSinceBeginMainFrame();
}
-void LayerTreeImpl::ApplyScrollDeltasSinceBeginFrame() {
+void LayerTreeImpl::ApplyScrollDeltasSinceBeginMainFrame() {
DCHECK(IsPendingTree());
if (!root_layer())
return;
LayerTreeHostCommon::CallFunctionForSubtree(
- root_layer(), base::Bind(&ApplyScrollDeltasSinceBeginFrameTo));
+ root_layer(), base::Bind(&ApplyScrollDeltasSinceBeginMainFrameTo));
}
void LayerTreeImpl::SetViewportLayersFromIds(
@@ -295,8 +323,6 @@ void LayerTreeImpl::ClearViewportLayers() {
// of login that works for both scrollbar layer types. This is already planned
// as part of the larger pinch-zoom re-factoring viewport.
void LayerTreeImpl::UpdateSolidColorScrollbars() {
- DCHECK(settings().solid_color_scrollbars);
-
LayerImpl* root_scroll = RootScrollLayer();
DCHECK(root_scroll);
DCHECK(IsActiveTree());
@@ -327,9 +353,9 @@ void LayerTreeImpl::UpdateDrawProperties() {
if (IsActiveTree() && RootScrollLayer() && RootContainerLayer())
UpdateRootScrollLayerSizeDelta();
- if (settings().solid_color_scrollbars &&
- IsActiveTree() &&
- RootScrollLayer()) {
+ if (IsActiveTree() &&
+ RootContainerLayer()
+ && !RootContainerLayer()->masks_to_bounds()) {
UpdateSolidColorScrollbars();
}
@@ -352,6 +378,8 @@ void LayerTreeImpl::UpdateDrawProperties() {
source_frame_number_);
LayerImpl* page_scale_layer =
page_scale_layer_ ? page_scale_layer_ : RootContainerLayer();
+ bool can_render_to_separate_surface =
+ !output_surface()->ForcedDrawToSoftwareDevice();
LayerTreeHostCommon::CalcDrawPropsImplInputs inputs(
root_layer(),
DrawViewportSize(),
@@ -361,11 +389,43 @@ void LayerTreeImpl::UpdateDrawProperties() {
page_scale_layer,
MaxTextureSize(),
settings().can_use_lcd_text,
+ can_render_to_separate_surface,
settings().layer_transforms_should_scale_layer_contents,
&render_surface_layer_list_);
LayerTreeHostCommon::CalculateDrawProperties(&inputs);
}
+ {
+ TRACE_EVENT2("cc",
+ "LayerTreeImpl::UpdateTilePriorities",
+ "IsActive",
+ IsActiveTree(),
+ "SourceFrameNumber",
+ source_frame_number_);
+ // LayerIterator is used here instead of CallFunctionForSubtree to only
+ // UpdateTilePriorities on layers that will be visible (and thus have valid
+ // draw properties) and not because any ordering is required.
+ typedef LayerIterator<LayerImpl,
+ LayerImplList,
+ RenderSurfaceImpl,
+ LayerIteratorActions::FrontToBack> LayerIteratorType;
+ LayerIteratorType end = LayerIteratorType::End(&render_surface_layer_list_);
+ for (LayerIteratorType it =
+ LayerIteratorType::Begin(&render_surface_layer_list_);
+ it != end;
+ ++it) {
+ if (!it.represents_itself())
+ continue;
+ LayerImpl* layer = *it;
+
+ layer->UpdateTilePriorities();
+ if (layer->mask_layer())
+ layer->mask_layer()->UpdateTilePriorities();
+ if (layer->replica_layer() && layer->replica_layer()->mask_layer())
+ layer->replica_layer()->mask_layer()->UpdateTilePriorities();
+ }
+ }
+
DCHECK(!needs_update_draw_properties_) <<
"CalcDrawProperties should not set_needs_update_draw_properties()";
}
@@ -401,8 +461,6 @@ void LayerTreeImpl::PushPersistedState(LayerTreeImpl* pending_tree) {
pending_tree->SetCurrentlyScrollingLayer(
LayerTreeHostCommon::FindLayerInSubtree(pending_tree->root_layer(),
currently_scrolling_layer_ ? currently_scrolling_layer_->id() : 0));
- pending_tree->SetLatencyInfo(latency_info_);
- latency_info_.Clear();
}
static void DidBecomeActiveRecursive(LayerImpl* layer) {
@@ -553,6 +611,10 @@ void LayerTreeImpl::StartScrollbarAnimation() {
layer_tree_host_impl_->StartScrollbarAnimation();
}
+void LayerTreeImpl::DidAnimateScrollOffset() {
+ layer_tree_host_impl_->DidAnimateScrollOffset();
+}
+
void LayerTreeImpl::SetNeedsRedraw() {
layer_tree_host_impl_->SetNeedsRedraw();
}
@@ -584,7 +646,7 @@ scoped_ptr<base::Value> LayerTreeImpl::AsValue() const {
typedef LayerIterator<LayerImpl,
LayerImplList,
RenderSurfaceImpl,
- LayerIteratorActions::BackToFront> LayerIteratorType;
+ LayerIteratorActions::FrontToBack> LayerIteratorType;
LayerIteratorType end = LayerIteratorType::End(&render_surface_layer_list_);
for (LayerIteratorType it = LayerIteratorType::Begin(
&render_surface_layer_list_); it != end; ++it) {
@@ -600,11 +662,21 @@ scoped_ptr<base::Value> LayerTreeImpl::AsValue() const {
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_scroll_layer_) {
root_scroll_layer_->SetScrollOffsetDelegate(
root_layer_scroll_offset_delegate_);
}
+
+ if (root_layer_scroll_offset_delegate_) {
+ root_layer_scroll_offset_delegate_->SetScrollableSize(ScrollableSize());
+ root_layer_scroll_offset_delegate_->SetTotalPageScaleFactor(
+ total_page_scale_factor());
+ }
}
void LayerTreeImpl::UpdateRootScrollLayerSizeDelta() {
@@ -626,16 +698,30 @@ void LayerTreeImpl::UpdateRootScrollLayerSizeDelta() {
scrollable_viewport_size - original_viewport_size);
}
-void LayerTreeImpl::SetLatencyInfo(const ui::LatencyInfo& latency_info) {
- latency_info_.MergeWith(latency_info);
+void LayerTreeImpl::QueueSwapPromise(scoped_ptr<SwapPromise> swap_promise) {
+ DCHECK(swap_promise);
+ if (swap_promise_list_.size() > kMaxQueuedSwapPromiseNumber)
+ BreakSwapPromises(SwapPromise::SWAP_PROMISE_LIST_OVERFLOW);
+ swap_promise_list_.push_back(swap_promise.Pass());
}
-const ui::LatencyInfo& LayerTreeImpl::GetLatencyInfo() {
- return latency_info_;
+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();
}
-void LayerTreeImpl::ClearLatencyInfo() {
- latency_info_.Clear();
+void LayerTreeImpl::FinishSwapPromises(CompositorFrameMetadata* metadata) {
+ for (size_t i = 0; i < swap_promise_list_.size(); i++)
+ swap_promise_list_[i]->DidSwap(metadata);
+ swap_promise_list_.clear();
+}
+
+void LayerTreeImpl::BreakSwapPromises(SwapPromise::DidNotSwapReason reason) {
+ for (size_t i = 0; i < swap_promise_list_.size(); i++)
+ swap_promise_list_[i]->DidNotSwap(reason);
+ swap_promise_list_.clear();
}
void LayerTreeImpl::DidModifyTilePriorities() {
@@ -652,6 +738,10 @@ ResourceProvider::ResourceId LayerTreeImpl::ResourceIdForUIResource(
return layer_tree_host_impl_->ResourceIdForUIResource(uid);
}
+bool LayerTreeImpl::IsUIResourceOpaque(UIResourceId uid) const {
+ return layer_tree_host_impl_->IsUIResourceOpaque(uid);
+}
+
void LayerTreeImpl::ProcessUIResourceRequestQueue() {
while (ui_resource_request_queue_.size() > 0) {
UIResourceRequest req = ui_resource_request_queue_.front();
@@ -700,7 +790,7 @@ void LayerTreeImpl::RemoveLayerWithCopyOutputRequest(LayerImpl* layer) {
layers_with_copy_output_request_.erase(it);
}
-const std::vector<LayerImpl*> LayerTreeImpl::LayersWithCopyOutputRequest()
+const std::vector<LayerImpl*>& LayerTreeImpl::LayersWithCopyOutputRequest()
const {
// Only the active tree needs to know about layers with copy requests, as
// they are aborted if not serviced during draw.
diff --git a/chromium/cc/trees/layer_tree_impl.h b/chromium/cc/trees/layer_tree_impl.h
index 2ae33df2ba2..85a71f5cd72 100644
--- a/chromium/cc/trees/layer_tree_impl.h
+++ b/chromium/cc/trees/layer_tree_impl.h
@@ -11,10 +11,11 @@
#include "base/containers/hash_tables.h"
#include "base/values.h"
+#include "cc/base/scoped_ptr_vector.h"
+#include "cc/base/swap_promise.h"
#include "cc/layers/layer_impl.h"
#include "cc/trees/layer_tree_host.h"
#include "cc/resources/ui_resource_client.h"
-#include "ui/events/latency_info.h"
#if defined(COMPILER_GCC)
namespace BASE_HASH_NAMESPACE {
@@ -81,6 +82,7 @@ class CC_EXPORT LayerTreeImpl {
void SetNeedsCommit();
gfx::Size DrawViewportSize() const;
void StartScrollbarAnimation();
+ void DidAnimateScrollOffset();
// Tree specific methods exposed to layer-impl tree.
// ---------------------------------------------------------------------------
@@ -124,7 +126,7 @@ class CC_EXPORT LayerTreeImpl {
int outer_viewport_scroll_layer_id);
void ClearViewportLayers();
void ApplySentScrollAndScaleDeltasFromAbortedCommit();
- void ApplyScrollDeltasSinceBeginFrame();
+ void ApplyScrollDeltasSinceBeginMainFrame();
SkColor background_color() const { return background_color_; }
void set_background_color(SkColor color) { background_color_ = color; }
@@ -165,6 +167,8 @@ class CC_EXPORT LayerTreeImpl {
void set_needs_full_tree_sync(bool needs) { needs_full_tree_sync_ = needs; }
bool needs_full_tree_sync() const { return needs_full_tree_sync_; }
+ void ForceRedrawNextActivation() { next_activation_forces_redraw_ = true; }
+
void set_ui_resource_request_queue(const UIResourceRequestQueue& queue);
const LayerImplList& RenderSurfaceLayerList() const;
@@ -174,6 +178,8 @@ class CC_EXPORT LayerTreeImpl {
gfx::Size ScrollableSize() const;
gfx::SizeF ScrollableViewportSize() const;
+ gfx::Rect RootScrollLayerDeviceViewportBounds() const;
+
LayerImpl* LayerById(int id);
// These should be called by LayerImpl's ctor/dtor.
@@ -202,18 +208,25 @@ class CC_EXPORT LayerTreeImpl {
void SetRootLayerScrollOffsetDelegate(
LayerScrollOffsetDelegate* root_layer_scroll_offset_delegate);
- void SetLatencyInfo(const ui::LatencyInfo& latency_info);
- const ui::LatencyInfo& GetLatencyInfo();
- void ClearLatencyInfo();
+ // Call this function when you expect there to be a swap buffer.
+ // See swap_promise.h for how to use SwapPromise.
+ void QueueSwapPromise(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);
+ void BreakSwapPromises(SwapPromise::DidNotSwapReason reason);
void DidModifyTilePriorities();
ResourceProvider::ResourceId ResourceIdForUIResource(UIResourceId uid) const;
void ProcessUIResourceRequestQueue();
+ bool IsUIResourceOpaque(UIResourceId uid) const;
+
void AddLayerWithCopyOutputRequest(LayerImpl* layer);
void RemoveLayerWithCopyOutputRequest(LayerImpl* layer);
- const std::vector<LayerImpl*> LayersWithCopyOutputRequest() const;
+ const std::vector<LayerImpl*>& LayersWithCopyOutputRequest() const;
protected:
explicit LayerTreeImpl(LayerTreeHostImpl* layer_tree_host_impl);
@@ -250,8 +263,8 @@ class CC_EXPORT LayerTreeImpl {
// Persisted state for non-impl-side-painting.
int scrolling_layer_id_from_previous_tree_;
- // List of visible layers for the most recently prepared frame. Used for
- // rendering and input event hit testing.
+ // List of visible or hit-testable layers for the most recently prepared
+ // frame. Used for rendering and input event hit testing.
LayerImplList render_surface_layer_list_;
bool contents_textures_purged_;
@@ -262,7 +275,9 @@ class CC_EXPORT LayerTreeImpl {
// structural differences relative to the active tree.
bool needs_full_tree_sync_;
- ui::LatencyInfo latency_info_;
+ bool next_activation_forces_redraw_;
+
+ ScopedPtrVector<SwapPromise> swap_promise_list_;
UIResourceRequestQueue ui_resource_request_queue_;
diff --git a/chromium/cc/trees/layer_tree_settings.cc b/chromium/cc/trees/layer_tree_settings.cc
index 8e8e35d5faa..b39524cb61b 100644
--- a/chromium/cc/trees/layer_tree_settings.cc
+++ b/chromium/cc/trees/layer_tree_settings.cc
@@ -16,21 +16,20 @@ LayerTreeSettings::LayerTreeSettings()
: impl_side_painting(false),
allow_antialiasing(true),
throttle_frame_production(true),
- begin_frame_scheduling_enabled(false),
- deadline_scheduling_enabled(false),
+ begin_impl_frame_scheduling_enabled(false),
+ deadline_scheduling_enabled(true),
using_synchronous_renderer_compositor(false),
per_tile_painting_enabled(false),
partial_swap_enabled(false),
- cache_render_pass_contents(true),
accelerated_animation_enabled(true),
background_color_instead_of_checkerboard(false),
show_overdraw_in_tracing(false),
can_use_lcd_text(true),
should_clear_root_render_pass(true),
+ gpu_rasterization(false),
scrollbar_animator(NoAnimator),
scrollbar_linear_fade_delay_ms(300),
scrollbar_linear_fade_length_ms(300),
- solid_color_scrollbars(false),
solid_color_scrollbar_color(SK_ColorWHITE),
calculate_top_controls_position(false),
use_memory_management(true),
@@ -38,7 +37,7 @@ LayerTreeSettings::LayerTreeSettings()
maximum_number_of_failed_draws_before_draw_is_forced_(3),
layer_transforms_should_scale_layer_contents(false),
minimum_contents_scale(0.0625f),
- low_res_contents_scale_factor(0.125f),
+ low_res_contents_scale_factor(0.25f),
top_controls_height(0.f),
top_controls_show_threshold(0.5f),
top_controls_hide_threshold(0.5f),
@@ -54,14 +53,13 @@ LayerTreeSettings::LayerTreeSettings()
max_tiles_for_interest_area(128),
max_unused_resource_memory_percentage(100),
highp_threshold_min(0),
- force_direct_layer_drawing(false),
strict_layer_property_change_checking(false),
use_map_image(false),
ignore_root_layer_flings(false),
- use_rgba_4444_textures(false) {
- // TODO(danakj): Renable surface caching when we can do it more realiably.
- // crbug.com/170713
- cache_render_pass_contents = false;
+ use_rgba_4444_textures(false),
+ always_overscroll(false),
+ touch_hit_testing(true),
+ texture_id_allocation_chunk_size(64) {
}
LayerTreeSettings::~LayerTreeSettings() {}
diff --git a/chromium/cc/trees/layer_tree_settings.h b/chromium/cc/trees/layer_tree_settings.h
index aa8cdd9860f..6ba5da464a2 100644
--- a/chromium/cc/trees/layer_tree_settings.h
+++ b/chromium/cc/trees/layer_tree_settings.h
@@ -21,17 +21,17 @@ class CC_EXPORT LayerTreeSettings {
bool impl_side_painting;
bool allow_antialiasing;
bool throttle_frame_production;
- bool begin_frame_scheduling_enabled;
+ bool begin_impl_frame_scheduling_enabled;
bool deadline_scheduling_enabled;
bool using_synchronous_renderer_compositor;
bool per_tile_painting_enabled;
bool partial_swap_enabled;
- bool cache_render_pass_contents;
bool accelerated_animation_enabled;
bool background_color_instead_of_checkerboard;
bool show_overdraw_in_tracing;
bool can_use_lcd_text;
bool should_clear_root_render_pass;
+ bool gpu_rasterization;
enum ScrollbarAnimator {
NoAnimator,
@@ -41,7 +41,6 @@ class CC_EXPORT LayerTreeSettings {
ScrollbarAnimator scrollbar_animator;
int scrollbar_linear_fade_delay_ms;
int scrollbar_linear_fade_length_ms;
- bool solid_color_scrollbars;
SkColor solid_color_scrollbar_color;
bool calculate_top_controls_position;
bool use_memory_management;
@@ -64,11 +63,13 @@ class CC_EXPORT LayerTreeSettings {
size_t max_tiles_for_interest_area;
size_t max_unused_resource_memory_percentage;
int highp_threshold_min;
- bool force_direct_layer_drawing; // With Skia GPU backend.
bool strict_layer_property_change_checking;
bool use_map_image;
bool ignore_root_layer_flings;
bool use_rgba_4444_textures;
+ bool always_overscroll;
+ bool touch_hit_testing;
+ size_t texture_id_allocation_chunk_size;
LayerTreeDebugState initial_debug_state;
};
diff --git a/chromium/cc/trees/occlusion_tracker.cc b/chromium/cc/trees/occlusion_tracker.cc
index 9fc26da5667..1c6c8a04e4e 100644
--- a/chromium/cc/trees/occlusion_tracker.cc
+++ b/chromium/cc/trees/occlusion_tracker.cc
@@ -22,7 +22,6 @@ OcclusionTrackerBase<LayerType, RenderSurfaceType>::OcclusionTrackerBase(
gfx::Rect screen_space_clip_rect, bool record_metrics_for_frame)
: screen_space_clip_rect_(screen_space_clip_rect),
overdraw_metrics_(OverdrawMetrics::Create(record_metrics_for_frame)),
- prevent_occlusion_(false),
occluding_screen_space_rects_(NULL),
non_occluding_screen_space_rects_(NULL) {}
@@ -31,16 +30,13 @@ OcclusionTrackerBase<LayerType, RenderSurfaceType>::~OcclusionTrackerBase() {}
template <typename LayerType, typename RenderSurfaceType>
void OcclusionTrackerBase<LayerType, RenderSurfaceType>::EnterLayer(
- const LayerIteratorPosition<LayerType>& layer_iterator,
- bool prevent_occlusion) {
+ const LayerIteratorPosition<LayerType>& layer_iterator) {
LayerType* render_target = layer_iterator.target_render_surface_layer;
if (layer_iterator.represents_itself)
EnterRenderTarget(render_target);
else if (layer_iterator.represents_target_render_surface)
FinishedRenderTarget(render_target);
-
- prevent_occlusion_ = prevent_occlusion;
}
template <typename LayerType, typename RenderSurfaceType>
@@ -54,8 +50,6 @@ void OcclusionTrackerBase<LayerType, RenderSurfaceType>::LeaveLayer(
// but in a way that the surface's own occlusion won't occlude itself.
else if (layer_iterator.represents_contributing_render_surface)
LeaveToRenderTarget(render_target);
-
- prevent_occlusion_ = false;
}
template <typename RenderSurfaceType>
@@ -156,14 +150,14 @@ void OcclusionTrackerBase<LayerType, RenderSurfaceType>::EnterRenderTarget(
return;
const LayerType* old_target = NULL;
- const RenderSurfaceType* old_ancestor_that_moves_pixels = NULL;
+ const RenderSurfaceType* old_occlusion_immune_ancestor = NULL;
if (!stack_.empty()) {
old_target = stack_.back().target;
- old_ancestor_that_moves_pixels =
- old_target->render_surface()->nearest_ancestor_that_moves_pixels();
+ old_occlusion_immune_ancestor =
+ old_target->render_surface()->nearest_occlusion_immune_ancestor();
}
- const RenderSurfaceType* new_ancestor_that_moves_pixels =
- new_target->render_surface()->nearest_ancestor_that_moves_pixels();
+ const RenderSurfaceType* new_occlusion_immune_ancestor =
+ new_target->render_surface()->nearest_occlusion_immune_ancestor();
stack_.push_back(StackObject(new_target));
@@ -171,14 +165,11 @@ void OcclusionTrackerBase<LayerType, RenderSurfaceType>::EnterRenderTarget(
// never copy in the occlusion from inside the target, since we are looking
// at a new RenderSurface target.
- // If we are entering a subtree that is going to move pixels around, then the
- // occlusion we've computed so far won't apply to the pixels we're drawing
- // here in the same way. We discard the occlusion thus far to be safe, and
- // ensure we don't cull any pixels that are moved such that they become
- // visible.
- bool entering_subtree_that_moves_pixels =
- new_ancestor_that_moves_pixels &&
- new_ancestor_that_moves_pixels != old_ancestor_that_moves_pixels;
+ // If entering an unoccluded subtree, do not carry forward the outside
+ // occlusion calculated so far.
+ bool entering_unoccluded_subtree =
+ new_occlusion_immune_ancestor &&
+ new_occlusion_immune_ancestor != old_occlusion_immune_ancestor;
bool have_transform_from_screen_to_new_target = false;
gfx::Transform inverse_new_target_screen_space_transform(
@@ -194,7 +185,7 @@ void OcclusionTrackerBase<LayerType, RenderSurfaceType>::EnterRenderTarget(
bool copy_outside_occlusion_forward =
stack_.size() > 1 &&
- !entering_subtree_that_moves_pixels &&
+ !entering_unoccluded_subtree &&
have_transform_from_screen_to_new_target &&
!entering_root_target;
if (!copy_outside_occlusion_forward)
@@ -233,14 +224,11 @@ void OcclusionTrackerBase<LayerType, RenderSurfaceType>::FinishedRenderTarget(
// If the occlusion within the surface can not be applied to things outside of
// the surface's subtree, then clear the occlusion here so it won't be used.
- // TODO(senorblanco): Make this smarter for SkImageFilter case: once
- // SkImageFilters can report affectsOpacity(), call that.
- if (finished_target->mask_layer() ||
- !SurfaceOpacityKnown(surface) ||
+ if (finished_target->mask_layer() || !SurfaceOpacityKnown(surface) ||
surface->draw_opacity() < 1 ||
+ !finished_target->uses_default_blend_mode() ||
target_is_only_for_copy_request ||
- finished_target->filters().HasFilterThatAffectsOpacity() ||
- finished_target->filter()) {
+ finished_target->filters().HasFilterThatAffectsOpacity()) {
stack_.back().occlusion_from_outside_target.Clear();
stack_.back().occlusion_from_inside_target.Clear();
} else if (!SurfaceTransformsToTargetKnown(surface)) {
@@ -275,12 +263,6 @@ static void ReduceOcclusionBelowSurface(LayerType* contributing_layer,
// to expand outside the clip.
affected_area_in_target.Inset(
-outset_left, -outset_top, -outset_right, -outset_bottom);
-
- gfx::Rect FilterOutsetsInTarget(-outset_left,
- -outset_top,
- outset_left + outset_right,
- outset_top + outset_bottom);
-
Region affected_occlusion = IntersectRegions(*occlusion_from_inside_target,
affected_area_in_target);
Region::Iterator affected_occlusion_rects(affected_occlusion);
@@ -350,10 +332,10 @@ void OcclusionTrackerBase<LayerType, RenderSurfaceType>::LeaveToRenderTarget(
gfx::Rect unoccluded_replica_rect;
if (old_target->background_filters().HasFilterThatMovesPixels()) {
unoccluded_surface_rect = UnoccludedContributingSurfaceContentRect(
- old_target, false, old_surface->content_rect(), NULL);
+ old_target, false, old_surface->content_rect());
if (old_target->has_replica()) {
unoccluded_replica_rect = UnoccludedContributingSurfaceContentRect(
- old_target, true, old_surface->content_rect(), NULL);
+ old_target, true, old_surface->content_rect());
}
}
@@ -417,9 +399,15 @@ void OcclusionTrackerBase<LayerType, RenderSurfaceType>::
if (stack_.empty())
return;
+ if (!layer->DrawsContent())
+ return;
+
if (!LayerOpacityKnown(layer) || layer->draw_opacity() < 1)
return;
+ if (!layer->uses_default_blend_mode())
+ return;
+
if (LayerIsInUnsorted3dRenderingContext(layer))
return;
@@ -511,15 +499,7 @@ bool OcclusionTrackerBase<LayerType, RenderSurfaceType>::Occluded(
const LayerType* render_target,
gfx::Rect content_rect,
const gfx::Transform& draw_transform,
- bool impl_draw_transform_is_unknown,
- bool is_clipped,
- gfx::Rect clip_rect_in_target,
- bool* has_occlusion_from_outside_target_surface) const {
- if (has_occlusion_from_outside_target_surface)
- *has_occlusion_from_outside_target_surface = false;
- if (prevent_occlusion_)
- return false;
-
+ bool impl_draw_transform_is_unknown) const {
DCHECK(!stack_.empty());
if (stack_.empty())
return false;
@@ -536,6 +516,11 @@ bool OcclusionTrackerBase<LayerType, RenderSurfaceType>::Occluded(
DCHECK(render_target->render_surface());
DCHECK_EQ(render_target, stack_.back().target);
+ if (stack_.back().occlusion_from_inside_target.IsEmpty() &&
+ stack_.back().occlusion_from_outside_target.IsEmpty()) {
+ return false;
+ }
+
gfx::Transform inverse_draw_transform(gfx::Transform::kSkipInitialization);
if (!draw_transform.GetInverse(&inverse_draw_transform))
return false;
@@ -544,9 +529,6 @@ bool OcclusionTrackerBase<LayerType, RenderSurfaceType>::Occluded(
// partial pixels in the resulting Rect.
Region unoccluded_region_in_target_surface = gfx::ToEnclosingRect(
MathUtil::MapClippedRect(draw_transform, gfx::RectF(content_rect)));
- // Layers can't clip across surfaces, so count this as internal occlusion.
- if (is_clipped)
- unoccluded_region_in_target_surface.Intersect(clip_rect_in_target);
unoccluded_region_in_target_surface.Subtract(
stack_.back().occlusion_from_inside_target);
gfx::RectF unoccluded_rect_in_target_surface_without_outside_occlusion =
@@ -554,24 +536,9 @@ bool OcclusionTrackerBase<LayerType, RenderSurfaceType>::Occluded(
unoccluded_region_in_target_surface.Subtract(
stack_.back().occlusion_from_outside_target);
- // Treat other clipping as occlusion from outside the surface.
- // TODO(danakj): Clip to visibleContentRect?
- unoccluded_region_in_target_surface.Intersect(
- render_target->render_surface()->content_rect());
- unoccluded_region_in_target_surface.Intersect(
- ScreenSpaceClipRectInTargetSurface(render_target->render_surface(),
- screen_space_clip_rect_));
-
gfx::RectF unoccluded_rect_in_target_surface =
unoccluded_region_in_target_surface.bounds();
- if (has_occlusion_from_outside_target_surface) {
- // Check if the unoccluded rect shrank when applying outside occlusion.
- *has_occlusion_from_outside_target_surface = !gfx::SubtractRects(
- unoccluded_rect_in_target_surface_without_outside_occlusion,
- unoccluded_rect_in_target_surface).IsEmpty();
- }
-
return unoccluded_rect_in_target_surface.IsEmpty();
}
@@ -581,15 +548,7 @@ gfx::Rect OcclusionTrackerBase<LayerType, RenderSurfaceType>::
const LayerType* render_target,
gfx::Rect content_rect,
const gfx::Transform& draw_transform,
- bool impl_draw_transform_is_unknown,
- bool is_clipped,
- gfx::Rect clip_rect_in_target,
- bool* has_occlusion_from_outside_target_surface) const {
- if (has_occlusion_from_outside_target_surface)
- *has_occlusion_from_outside_target_surface = false;
- if (prevent_occlusion_)
- return content_rect;
-
+ bool impl_draw_transform_is_unknown) const {
DCHECK(!stack_.empty());
if (stack_.empty())
return content_rect;
@@ -606,6 +565,11 @@ gfx::Rect OcclusionTrackerBase<LayerType, RenderSurfaceType>::
DCHECK(render_target->render_surface());
DCHECK_EQ(render_target, stack_.back().target);
+ if (stack_.back().occlusion_from_inside_target.IsEmpty() &&
+ stack_.back().occlusion_from_outside_target.IsEmpty()) {
+ return content_rect;
+ }
+
gfx::Transform inverse_draw_transform(gfx::Transform::kSkipInitialization);
if (!draw_transform.GetInverse(&inverse_draw_transform))
return content_rect;
@@ -614,24 +578,11 @@ gfx::Rect OcclusionTrackerBase<LayerType, RenderSurfaceType>::
// partial pixels in the resulting Rect.
Region unoccluded_region_in_target_surface = gfx::ToEnclosingRect(
MathUtil::MapClippedRect(draw_transform, gfx::RectF(content_rect)));
- // Layers can't clip across surfaces, so count this as internal occlusion.
- if (is_clipped)
- unoccluded_region_in_target_surface.Intersect(clip_rect_in_target);
unoccluded_region_in_target_surface.Subtract(
stack_.back().occlusion_from_inside_target);
- gfx::RectF unoccluded_rect_in_target_surface_without_outside_occlusion =
- unoccluded_region_in_target_surface.bounds();
unoccluded_region_in_target_surface.Subtract(
stack_.back().occlusion_from_outside_target);
- // Treat other clipping as occlusion from outside the surface.
- // TODO(danakj): Clip to visibleContentRect?
- unoccluded_region_in_target_surface.Intersect(
- render_target->render_surface()->content_rect());
- unoccluded_region_in_target_surface.Intersect(
- ScreenSpaceClipRectInTargetSurface(render_target->render_surface(),
- screen_space_clip_rect_));
-
gfx::RectF unoccluded_rect_in_target_surface =
unoccluded_region_in_target_surface.bounds();
gfx::Rect unoccluded_rect = gfx::ToEnclosingRect(
@@ -639,13 +590,6 @@ gfx::Rect OcclusionTrackerBase<LayerType, RenderSurfaceType>::
unoccluded_rect_in_target_surface));
unoccluded_rect.Intersect(content_rect);
- if (has_occlusion_from_outside_target_surface) {
- // Check if the unoccluded rect shrank when applying outside occlusion.
- *has_occlusion_from_outside_target_surface = !gfx::SubtractRects(
- unoccluded_rect_in_target_surface_without_outside_occlusion,
- unoccluded_rect_in_target_surface).IsEmpty();
- }
-
return unoccluded_rect;
}
@@ -654,8 +598,7 @@ gfx::Rect OcclusionTrackerBase<LayerType, RenderSurfaceType>::
UnoccludedContributingSurfaceContentRect(
const LayerType* layer,
bool for_replica,
- gfx::Rect content_rect,
- bool* has_occlusion_from_outside_target_surface) const {
+ gfx::Rect content_rect) const {
DCHECK(!stack_.empty());
// The layer is a contributing render_target so it should have a surface.
DCHECK(layer->render_surface());
@@ -667,11 +610,6 @@ gfx::Rect OcclusionTrackerBase<LayerType, RenderSurfaceType>::
// target in the occlusion tracker.
DCHECK_EQ(layer, stack_.back().target);
- if (has_occlusion_from_outside_target_surface)
- *has_occlusion_from_outside_target_surface = false;
- if (prevent_occlusion_)
- return content_rect;
-
if (content_rect.IsEmpty())
return content_rect;
@@ -705,11 +643,6 @@ gfx::Rect OcclusionTrackerBase<LayerType, RenderSurfaceType>::
const StackObject& second_last = stack_[stack_.size() - 2];
unoccluded_region_in_target_surface.Subtract(
second_last.occlusion_from_inside_target);
- }
- gfx::RectF unoccluded_rect_in_target_surface_without_outside_occlusion =
- unoccluded_region_in_target_surface.bounds();
- if (has_occlusion) {
- const StackObject& second_last = stack_[stack_.size() - 2];
unoccluded_region_in_target_surface.Subtract(
second_last.occlusion_from_outside_target);
}
@@ -729,13 +662,6 @@ gfx::Rect OcclusionTrackerBase<LayerType, RenderSurfaceType>::
unoccluded_rect_in_target_surface));
unoccluded_rect.Intersect(content_rect);
- if (has_occlusion_from_outside_target_surface) {
- // Check if the unoccluded rect shrank when applying outside occlusion.
- *has_occlusion_from_outside_target_surface = !gfx::SubtractRects(
- unoccluded_rect_in_target_surface_without_outside_occlusion,
- unoccluded_rect_in_target_surface).IsEmpty();
- }
-
return unoccluded_rect;
}
diff --git a/chromium/cc/trees/occlusion_tracker.h b/chromium/cc/trees/occlusion_tracker.h
index 132b3fa3160..68418c7e435 100644
--- a/chromium/cc/trees/occlusion_tracker.h
+++ b/chromium/cc/trees/occlusion_tracker.h
@@ -37,10 +37,8 @@ class CC_EXPORT OcclusionTrackerBase {
~OcclusionTrackerBase();
// Called at the beginning of each step in the LayerIterator's front-to-back
- // traversal. If |prevent_occlusion| is true, the layer will be considered
- // unoccluded.
- void EnterLayer(const LayerIteratorPosition<LayerType>& layer_iterator,
- bool prevent_occlusion);
+ // traversal.
+ void EnterLayer(const LayerIteratorPosition<LayerType>& layer_iterator);
// Called at the end of each step in the LayerIterator's front-to-back
// traversal.
void LeaveLayer(const LayerIteratorPosition<LayerType>& layer_iterator);
@@ -48,29 +46,21 @@ class CC_EXPORT OcclusionTrackerBase {
// Returns true if the given rect in content space for a layer is fully
// occluded in either screen space or the layer's target surface.
// |render_target| is the contributing layer's render target, and
- // |draw_transform|, |transformsToTargetKnown| and |clippedRectInTarget| are
- // relative to that.
+ // |draw_transform| and |impl_draw_transform_is_unknown| are relative to that.
bool Occluded(const LayerType* render_target,
gfx::Rect content_rect,
const gfx::Transform& draw_transform,
- bool impl_draw_transform_is_unknown,
- bool is_clipped,
- gfx::Rect clip_rect_in_target,
- bool* has_occlusion_from_outside_target_surface) const;
+ bool impl_draw_transform_is_unknown) const;
// Gives an unoccluded sub-rect of |content_rect| in the content space of a
// layer. Used when considering occlusion for a layer that paints/draws
// something. |render_target| is the contributing layer's render target, and
- // |draw_transform|, |transformsToTargetKnown| and |clippedRectInTarget| are
- // relative to that.
+ // |draw_transform| and |impl_draw_transform_is_unknown| are relative to that.
gfx::Rect UnoccludedContentRect(
const LayerType* render_target,
gfx::Rect content_rect,
const gfx::Transform& draw_transform,
- bool impl_draw_transform_is_unknown,
- bool is_clipped,
- gfx::Rect clip_rect_in_target,
- bool* has_occlusion_from_outside_target_surface) const;
+ bool impl_draw_transform_is_unknown) const;
// Gives an unoccluded sub-rect of |content_rect| in the content space of the
// render_target owned by the layer. Used when considering occlusion for a
@@ -78,8 +68,7 @@ class CC_EXPORT OcclusionTrackerBase {
gfx::Rect UnoccludedContributingSurfaceContentRect(
const LayerType* layer,
bool for_replica,
- gfx::Rect content_rect,
- bool* has_occlusion_from_outside_target_surface) const;
+ gfx::Rect content_rect) const;
// Report operations for recording overdraw metrics.
OverdrawMetrics* overdraw_metrics() const {
@@ -155,7 +144,6 @@ class CC_EXPORT OcclusionTrackerBase {
gfx::Rect screen_space_clip_rect_;
scoped_ptr<class OverdrawMetrics> overdraw_metrics_;
gfx::Size minimum_tracking_size_;
- bool prevent_occlusion_;
// This is used for visualizing the occlusion tracking process.
std::vector<gfx::Rect>* occluding_screen_space_rects_;
diff --git a/chromium/cc/trees/occlusion_tracker_unittest.cc b/chromium/cc/trees/occlusion_tracker_unittest.cc
index 469d65a4cb2..89afe4f909b 100644
--- a/chromium/cc/trees/occlusion_tracker_unittest.cc
+++ b/chromium/cc/trees/occlusion_tracker_unittest.cc
@@ -30,9 +30,10 @@ namespace {
class TestContentLayer : public Layer {
public:
- TestContentLayer() : Layer(), override_opaque_contents_rect_(false) {}
+ TestContentLayer() : Layer(), override_opaque_contents_rect_(false) {
+ SetIsDrawable(true);
+ }
- virtual bool DrawsContent() const OVERRIDE { return true; }
virtual Region VisibleContentOpaqueRegion() const OVERRIDE {
if (override_opaque_contents_rect_)
return gfx::IntersectRects(opaque_contents_rect_, visible_content_rect());
@@ -92,42 +93,25 @@ class TestOcclusionTrackerWithClip
: TestOcclusionTrackerBase<LayerType, RenderSurfaceType>(viewport_rect,
false) {}
- bool OccludedLayer(const LayerType* layer, gfx::Rect content_rect) {
- bool temp;
- return OccludedLayer(layer, content_rect, &temp);
- }
-
bool OccludedLayer(const LayerType* layer,
- gfx::Rect content_rect,
- bool* has_occlusion_from_outside_target_surface) const {
+ gfx::Rect content_rect) const {
+ DCHECK(layer->visible_content_rect().Contains(content_rect));
return this->Occluded(layer->render_target(),
content_rect,
layer->draw_transform(),
- LayerImplDrawTransformIsUnknown(layer),
- layer->is_clipped(),
- layer->clip_rect(),
- has_occlusion_from_outside_target_surface);
+ LayerImplDrawTransformIsUnknown(layer));
}
+
// Gives an unoccluded sub-rect of |content_rect| in the content space of the
// layer. Simple wrapper around UnoccludedContentRect.
gfx::Rect UnoccludedLayerContentRect(const LayerType* layer,
gfx::Rect content_rect) const {
- bool temp;
- return UnoccludedLayerContentRect(layer, content_rect, &temp);
- }
-
- gfx::Rect UnoccludedLayerContentRect(
- const LayerType* layer,
- gfx::Rect content_rect,
- bool* has_occlusion_from_outside_target_surface) const {
+ DCHECK(layer->visible_content_rect().Contains(content_rect));
return this->UnoccludedContentRect(
layer->render_target(),
content_rect,
layer->draw_transform(),
- LayerImplDrawTransformIsUnknown(layer),
- layer->is_clipped(),
- layer->clip_rect(),
- has_occlusion_from_outside_target_surface);
+ LayerImplDrawTransformIsUnknown(layer));
}
};
@@ -359,12 +343,19 @@ template <typename Types> class OcclusionTrackerTest : public testing::Test {
Types::TestLayerIterator::Begin(render_surface_layer_list_.get());
}
+ void SetDrawsContent(LayerImpl* layer_impl, bool draws_content) {
+ layer_impl->SetDrawsContent(draws_content);
+ }
+
+ void SetDrawsContent(Layer* layer, bool draws_content) {
+ layer->SetIsDrawable(draws_content);
+ }
+
void EnterLayer(typename Types::LayerType* layer,
- typename Types::OcclusionTrackerType* occlusion,
- bool prevent_occlusion) {
+ typename Types::OcclusionTrackerType* occlusion) {
ASSERT_EQ(layer, *layer_iterator_);
ASSERT_TRUE(layer_iterator_.represents_itself());
- occlusion->EnterLayer(layer_iterator_, prevent_occlusion);
+ occlusion->EnterLayer(layer_iterator_);
}
void LeaveLayer(typename Types::LayerType* layer,
@@ -377,21 +368,20 @@ template <typename Types> class OcclusionTrackerTest : public testing::Test {
void VisitLayer(typename Types::LayerType* layer,
typename Types::OcclusionTrackerType* occlusion) {
- EnterLayer(layer, occlusion, false);
+ EnterLayer(layer, occlusion);
LeaveLayer(layer, occlusion);
}
void EnterContributingSurface(
typename Types::LayerType* layer,
- typename Types::OcclusionTrackerType* occlusion,
- bool prevent_occlusion) {
+ typename Types::OcclusionTrackerType* occlusion) {
ASSERT_EQ(layer, *layer_iterator_);
ASSERT_TRUE(layer_iterator_.represents_target_render_surface());
- occlusion->EnterLayer(layer_iterator_, false);
+ occlusion->EnterLayer(layer_iterator_);
occlusion->LeaveLayer(layer_iterator_);
++layer_iterator_;
ASSERT_TRUE(layer_iterator_.represents_contributing_render_surface());
- occlusion->EnterLayer(layer_iterator_, prevent_occlusion);
+ occlusion->EnterLayer(layer_iterator_);
}
void LeaveContributingSurface(
@@ -406,7 +396,7 @@ template <typename Types> class OcclusionTrackerTest : public testing::Test {
void VisitContributingSurface(
typename Types::LayerType* layer,
typename Types::OcclusionTrackerType* occlusion) {
- EnterContributingSurface(layer, occlusion, false);
+ EnterContributingSurface(layer, occlusion);
LeaveContributingSurface(layer, occlusion);
}
@@ -567,7 +557,7 @@ class OcclusionTrackerTestIdentityTransforms
gfx::Rect(0, 0, 1000, 1000), false);
this->VisitLayer(layer, &occlusion);
- this->EnterLayer(parent, &occlusion, false);
+ this->EnterLayer(parent, &occlusion);
EXPECT_EQ(gfx::Rect().ToString(),
occlusion.occlusion_from_outside_target().ToString());
@@ -577,8 +567,8 @@ class OcclusionTrackerTestIdentityTransforms
EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 30, 70, 70)));
EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 30, 70, 70)));
EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 29, 70, 70)));
- EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(31, 30, 70, 70)));
- EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 31, 70, 70)));
+ EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(31, 30, 69, 70)));
+ EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 31, 70, 69)));
EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
parent, gfx::Rect(30, 30, 70, 70)).IsEmpty());
@@ -593,19 +583,19 @@ class OcclusionTrackerTestIdentityTransforms
parent, gfx::Rect(30, 29, 70, 70)));
EXPECT_RECT_EQ(gfx::Rect(31, 29, 69, 1),
occlusion.UnoccludedLayerContentRect(
- parent, gfx::Rect(31, 29, 70, 70)));
+ parent, gfx::Rect(31, 29, 69, 70)));
EXPECT_RECT_EQ(gfx::Rect(),
occlusion.UnoccludedLayerContentRect(
- parent, gfx::Rect(31, 30, 70, 70)));
+ parent, gfx::Rect(31, 30, 69, 70)));
EXPECT_RECT_EQ(gfx::Rect(),
occlusion.UnoccludedLayerContentRect(
- parent, gfx::Rect(31, 31, 70, 70)));
+ parent, gfx::Rect(31, 31, 69, 69)));
EXPECT_RECT_EQ(gfx::Rect(),
occlusion.UnoccludedLayerContentRect(
- parent, gfx::Rect(30, 31, 70, 70)));
+ parent, gfx::Rect(30, 31, 70, 69)));
EXPECT_RECT_EQ(gfx::Rect(29, 31, 1, 69),
occlusion.UnoccludedLayerContentRect(
- parent, gfx::Rect(29, 31, 70, 70)));
+ parent, gfx::Rect(29, 31, 70, 69)));
}
};
@@ -634,7 +624,7 @@ class OcclusionTrackerTestQuadsMismatchLayer
gfx::Rect(0, 0, 1000, 1000));
this->VisitLayer(layer2, &occlusion);
- this->EnterLayer(layer1, &occlusion, false);
+ this->EnterLayer(layer1, &occlusion);
EXPECT_EQ(gfx::Rect().ToString(),
occlusion.occlusion_from_outside_target().ToString());
@@ -647,47 +637,26 @@ class OcclusionTrackerTestQuadsMismatchLayer
gfx::Transform quad_transform;
quad_transform.Translate(30.0, 30.0);
- gfx::Rect clip_rect_in_target(0, 0, 100, 100);
EXPECT_TRUE(occlusion.UnoccludedContentRect(parent,
gfx::Rect(0, 0, 10, 10),
quad_transform,
- false,
- true,
- clip_rect_in_target,
- NULL).IsEmpty());
+ false).IsEmpty());
EXPECT_RECT_EQ(gfx::Rect(0, 0, 10, 10),
occlusion.UnoccludedContentRect(parent,
gfx::Rect(0, 0, 10, 10),
quad_transform,
- true,
- true,
- clip_rect_in_target,
- NULL));
+ true));
EXPECT_RECT_EQ(gfx::Rect(40, 40, 10, 10),
occlusion.UnoccludedContentRect(parent,
gfx::Rect(40, 40, 10, 10),
quad_transform,
- false,
- true,
- clip_rect_in_target,
- NULL));
+ false));
EXPECT_RECT_EQ(gfx::Rect(40, 30, 5, 10),
occlusion.UnoccludedContentRect(parent,
gfx::Rect(35, 30, 10, 10),
quad_transform,
- false,
- true,
- clip_rect_in_target,
- NULL));
- EXPECT_RECT_EQ(gfx::Rect(40, 40, 5, 5),
- occlusion.UnoccludedContentRect(parent,
- gfx::Rect(40, 40, 10, 10),
- quad_transform,
- false,
- true,
- gfx::Rect(0, 0, 75, 75),
- NULL));
+ false));
}
};
@@ -722,7 +691,7 @@ class OcclusionTrackerTestRotatedChild : public OcclusionTrackerTest<Types> {
gfx::Rect(0, 0, 1000, 1000));
this->VisitLayer(layer, &occlusion);
- this->EnterLayer(parent, &occlusion, false);
+ this->EnterLayer(parent, &occlusion);
EXPECT_EQ(gfx::Rect().ToString(),
occlusion.occlusion_from_outside_target().ToString());
@@ -732,14 +701,14 @@ class OcclusionTrackerTestRotatedChild : public OcclusionTrackerTest<Types> {
EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 30, 70, 70)));
EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 30, 70, 70)));
EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 29, 70, 70)));
- EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(31, 30, 70, 70)));
- EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 31, 70, 70)));
+ EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(31, 30, 69, 70)));
+ EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 31, 70, 69)));
EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
parent, gfx::Rect(30, 30, 70, 70)).IsEmpty());
EXPECT_RECT_EQ(gfx::Rect(29, 30, 1, 70),
occlusion.UnoccludedLayerContentRect(
- parent, gfx::Rect(29, 30, 70, 70)));
+ parent, gfx::Rect(29, 30, 69, 70)));
EXPECT_RECT_EQ(gfx::Rect(29, 29, 70, 70),
occlusion.UnoccludedLayerContentRect(
parent, gfx::Rect(29, 29, 70, 70)));
@@ -748,19 +717,19 @@ class OcclusionTrackerTestRotatedChild : public OcclusionTrackerTest<Types> {
parent, gfx::Rect(30, 29, 70, 70)));
EXPECT_RECT_EQ(gfx::Rect(31, 29, 69, 1),
occlusion.UnoccludedLayerContentRect(
- parent, gfx::Rect(31, 29, 70, 70)));
+ parent, gfx::Rect(31, 29, 69, 70)));
EXPECT_RECT_EQ(gfx::Rect(),
occlusion.UnoccludedLayerContentRect(
- parent, gfx::Rect(31, 30, 70, 70)));
+ parent, gfx::Rect(31, 30, 69, 70)));
EXPECT_RECT_EQ(gfx::Rect(),
occlusion.UnoccludedLayerContentRect(
- parent, gfx::Rect(31, 31, 70, 70)));
+ parent, gfx::Rect(31, 31, 69, 69)));
EXPECT_RECT_EQ(gfx::Rect(),
occlusion.UnoccludedLayerContentRect(
- parent, gfx::Rect(30, 31, 70, 70)));
+ parent, gfx::Rect(30, 31, 70, 69)));
EXPECT_RECT_EQ(gfx::Rect(29, 31, 1, 69),
occlusion.UnoccludedLayerContentRect(
- parent, gfx::Rect(29, 31, 70, 70)));
+ parent, gfx::Rect(29, 31, 70, 69)));
}
};
@@ -793,7 +762,7 @@ class OcclusionTrackerTestTranslatedChild : public OcclusionTrackerTest<Types> {
gfx::Rect(0, 0, 1000, 1000));
this->VisitLayer(layer, &occlusion);
- this->EnterLayer(parent, &occlusion, false);
+ this->EnterLayer(parent, &occlusion);
EXPECT_EQ(gfx::Rect().ToString(),
occlusion.occlusion_from_outside_target().ToString());
@@ -803,8 +772,8 @@ class OcclusionTrackerTestTranslatedChild : public OcclusionTrackerTest<Types> {
EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(50, 50, 50, 50)));
EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(49, 50, 50, 50)));
EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(50, 49, 50, 50)));
- EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(51, 50, 50, 50)));
- EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(50, 51, 50, 50)));
+ EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(51, 50, 49, 50)));
+ EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(50, 51, 50, 49)));
EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
parent, gfx::Rect(50, 50, 50, 50)).IsEmpty());
@@ -819,16 +788,16 @@ class OcclusionTrackerTestTranslatedChild : public OcclusionTrackerTest<Types> {
parent, gfx::Rect(50, 49, 50, 50)));
EXPECT_RECT_EQ(gfx::Rect(51, 49, 49, 1),
occlusion.UnoccludedLayerContentRect(
- parent, gfx::Rect(51, 49, 50, 50)));
+ parent, gfx::Rect(51, 49, 49, 50)));
EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
- parent, gfx::Rect(51, 50, 50, 50)).IsEmpty());
+ parent, gfx::Rect(51, 50, 49, 50)).IsEmpty());
EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
- parent, gfx::Rect(51, 51, 50, 50)).IsEmpty());
+ parent, gfx::Rect(51, 51, 49, 49)).IsEmpty());
EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
- parent, gfx::Rect(50, 51, 50, 50)).IsEmpty());
+ parent, gfx::Rect(50, 51, 50, 49)).IsEmpty());
EXPECT_RECT_EQ(gfx::Rect(49, 51, 1, 49),
occlusion.UnoccludedLayerContentRect(
- parent, gfx::Rect(49, 51, 50, 50)));
+ parent, gfx::Rect(49, 51, 50, 49)));
}
};
@@ -865,7 +834,7 @@ class OcclusionTrackerTestChildInRotatedChild
gfx::Rect(0, 0, 1000, 1000));
this->VisitLayer(layer, &occlusion);
- this->EnterContributingSurface(child, &occlusion, false);
+ this->EnterContributingSurface(child, &occlusion);
EXPECT_EQ(gfx::Rect().ToString(),
occlusion.occlusion_from_outside_target().ToString());
@@ -873,7 +842,7 @@ class OcclusionTrackerTestChildInRotatedChild
occlusion.occlusion_from_inside_target().ToString());
this->LeaveContributingSurface(child, &occlusion);
- this->EnterLayer(parent, &occlusion, false);
+ this->EnterLayer(parent, &occlusion);
EXPECT_EQ(gfx::Rect().ToString(),
occlusion.occlusion_from_outside_target().ToString());
@@ -883,8 +852,8 @@ class OcclusionTrackerTestChildInRotatedChild
EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 40, 70, 60)));
EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 40, 70, 60)));
EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 39, 70, 60)));
- EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(31, 40, 70, 60)));
- EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 41, 70, 60)));
+ EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(31, 40, 69, 60)));
+ EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 41, 70, 59)));
/* Justification for the above occlusion from |layer|:
100
@@ -972,7 +941,7 @@ class OcclusionTrackerTestScaledRenderSurface
gfx::Rect(0, 0, 1000, 1000));
this->VisitLayer(occluder, &occlusion);
- this->EnterLayer(layer2, &occlusion, false);
+ this->EnterLayer(layer2, &occlusion);
EXPECT_EQ(gfx::Rect(100, 100, 100, 100).ToString(),
occlusion.occlusion_from_outside_target().ToString());
@@ -1050,7 +1019,7 @@ class OcclusionTrackerTestVisitTargetTwoTimes
EXPECT_EQ(gfx::Rect(10, 430, 60, 70).ToString(),
occlusion.occlusion_from_inside_target().ToString());
- this->EnterContributingSurface(child, &occlusion, false);
+ this->EnterContributingSurface(child, &occlusion);
EXPECT_EQ(gfx::Rect(0, 440, 20, 60).ToString(),
occlusion.occlusion_from_outside_target().ToString());
@@ -1060,7 +1029,7 @@ class OcclusionTrackerTestVisitTargetTwoTimes
// Occlusion in |child2| should get merged with the |child| surface we are
// leaving now.
this->LeaveContributingSurface(child, &occlusion);
- this->EnterLayer(parent, &occlusion, false);
+ this->EnterLayer(parent, &occlusion);
EXPECT_EQ(gfx::Rect().ToString(),
occlusion.occlusion_from_outside_target().ToString());
@@ -1116,10 +1085,10 @@ class OcclusionTrackerTestVisitTargetTwoTimes
parent, gfx::Rect(20, 39, 80, 60)));
EXPECT_RECT_EQ(gfx::Rect(),
occlusion.UnoccludedLayerContentRect(
- parent, gfx::Rect(31, 40, 70, 60)));
+ parent, gfx::Rect(31, 40, 69, 60)));
EXPECT_RECT_EQ(gfx::Rect(),
occlusion.UnoccludedLayerContentRect(
- parent, gfx::Rect(30, 41, 70, 60)));
+ parent, gfx::Rect(30, 41, 70, 59)));
/* Justification for the above occlusion from |layer|:
100
@@ -1207,7 +1176,7 @@ class OcclusionTrackerTestSurfaceRotatedOffAxis
layer_transform, layer->visible_content_rect());
this->VisitLayer(layer, &occlusion);
- this->EnterContributingSurface(child, &occlusion, false);
+ this->EnterContributingSurface(child, &occlusion);
EXPECT_EQ(gfx::Rect().ToString(),
occlusion.occlusion_from_outside_target().ToString());
@@ -1215,7 +1184,7 @@ class OcclusionTrackerTestSurfaceRotatedOffAxis
occlusion.occlusion_from_inside_target().ToString());
this->LeaveContributingSurface(child, &occlusion);
- this->EnterLayer(parent, &occlusion, false);
+ this->EnterLayer(parent, &occlusion);
EXPECT_EQ(gfx::Rect().ToString(),
occlusion.occlusion_from_outside_target().ToString());
@@ -1276,7 +1245,7 @@ class OcclusionTrackerTestSurfaceWithTwoOpaqueChildren
this->VisitLayer(layer2, &occlusion);
this->VisitLayer(layer1, &occlusion);
this->VisitLayer(child, &occlusion);
- this->EnterContributingSurface(child, &occlusion, false);
+ this->EnterContributingSurface(child, &occlusion);
EXPECT_EQ(gfx::Rect().ToString(),
occlusion.occlusion_from_outside_target().ToString());
@@ -1285,31 +1254,23 @@ class OcclusionTrackerTestSurfaceWithTwoOpaqueChildren
EXPECT_TRUE(occlusion.OccludedLayer(child, gfx::Rect(10, 430, 60, 70)));
EXPECT_FALSE(occlusion.OccludedLayer(child, gfx::Rect(9, 430, 60, 70)));
- // These rects are occluded except for the part outside the bounds of the
- // target surface.
- EXPECT_TRUE(occlusion.OccludedLayer(child, gfx::Rect(10, 429, 60, 70)));
- EXPECT_TRUE(occlusion.OccludedLayer(child, gfx::Rect(11, 430, 60, 70)));
- EXPECT_TRUE(occlusion.OccludedLayer(child, gfx::Rect(10, 431, 60, 70)));
+ EXPECT_TRUE(occlusion.OccludedLayer(child, gfx::Rect(11, 430, 59, 70)));
+ EXPECT_TRUE(occlusion.OccludedLayer(child, gfx::Rect(10, 431, 60, 69)));
EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
child, gfx::Rect(10, 430, 60, 70)).IsEmpty());
EXPECT_RECT_EQ(
gfx::Rect(9, 430, 1, 70),
occlusion.UnoccludedLayerContentRect(child, gfx::Rect(9, 430, 60, 70)));
- // These rects are occluded except for the part outside the bounds of the
- // target surface.
EXPECT_RECT_EQ(gfx::Rect(),
occlusion.UnoccludedLayerContentRect(
- child, gfx::Rect(10, 429, 60, 70)));
+ child, gfx::Rect(11, 430, 59, 70)));
EXPECT_RECT_EQ(gfx::Rect(),
occlusion.UnoccludedLayerContentRect(
- child, gfx::Rect(11, 430, 60, 70)));
- EXPECT_RECT_EQ(gfx::Rect(),
- occlusion.UnoccludedLayerContentRect(
- child, gfx::Rect(10, 431, 60, 70)));
+ child, gfx::Rect(10, 431, 60, 69)));
this->LeaveContributingSurface(child, &occlusion);
- this->EnterLayer(parent, &occlusion, false);
+ this->EnterLayer(parent, &occlusion);
EXPECT_EQ(gfx::Rect().ToString(),
occlusion.occlusion_from_outside_target().ToString());
@@ -1330,10 +1291,10 @@ class OcclusionTrackerTestSurfaceWithTwoOpaqueChildren
parent, gfx::Rect(30, 39, 70, 60)));
EXPECT_RECT_EQ(gfx::Rect(),
occlusion.UnoccludedLayerContentRect(
- parent, gfx::Rect(31, 40, 70, 60)));
+ parent, gfx::Rect(31, 40, 69, 60)));
EXPECT_RECT_EQ(gfx::Rect(),
occlusion.UnoccludedLayerContentRect(
- parent, gfx::Rect(30, 41, 70, 60)));
+ parent, gfx::Rect(30, 41, 70, 59)));
/* Justification for the above occlusion from |layer1| and |layer2|:
@@ -1402,27 +1363,21 @@ class OcclusionTrackerTestOverlappingSurfaceSiblings
gfx::Rect(0, 0, 1000, 1000));
this->VisitLayer(layer2, &occlusion);
- this->EnterContributingSurface(child2, &occlusion, false);
+ this->EnterContributingSurface(child2, &occlusion);
EXPECT_EQ(gfx::Rect().ToString(),
occlusion.occlusion_from_outside_target().ToString());
EXPECT_EQ(gfx::Rect(-10, 420, 70, 80).ToString(),
occlusion.occlusion_from_inside_target().ToString());
- EXPECT_TRUE(occlusion.OccludedLayer(child2, gfx::Rect(-10, 420, 70, 80)));
- EXPECT_TRUE(occlusion.OccludedLayer(child2, gfx::Rect(-11, 420, 70, 80)));
- EXPECT_TRUE(occlusion.OccludedLayer(child2, gfx::Rect(-10, 419, 70, 80)));
- EXPECT_TRUE(occlusion.OccludedLayer(child2, gfx::Rect(-10, 420, 71, 80)));
- EXPECT_TRUE(occlusion.OccludedLayer(child2, gfx::Rect(-10, 420, 70, 81)));
-
// There is nothing above child2's surface in the z-order.
EXPECT_RECT_EQ(gfx::Rect(-10, 420, 70, 80),
occlusion.UnoccludedContributingSurfaceContentRect(
- child2, false, gfx::Rect(-10, 420, 70, 80), NULL));
+ child2, false, gfx::Rect(-10, 420, 70, 80)));
this->LeaveContributingSurface(child2, &occlusion);
this->VisitLayer(layer1, &occlusion);
- this->EnterContributingSurface(child1, &occlusion, false);
+ this->EnterContributingSurface(child1, &occlusion);
EXPECT_EQ(gfx::Rect(0, 430, 70, 80).ToString(),
occlusion.occlusion_from_outside_target().ToString());
@@ -1432,10 +1387,10 @@ class OcclusionTrackerTestOverlappingSurfaceSiblings
// child2's contents will occlude child1 below it.
EXPECT_RECT_EQ(gfx::Rect(-10, 430, 10, 70),
occlusion.UnoccludedContributingSurfaceContentRect(
- child1, false, gfx::Rect(-10, 430, 80, 70), NULL));
+ child1, false, gfx::Rect(-10, 430, 80, 70)));
this->LeaveContributingSurface(child1, &occlusion);
- this->EnterLayer(parent, &occlusion, false);
+ this->EnterLayer(parent, &occlusion);
EXPECT_EQ(gfx::Rect().ToString(),
occlusion.occlusion_from_outside_target().ToString());
@@ -1529,7 +1484,7 @@ class OcclusionTrackerTestOverlappingSurfaceSiblingsWithTwoTransforms
gfx::Rect(0, 0, 1000, 1000));
this->VisitLayer(layer2, &occlusion);
- this->EnterLayer(child2, &occlusion, false);
+ this->EnterLayer(child2, &occlusion);
EXPECT_EQ(gfx::Rect().ToString(),
occlusion.occlusion_from_outside_target().ToString());
@@ -1537,16 +1492,16 @@ class OcclusionTrackerTestOverlappingSurfaceSiblingsWithTwoTransforms
occlusion.occlusion_from_inside_target().ToString());
this->LeaveLayer(child2, &occlusion);
- this->EnterContributingSurface(child2, &occlusion, false);
+ this->EnterContributingSurface(child2, &occlusion);
// There is nothing above child2's surface in the z-order.
EXPECT_RECT_EQ(gfx::Rect(-10, 420, 70, 80),
occlusion.UnoccludedContributingSurfaceContentRect(
- child2, false, gfx::Rect(-10, 420, 70, 80), NULL));
+ child2, false, gfx::Rect(-10, 420, 70, 80)));
this->LeaveContributingSurface(child2, &occlusion);
this->VisitLayer(layer1, &occlusion);
- this->EnterContributingSurface(child1, &occlusion, false);
+ this->EnterContributingSurface(child1, &occlusion);
EXPECT_EQ(gfx::Rect(420, -10, 70, 80).ToString(),
occlusion.occlusion_from_outside_target().ToString());
@@ -1556,16 +1511,16 @@ class OcclusionTrackerTestOverlappingSurfaceSiblingsWithTwoTransforms
// child2's contents will occlude child1 below it.
EXPECT_RECT_EQ(gfx::Rect(420, -20, 80, 90),
occlusion.UnoccludedContributingSurfaceContentRect(
- child1, false, gfx::Rect(420, -20, 80, 90), NULL));
+ child1, false, gfx::Rect(420, -20, 80, 90)));
EXPECT_RECT_EQ(gfx::Rect(490, -10, 10, 80),
occlusion.UnoccludedContributingSurfaceContentRect(
- child1, false, gfx::Rect(420, -10, 80, 90), NULL));
+ child1, false, gfx::Rect(420, -10, 80, 90)));
EXPECT_RECT_EQ(gfx::Rect(420, -20, 70, 10),
occlusion.UnoccludedContributingSurfaceContentRect(
- child1, false, gfx::Rect(420, -20, 70, 90), NULL));
+ child1, false, gfx::Rect(420, -20, 70, 90)));
this->LeaveContributingSurface(child1, &occlusion);
- this->EnterLayer(parent, &occlusion, false);
+ this->EnterLayer(parent, &occlusion);
EXPECT_EQ(gfx::Rect().ToString(),
occlusion.occlusion_from_outside_target().ToString());
@@ -1654,7 +1609,7 @@ class OcclusionTrackerTestFilters : public OcclusionTrackerTest<Types> {
// Opacity layer won't contribute to occlusion.
this->VisitLayer(opacity_layer, &occlusion);
- this->EnterContributingSurface(opacity_layer, &occlusion, false);
+ this->EnterContributingSurface(opacity_layer, &occlusion);
EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty());
@@ -1666,7 +1621,7 @@ class OcclusionTrackerTestFilters : public OcclusionTrackerTest<Types> {
// Opaque layer will contribute to occlusion.
this->VisitLayer(opaque_layer, &occlusion);
- this->EnterContributingSurface(opaque_layer, &occlusion, false);
+ this->EnterContributingSurface(opaque_layer, &occlusion);
EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
EXPECT_EQ(gfx::Rect(0, 430, 70, 70).ToString(),
@@ -1680,19 +1635,19 @@ class OcclusionTrackerTestFilters : public OcclusionTrackerTest<Types> {
// The blur layer needs to throw away any occlusion from outside its
// subtree.
- this->EnterLayer(blur_layer, &occlusion, false);
+ this->EnterLayer(blur_layer, &occlusion);
EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty());
// And it won't contribute to occlusion.
this->LeaveLayer(blur_layer, &occlusion);
- this->EnterContributingSurface(blur_layer, &occlusion, false);
+ this->EnterContributingSurface(blur_layer, &occlusion);
EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty());
// But the opaque layer's occlusion is preserved on the parent.
this->LeaveContributingSurface(blur_layer, &occlusion);
- this->EnterLayer(parent, &occlusion, false);
+ this->EnterLayer(parent, &occlusion);
EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
EXPECT_EQ(gfx::Rect(30, 30, 70, 70).ToString(),
occlusion.occlusion_from_inside_target().ToString());
@@ -1730,7 +1685,7 @@ class OcclusionTrackerTestReplicaDoesOcclude
occlusion.occlusion_from_inside_target().ToString());
this->VisitContributingSurface(surface, &occlusion);
- this->EnterLayer(parent, &occlusion, false);
+ this->EnterLayer(parent, &occlusion);
// The surface and replica should both be occluding the parent.
EXPECT_EQ(
@@ -1772,7 +1727,7 @@ class OcclusionTrackerTestReplicaWithClipping
occlusion.occlusion_from_inside_target().ToString());
this->VisitContributingSurface(surface, &occlusion);
- this->EnterLayer(parent, &occlusion, false);
+ this->EnterLayer(parent, &occlusion);
// The surface and replica should both be occluding the parent.
EXPECT_EQ(
@@ -1813,7 +1768,7 @@ class OcclusionTrackerTestReplicaWithMask : public OcclusionTrackerTest<Types> {
occlusion.occlusion_from_inside_target().ToString());
this->VisitContributingSurface(surface, &occlusion);
- this->EnterLayer(parent, &occlusion, false);
+ this->EnterLayer(parent, &occlusion);
// The replica should not be occluding the parent, since it has a mask
// applied to it.
@@ -1825,429 +1780,6 @@ class OcclusionTrackerTestReplicaWithMask : public OcclusionTrackerTest<Types> {
ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestReplicaWithMask);
template <class Types>
-class OcclusionTrackerTestLayerClipRectOutsideChild
- : public OcclusionTrackerTest<Types> {
- protected:
- explicit OcclusionTrackerTestLayerClipRectOutsideChild(bool opaque_layers)
- : OcclusionTrackerTest<Types>(opaque_layers) {}
- void RunMyTest() {
- typename Types::ContentLayerType* parent = this->CreateRoot(
- this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
- typename Types::ContentLayerType* clip =
- this->CreateDrawingLayer(parent,
- this->identity_matrix,
- gfx::PointF(200.f, 100.f),
- gfx::Size(100, 100),
- false);
- clip->SetMasksToBounds(true);
- typename Types::ContentLayerType* layer =
- this->CreateDrawingLayer(clip,
- this->identity_matrix,
- gfx::PointF(-200.f, -100.f),
- gfx::Size(200, 200),
- false);
- this->CalcDrawEtc(parent);
-
- TestOcclusionTrackerWithClip<typename Types::LayerType,
- typename Types::RenderSurfaceType> occlusion(
- gfx::Rect(0, 0, 1000, 1000));
-
- this->EnterLayer(layer, &occlusion, false);
-
- EXPECT_TRUE(occlusion.OccludedLayer(layer, gfx::Rect(0, 0, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(layer, gfx::Rect(100, 0, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(layer, gfx::Rect(0, 100, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(layer, gfx::Rect(100, 100, 100, 100)));
- EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(200, 100, 100, 100)));
-
- this->LeaveLayer(layer, &occlusion);
- this->EnterLayer(clip, &occlusion, false);
-
- EXPECT_TRUE(occlusion.OccludedLayer(clip, gfx::Rect(-100, 0, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(clip, gfx::Rect(0, -100, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(clip, gfx::Rect(100, 0, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(clip, gfx::Rect(0, 100, 100, 100)));
- EXPECT_FALSE(occlusion.OccludedLayer(clip, gfx::Rect(0, 0, 100, 100)));
-
- EXPECT_RECT_EQ(gfx::Rect(0, 0, 100, 100),
- occlusion.UnoccludedLayerContentRect(
- clip, gfx::Rect(-100, -100, 300, 300)));
- }
-};
-
-ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestLayerClipRectOutsideChild);
-
-template <class Types>
-class OcclusionTrackerTestViewportRectOutsideChild
- : public OcclusionTrackerTest<Types> {
- protected:
- explicit OcclusionTrackerTestViewportRectOutsideChild(bool opaque_layers)
- : OcclusionTrackerTest<Types>(opaque_layers) {}
- void RunMyTest() {
- typename Types::ContentLayerType* parent = this->CreateRoot(
- this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
- typename Types::ContentLayerType* layer =
- this->CreateDrawingSurface(parent,
- this->identity_matrix,
- gfx::PointF(),
- gfx::Size(200, 200),
- true);
- this->CalcDrawEtc(parent);
-
- TestOcclusionTrackerWithClip<typename Types::LayerType,
- typename Types::RenderSurfaceType> occlusion(
- gfx::Rect(200, 100, 100, 100));
-
- this->EnterLayer(layer, &occlusion, false);
-
- EXPECT_TRUE(occlusion.OccludedLayer(layer, gfx::Rect(0, 0, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(layer, gfx::Rect(100, 0, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(layer, gfx::Rect(0, 100, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(layer, gfx::Rect(100, 100, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(layer, gfx::Rect(200, 100, 100, 100)));
-
- this->LeaveLayer(layer, &occlusion);
- this->VisitContributingSurface(layer, &occlusion);
- this->EnterLayer(parent, &occlusion, false);
-
- EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(0, 0, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(0, 100, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(100, 0, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(0, 100, 100, 100)));
- EXPECT_FALSE(
- occlusion.OccludedLayer(parent, gfx::Rect(200, 100, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(200, 0, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(0, 200, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(100, 200, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(200, 200, 100, 100)));
-
- EXPECT_RECT_EQ(gfx::Rect(200, 100, 100, 100),
- occlusion.UnoccludedLayerContentRect(
- parent, gfx::Rect(0, 0, 300, 300)));
- }
-};
-
-ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestViewportRectOutsideChild);
-
-template <class Types>
-class OcclusionTrackerTestLayerClipRectOverChild
- : public OcclusionTrackerTest<Types> {
- protected:
- explicit OcclusionTrackerTestLayerClipRectOverChild(bool opaque_layers)
- : OcclusionTrackerTest<Types>(opaque_layers) {}
- void RunMyTest() {
- typename Types::ContentLayerType* parent = this->CreateRoot(
- this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
- typename Types::ContentLayerType* clip =
- this->CreateDrawingLayer(parent,
- this->identity_matrix,
- gfx::PointF(100.f, 100.f),
- gfx::Size(100, 100),
- false);
- clip->SetMasksToBounds(true);
- typename Types::ContentLayerType* layer =
- this->CreateDrawingSurface(clip,
- this->identity_matrix,
- gfx::PointF(-100.f, -100.f),
- gfx::Size(200, 200),
- true);
- this->CalcDrawEtc(parent);
-
- TestOcclusionTrackerWithClip<typename Types::LayerType,
- typename Types::RenderSurfaceType> occlusion(
- gfx::Rect(0, 0, 1000, 1000));
-
- this->EnterLayer(layer, &occlusion, false);
-
- EXPECT_TRUE(occlusion.OccludedLayer(layer, gfx::Rect(0, 0, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(layer, gfx::Rect(0, 100, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(layer, gfx::Rect(100, 0, 100, 100)));
- EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(100, 100, 100, 100)));
-
- this->LeaveLayer(layer, &occlusion);
- this->VisitContributingSurface(layer, &occlusion);
-
- EXPECT_EQ(gfx::Rect(100, 100, 100, 100).ToString(),
- occlusion.occlusion_from_inside_target().ToString());
-
- this->EnterLayer(clip, &occlusion, false);
-
- EXPECT_TRUE(occlusion.OccludedLayer(clip, gfx::Rect(0, 0, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(clip, gfx::Rect(0, 100, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(clip, gfx::Rect(100, 0, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(clip, gfx::Rect(100, 100, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(clip, gfx::Rect(200, 100, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(clip, gfx::Rect(200, 0, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(clip, gfx::Rect(0, 200, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(clip, gfx::Rect(100, 200, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(clip, gfx::Rect(200, 200, 100, 100)));
-
- EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
- clip, gfx::Rect(0, 0, 300, 300)).IsEmpty());
- }
-};
-
-ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestLayerClipRectOverChild);
-
-template <class Types>
-class OcclusionTrackerTestViewportRectOverChild
- : public OcclusionTrackerTest<Types> {
- protected:
- explicit OcclusionTrackerTestViewportRectOverChild(bool opaque_layers)
- : OcclusionTrackerTest<Types>(opaque_layers) {}
- void RunMyTest() {
- typename Types::ContentLayerType* parent = this->CreateRoot(
- this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
- typename Types::ContentLayerType* layer =
- this->CreateDrawingSurface(parent,
- this->identity_matrix,
- gfx::PointF(),
- gfx::Size(200, 200),
- true);
- this->CalcDrawEtc(parent);
-
- TestOcclusionTrackerWithClip<typename Types::LayerType,
- typename Types::RenderSurfaceType> occlusion(
- gfx::Rect(100, 100, 100, 100));
-
- this->EnterLayer(layer, &occlusion, false);
-
- EXPECT_TRUE(occlusion.OccludedLayer(layer, gfx::Rect(0, 0, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(layer, gfx::Rect(0, 100, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(layer, gfx::Rect(100, 0, 100, 100)));
- EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(100, 100, 100, 100)));
-
- this->LeaveLayer(layer, &occlusion);
- this->VisitContributingSurface(layer, &occlusion);
- this->EnterLayer(parent, &occlusion, false);
-
- EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(0, 0, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(0, 100, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(100, 0, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(100, 100, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(200, 100, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(200, 0, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(0, 200, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(100, 200, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(200, 200, 100, 100)));
-
- EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
- parent, gfx::Rect(0, 0, 300, 300)).IsEmpty());
- }
-};
-
-ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestViewportRectOverChild);
-
-template <class Types>
-class OcclusionTrackerTestLayerClipRectPartlyOverChild
- : public OcclusionTrackerTest<Types> {
- protected:
- explicit OcclusionTrackerTestLayerClipRectPartlyOverChild(bool opaque_layers)
- : OcclusionTrackerTest<Types>(opaque_layers) {}
- void RunMyTest() {
- typename Types::ContentLayerType* parent = this->CreateRoot(
- this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
- typename Types::ContentLayerType* clip =
- this->CreateDrawingLayer(parent,
- this->identity_matrix,
- gfx::PointF(50.f, 50.f),
- gfx::Size(200, 200),
- false);
- clip->SetMasksToBounds(true);
- typename Types::ContentLayerType* layer =
- this->CreateDrawingSurface(clip,
- this->identity_matrix,
- gfx::PointF(-50.f, -50.f),
- gfx::Size(200, 200),
- true);
- this->CalcDrawEtc(parent);
-
- TestOcclusionTrackerWithClip<typename Types::LayerType,
- typename Types::RenderSurfaceType> occlusion(
- gfx::Rect(0, 0, 1000, 1000));
-
- this->EnterLayer(layer, &occlusion, false);
-
- EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(0, 0, 100, 100)));
- EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(0, 100, 100, 100)));
- EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(100, 0, 100, 100)));
- EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(100, 100, 100, 100)));
-
- EXPECT_TRUE(occlusion.OccludedLayer(layer, gfx::Rect(0, 0, 100, 50)));
- EXPECT_TRUE(occlusion.OccludedLayer(layer, gfx::Rect(0, 0, 50, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(layer, gfx::Rect(100, 0, 100, 50)));
- EXPECT_TRUE(occlusion.OccludedLayer(layer, gfx::Rect(0, 100, 50, 100)));
-
- this->LeaveLayer(layer, &occlusion);
- this->VisitContributingSurface(layer, &occlusion);
- this->EnterLayer(clip, &occlusion, false);
-
- EXPECT_EQ(gfx::Rect(50, 50, 150, 150).ToString(),
- occlusion.occlusion_from_inside_target().ToString());
- }
-};
-
-ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestLayerClipRectPartlyOverChild);
-
-template <class Types>
-class OcclusionTrackerTestViewportRectPartlyOverChild
- : public OcclusionTrackerTest<Types> {
- protected:
- explicit OcclusionTrackerTestViewportRectPartlyOverChild(bool opaque_layers)
- : OcclusionTrackerTest<Types>(opaque_layers) {}
- void RunMyTest() {
- typename Types::ContentLayerType* parent = this->CreateRoot(
- this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
- typename Types::ContentLayerType* layer =
- this->CreateDrawingSurface(parent,
- this->identity_matrix,
- gfx::PointF(),
- gfx::Size(200, 200),
- true);
- this->CalcDrawEtc(parent);
-
- TestOcclusionTrackerWithClip<typename Types::LayerType,
- typename Types::RenderSurfaceType> occlusion(
- gfx::Rect(50, 50, 200, 200));
-
- this->EnterLayer(layer, &occlusion, false);
-
- EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(0, 0, 100, 100)));
- EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(0, 100, 100, 100)));
- EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(100, 0, 100, 100)));
- EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(100, 100, 100, 100)));
-
- this->LeaveLayer(layer, &occlusion);
- this->VisitContributingSurface(layer, &occlusion);
- this->EnterLayer(parent, &occlusion, false);
-
- EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(0, 0, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(0, 100, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(100, 0, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(100, 100, 100, 100)));
- EXPECT_FALSE(
- occlusion.OccludedLayer(parent, gfx::Rect(200, 100, 100, 100)));
- EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(200, 0, 100, 100)));
- EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(0, 200, 100, 100)));
- EXPECT_FALSE(
- occlusion.OccludedLayer(parent, gfx::Rect(100, 200, 100, 100)));
- EXPECT_FALSE(
- occlusion.OccludedLayer(parent, gfx::Rect(200, 200, 100, 100)));
-
- EXPECT_RECT_EQ(gfx::Rect(50, 50, 200, 200),
- occlusion.UnoccludedLayerContentRect(
- parent, gfx::Rect(0, 0, 300, 300)));
- EXPECT_RECT_EQ(gfx::Rect(200, 50, 50, 50),
- occlusion.UnoccludedLayerContentRect(
- parent, gfx::Rect(0, 0, 300, 100)));
- EXPECT_RECT_EQ(gfx::Rect(200, 100, 50, 100),
- occlusion.UnoccludedLayerContentRect(
- parent, gfx::Rect(0, 100, 300, 100)));
- EXPECT_RECT_EQ(gfx::Rect(200, 100, 50, 100),
- occlusion.UnoccludedLayerContentRect(
- parent, gfx::Rect(200, 100, 100, 100)));
- EXPECT_RECT_EQ(gfx::Rect(100, 200, 100, 50),
- occlusion.UnoccludedLayerContentRect(
- parent, gfx::Rect(100, 200, 100, 100)));
- }
-};
-
-ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestViewportRectPartlyOverChild);
-
-template <class Types>
-class OcclusionTrackerTestViewportRectOverNothing
- : public OcclusionTrackerTest<Types> {
- protected:
- explicit OcclusionTrackerTestViewportRectOverNothing(bool opaque_layers)
- : OcclusionTrackerTest<Types>(opaque_layers) {}
- void RunMyTest() {
- typename Types::ContentLayerType* parent = this->CreateRoot(
- this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
- typename Types::ContentLayerType* layer =
- this->CreateDrawingSurface(parent,
- this->identity_matrix,
- gfx::PointF(),
- gfx::Size(200, 200),
- true);
- this->CalcDrawEtc(parent);
-
- TestOcclusionTrackerWithClip<typename Types::LayerType,
- typename Types::RenderSurfaceType> occlusion(
- gfx::Rect(500, 500, 100, 100));
-
- this->EnterLayer(layer, &occlusion, false);
-
- EXPECT_TRUE(occlusion.OccludedLayer(layer, gfx::Rect(0, 0, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(layer, gfx::Rect(0, 100, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(layer, gfx::Rect(100, 0, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(layer, gfx::Rect(100, 100, 100, 100)));
-
- this->LeaveLayer(layer, &occlusion);
- this->VisitContributingSurface(layer, &occlusion);
- this->EnterLayer(parent, &occlusion, false);
-
- EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(0, 0, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(0, 100, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(100, 0, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(100, 100, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(200, 100, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(200, 0, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(0, 200, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(100, 200, 100, 100)));
- EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(200, 200, 100, 100)));
-
- EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
- parent, gfx::Rect(0, 0, 300, 300)).IsEmpty());
- EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
- parent, gfx::Rect(0, 0, 300, 100)).IsEmpty());
- EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
- parent, gfx::Rect(0, 100, 300, 100)).IsEmpty());
- EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
- parent, gfx::Rect(200, 100, 100, 100)).IsEmpty());
- EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
- parent, gfx::Rect(100, 200, 100, 100)).IsEmpty());
- }
-};
-
-ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestViewportRectOverNothing);
-
-template <class Types>
-class OcclusionTrackerTestLayerClipRectForLayerOffOrigin
- : public OcclusionTrackerTest<Types> {
- protected:
- explicit OcclusionTrackerTestLayerClipRectForLayerOffOrigin(
- bool opaque_layers)
- : OcclusionTrackerTest<Types>(opaque_layers) {}
- void RunMyTest() {
- typename Types::ContentLayerType* parent = this->CreateRoot(
- this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
- typename Types::ContentLayerType* layer =
- this->CreateDrawingSurface(parent,
- this->identity_matrix,
- gfx::PointF(),
- gfx::Size(200, 200),
- true);
- this->CalcDrawEtc(parent);
-
- TestOcclusionTrackerWithClip<typename Types::LayerType,
- typename Types::RenderSurfaceType> occlusion(
- gfx::Rect(0, 0, 1000, 1000));
- this->EnterLayer(layer, &occlusion, false);
-
- // This layer is translated when drawn into its target. So if the clip rect
- // given from the target surface is not in that target space, then after
- // translating these query rects into the target, they will fall outside the
- // clip and be considered occluded.
- EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(0, 0, 100, 100)));
- EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(0, 100, 100, 100)));
- EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(100, 0, 100, 100)));
- EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(100, 100, 100, 100)));
- }
-};
-
-ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestLayerClipRectForLayerOffOrigin);
-
-template <class Types>
class OcclusionTrackerTestOpaqueContentsRegionEmpty
: public OcclusionTrackerTest<Types> {
protected:
@@ -2267,19 +1799,16 @@ class OcclusionTrackerTestOpaqueContentsRegionEmpty
TestOcclusionTrackerWithClip<typename Types::LayerType,
typename Types::RenderSurfaceType> occlusion(
gfx::Rect(0, 0, 1000, 1000));
- this->EnterLayer(layer, &occlusion, false);
+ this->EnterLayer(layer, &occlusion);
EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(0, 0, 100, 100)));
EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(100, 0, 100, 100)));
EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(0, 100, 100, 100)));
EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(100, 100, 100, 100)));
- // Occluded since its outside the surface bounds.
- EXPECT_TRUE(occlusion.OccludedLayer(layer, gfx::Rect(200, 100, 100, 100)));
-
this->LeaveLayer(layer, &occlusion);
this->VisitContributingSurface(layer, &occlusion);
- this->EnterLayer(parent, &occlusion, false);
+ this->EnterLayer(parent, &occlusion);
EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
}
@@ -2311,7 +1840,7 @@ class OcclusionTrackerTestOpaqueContentsRegionNonEmpty
this->ResetLayerIterator();
this->VisitLayer(layer, &occlusion);
- this->EnterLayer(parent, &occlusion, false);
+ this->EnterLayer(parent, &occlusion);
EXPECT_EQ(gfx::Rect(100, 100, 100, 100).ToString(),
occlusion.occlusion_from_inside_target().ToString());
@@ -2331,7 +1860,7 @@ class OcclusionTrackerTestOpaqueContentsRegionNonEmpty
this->ResetLayerIterator();
this->VisitLayer(layer, &occlusion);
- this->EnterLayer(parent, &occlusion, false);
+ this->EnterLayer(parent, &occlusion);
EXPECT_EQ(gfx::Rect(120, 120, 180, 180).ToString(),
occlusion.occlusion_from_inside_target().ToString());
@@ -2351,7 +1880,7 @@ class OcclusionTrackerTestOpaqueContentsRegionNonEmpty
this->ResetLayerIterator();
this->VisitLayer(layer, &occlusion);
- this->EnterLayer(parent, &occlusion, false);
+ this->EnterLayer(parent, &occlusion);
EXPECT_EQ(gfx::Rect(250, 250, 50, 50).ToString(),
occlusion.occlusion_from_inside_target().ToString());
@@ -2392,7 +1921,7 @@ class OcclusionTrackerTest3dTransform : public OcclusionTrackerTest<Types> {
TestOcclusionTrackerWithClip<typename Types::LayerType,
typename Types::RenderSurfaceType> occlusion(
gfx::Rect(0, 0, 1000, 1000));
- this->EnterLayer(layer, &occlusion, false);
+ this->EnterLayer(layer, &occlusion);
// The layer is rotated in 3d but without preserving 3d, so it only gets
// resized.
@@ -2484,7 +2013,7 @@ class OcclusionTrackerTestPerspectiveTransform
TestOcclusionTrackerWithClip<typename Types::LayerType,
typename Types::RenderSurfaceType> occlusion(
gfx::Rect(0, 0, 1000, 1000));
- this->EnterLayer(layer, &occlusion, false);
+ this->EnterLayer(layer, &occlusion);
EXPECT_RECT_EQ(
gfx::Rect(0, 0, 200, 200),
@@ -2528,14 +2057,15 @@ class OcclusionTrackerTestPerspectiveTransformBehindCamera
TestOcclusionTrackerWithClip<typename Types::LayerType,
typename Types::RenderSurfaceType> occlusion(
gfx::Rect(0, 0, 1000, 1000));
- this->EnterLayer(layer, &occlusion, false);
+ this->EnterLayer(layer, &occlusion);
// The bottom 11 pixel rows of this layer remain visible inside the
// container, after translation to the target surface. When translated back,
// this will include many more pixels but must include at least the bottom
// 11 rows.
EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
- layer, gfx::Rect(0, 0, 500, 500)).Contains(gfx::Rect(0, 489, 500, 11)));
+ layer, gfx::Rect(0, 26, 500, 474)).
+ Contains(gfx::Rect(0, 489, 500, 11)));
}
};
@@ -2572,7 +2102,7 @@ class OcclusionTrackerTestLayerBehindCameraDoesNotOcclude
// The |layer| is entirely behind the camera and should not occlude.
this->VisitLayer(layer, &occlusion);
- this->EnterLayer(parent, &occlusion, false);
+ this->EnterLayer(parent, &occlusion);
EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty());
EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
}
@@ -2614,7 +2144,7 @@ class OcclusionTrackerTestLargePixelsOccludeInsideClipRect
// will actually go outside of the layer's clip rect. Ensure that those
// pixels don't occlude things outside the clip rect.
this->VisitLayer(layer, &occlusion);
- this->EnterLayer(parent, &occlusion, false);
+ this->EnterLayer(parent, &occlusion);
EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
occlusion.occlusion_from_inside_target().ToString());
EXPECT_EQ(gfx::Rect().ToString(),
@@ -2696,7 +2226,7 @@ class OcclusionTrackerTestAnimationOpacity1OnMainThread
gfx::Rect(0, 0, 1000, 1000));
this->VisitLayer(topmost, &occlusion);
- this->EnterLayer(parent2, &occlusion, false);
+ this->EnterLayer(parent2, &occlusion);
// This occlusion will affect all surfaces.
EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(),
occlusion.occlusion_from_inside_target().ToString());
@@ -2708,7 +2238,7 @@ class OcclusionTrackerTestAnimationOpacity1OnMainThread
this->LeaveLayer(parent2, &occlusion);
this->VisitLayer(surface_child2, &occlusion);
- this->EnterLayer(surface_child, &occlusion, false);
+ this->EnterLayer(surface_child, &occlusion);
EXPECT_EQ(gfx::Rect(0, 0, 100, 300).ToString(),
occlusion.occlusion_from_inside_target().ToString());
EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(),
@@ -2717,7 +2247,7 @@ class OcclusionTrackerTestAnimationOpacity1OnMainThread
occlusion.UnoccludedLayerContentRect(
surface_child, gfx::Rect(0, 0, 200, 300)));
this->LeaveLayer(surface_child, &occlusion);
- this->EnterLayer(surface, &occlusion, false);
+ this->EnterLayer(surface, &occlusion);
EXPECT_EQ(gfx::Rect(0, 0, 200, 300).ToString(),
occlusion.occlusion_from_inside_target().ToString());
EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(),
@@ -2727,7 +2257,7 @@ class OcclusionTrackerTestAnimationOpacity1OnMainThread
surface, gfx::Rect(0, 0, 300, 300)));
this->LeaveLayer(surface, &occlusion);
- this->EnterContributingSurface(surface, &occlusion, false);
+ this->EnterContributingSurface(surface, &occlusion);
// Occlusion within the surface is lost when leaving the animating surface.
EXPECT_EQ(gfx::Rect().ToString(),
occlusion.occlusion_from_inside_target().ToString());
@@ -2735,7 +2265,7 @@ class OcclusionTrackerTestAnimationOpacity1OnMainThread
occlusion.occlusion_from_outside_target().ToString());
EXPECT_RECT_EQ(gfx::Rect(0, 0, 250, 300),
occlusion.UnoccludedContributingSurfaceContentRect(
- surface, false, gfx::Rect(0, 0, 300, 300), NULL));
+ surface, false, gfx::Rect(0, 0, 300, 300)));
this->LeaveContributingSurface(surface, &occlusion);
// Occlusion from outside the animating surface still exists.
@@ -2745,7 +2275,7 @@ class OcclusionTrackerTestAnimationOpacity1OnMainThread
occlusion.occlusion_from_outside_target().ToString());
this->VisitLayer(layer, &occlusion);
- this->EnterLayer(parent, &occlusion, false);
+ this->EnterLayer(parent, &occlusion);
// Occlusion is not added for the animating |layer|.
EXPECT_RECT_EQ(gfx::Rect(0, 0, 250, 300),
@@ -2817,7 +2347,7 @@ class OcclusionTrackerTestAnimationOpacity0OnMainThread
gfx::Rect(0, 0, 1000, 1000));
this->VisitLayer(topmost, &occlusion);
- this->EnterLayer(parent2, &occlusion, false);
+ this->EnterLayer(parent2, &occlusion);
// This occlusion will affect all surfaces.
EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(),
occlusion.occlusion_from_inside_target().ToString());
@@ -2829,7 +2359,7 @@ class OcclusionTrackerTestAnimationOpacity0OnMainThread
this->LeaveLayer(parent2, &occlusion);
this->VisitLayer(surface_child2, &occlusion);
- this->EnterLayer(surface_child, &occlusion, false);
+ this->EnterLayer(surface_child, &occlusion);
EXPECT_EQ(gfx::Rect(0, 0, 100, 300).ToString(),
occlusion.occlusion_from_inside_target().ToString());
EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(),
@@ -2838,7 +2368,7 @@ class OcclusionTrackerTestAnimationOpacity0OnMainThread
occlusion.UnoccludedLayerContentRect(
surface_child, gfx::Rect(0, 0, 200, 300)));
this->LeaveLayer(surface_child, &occlusion);
- this->EnterLayer(surface, &occlusion, false);
+ this->EnterLayer(surface, &occlusion);
EXPECT_EQ(gfx::Rect(0, 0, 200, 300).ToString(),
occlusion.occlusion_from_inside_target().ToString());
EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(),
@@ -2848,7 +2378,7 @@ class OcclusionTrackerTestAnimationOpacity0OnMainThread
surface, gfx::Rect(0, 0, 300, 300)));
this->LeaveLayer(surface, &occlusion);
- this->EnterContributingSurface(surface, &occlusion, false);
+ this->EnterContributingSurface(surface, &occlusion);
// Occlusion within the surface is lost when leaving the animating surface.
EXPECT_EQ(gfx::Rect().ToString(),
occlusion.occlusion_from_inside_target().ToString());
@@ -2856,7 +2386,7 @@ class OcclusionTrackerTestAnimationOpacity0OnMainThread
occlusion.occlusion_from_outside_target().ToString());
EXPECT_RECT_EQ(gfx::Rect(0, 0, 250, 300),
occlusion.UnoccludedContributingSurfaceContentRect(
- surface, false, gfx::Rect(0, 0, 300, 300), NULL));
+ surface, false, gfx::Rect(0, 0, 300, 300)));
this->LeaveContributingSurface(surface, &occlusion);
// Occlusion from outside the animating surface still exists.
@@ -2866,7 +2396,7 @@ class OcclusionTrackerTestAnimationOpacity0OnMainThread
occlusion.occlusion_from_outside_target().ToString());
this->VisitLayer(layer, &occlusion);
- this->EnterLayer(parent, &occlusion, false);
+ this->EnterLayer(parent, &occlusion);
// Occlusion is not added for the animating |layer|.
EXPECT_RECT_EQ(gfx::Rect(0, 0, 250, 300),
@@ -2939,13 +2469,13 @@ class OcclusionTrackerTestAnimationTranslateOnMainThread
gfx::Rect(0, 0, 1000, 1000));
this->VisitLayer(surface2, &occlusion);
- this->EnterContributingSurface(surface2, &occlusion, false);
+ this->EnterContributingSurface(surface2, &occlusion);
EXPECT_EQ(gfx::Rect(0, 0, 50, 300).ToString(),
occlusion.occlusion_from_inside_target().ToString());
this->LeaveContributingSurface(surface2, &occlusion);
- this->EnterLayer(surface_child2, &occlusion, false);
+ this->EnterLayer(surface_child2, &occlusion);
// surface_child2 is moving in screen space but not relative to its target,
// so occlusion should happen in its target space only. It also means that
@@ -2961,7 +2491,7 @@ class OcclusionTrackerTestAnimationTranslateOnMainThread
occlusion.OccludedLayer(surface_child, gfx::Rect(0, 0, 50, 300)));
this->LeaveLayer(surface_child2, &occlusion);
- this->EnterLayer(surface_child, &occlusion, false);
+ this->EnterLayer(surface_child, &occlusion);
EXPECT_FALSE(
occlusion.OccludedLayer(surface_child, gfx::Rect(0, 0, 100, 300)));
EXPECT_EQ(gfx::Rect().ToString(),
@@ -2981,7 +2511,7 @@ class OcclusionTrackerTestAnimationTranslateOnMainThread
occlusion.OccludedLayer(surface_child, gfx::Rect(0, 0, 50, 300)));
this->LeaveLayer(surface_child, &occlusion);
- this->EnterLayer(surface, &occlusion, false);
+ this->EnterLayer(surface, &occlusion);
// The surface_child is moving in screen space but not relative to its
// target, so occlusion should happen from within the target only.
EXPECT_EQ(gfx::Rect().ToString(),
@@ -3003,14 +2533,14 @@ class OcclusionTrackerTestAnimationTranslateOnMainThread
occlusion.UnoccludedLayerContentRect(
surface, gfx::Rect(0, 0, 300, 300)));
- this->EnterContributingSurface(surface, &occlusion, false);
+ this->EnterContributingSurface(surface, &occlusion);
// The contributing |surface| is animating so it can't be occluded.
EXPECT_RECT_EQ(gfx::Rect(0, 0, 300, 300),
occlusion.UnoccludedContributingSurfaceContentRect(
- surface, false, gfx::Rect(0, 0, 300, 300), NULL));
+ surface, false, gfx::Rect(0, 0, 300, 300)));
this->LeaveContributingSurface(surface, &occlusion);
- this->EnterLayer(layer, &occlusion, false);
+ this->EnterLayer(layer, &occlusion);
// The |surface| is moving in the screen and in its target, so all occlusion
// within the surface is lost when leaving it.
EXPECT_RECT_EQ(gfx::Rect(50, 0, 250, 300),
@@ -3018,7 +2548,7 @@ class OcclusionTrackerTestAnimationTranslateOnMainThread
parent, gfx::Rect(0, 0, 300, 300)));
this->LeaveLayer(layer, &occlusion);
- this->EnterLayer(parent, &occlusion, false);
+ this->EnterLayer(parent, &occlusion);
// The |layer| is animating in the screen and in its target, so no occlusion
// is added.
EXPECT_RECT_EQ(gfx::Rect(50, 0, 250, 300),
@@ -3162,17 +2692,18 @@ class OcclusionTrackerTestReplicaOccluded : public OcclusionTrackerTest<Types> {
this->VisitLayer(surface, &occlusion);
- EXPECT_EQ(gfx::Rect(0, 100, 100, 100).ToString(),
+ // Render target with replica ignores occlusion from outside.
+ EXPECT_EQ(gfx::Rect().ToString(),
occlusion.occlusion_from_outside_target().ToString());
EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
occlusion.occlusion_from_inside_target().ToString());
- this->EnterContributingSurface(surface, &occlusion, false);
+ this->EnterContributingSurface(surface, &occlusion);
// Surface is not occluded so it shouldn't think it is.
EXPECT_RECT_EQ(gfx::Rect(0, 0, 100, 100),
occlusion.UnoccludedContributingSurfaceContentRect(
- surface, false, gfx::Rect(0, 0, 100, 100), NULL));
+ surface, false, gfx::Rect(0, 0, 100, 100)));
}
};
@@ -3219,20 +2750,21 @@ class OcclusionTrackerTestSurfaceWithReplicaUnoccluded
this->VisitLayer(surface, &occlusion);
- EXPECT_EQ(gfx::Rect(0, 0, 100, 110).ToString(),
+ // Render target with replica ignores occlusion from outside.
+ EXPECT_EQ(gfx::Rect().ToString(),
occlusion.occlusion_from_outside_target().ToString());
EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
occlusion.occlusion_from_inside_target().ToString());
- this->EnterContributingSurface(surface, &occlusion, false);
+ this->EnterContributingSurface(surface, &occlusion);
// Surface is occluded, but only the top 10px of the replica.
EXPECT_RECT_EQ(gfx::Rect(0, 0, 0, 0),
occlusion.UnoccludedContributingSurfaceContentRect(
- surface, false, gfx::Rect(0, 0, 100, 100), NULL));
+ surface, false, gfx::Rect(0, 0, 100, 100)));
EXPECT_RECT_EQ(gfx::Rect(0, 10, 100, 90),
occlusion.UnoccludedContributingSurfaceContentRect(
- surface, true, gfx::Rect(0, 0, 100, 100), NULL));
+ surface, true, gfx::Rect(0, 0, 100, 100)));
}
};
@@ -3285,21 +2817,21 @@ class OcclusionTrackerTestSurfaceAndReplicaOccludedDifferently
this->VisitLayer(surface, &occlusion);
- EXPECT_EQ(UnionRegions(gfx::Rect(0, 0, 40, 100), gfx::Rect(0, 100, 50, 100))
- .ToString(),
+ // Render target with replica ignores occlusion from outside.
+ EXPECT_EQ(gfx::Rect().ToString(),
occlusion.occlusion_from_outside_target().ToString());
EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
occlusion.occlusion_from_inside_target().ToString());
- this->EnterContributingSurface(surface, &occlusion, false);
+ this->EnterContributingSurface(surface, &occlusion);
// Surface and replica are occluded different amounts.
EXPECT_RECT_EQ(gfx::Rect(40, 0, 60, 100),
occlusion.UnoccludedContributingSurfaceContentRect(
- surface, false, gfx::Rect(0, 0, 100, 100), NULL));
+ surface, false, gfx::Rect(0, 0, 100, 100)));
EXPECT_RECT_EQ(gfx::Rect(50, 0, 50, 100),
occlusion.UnoccludedContributingSurfaceContentRect(
- surface, true, gfx::Rect(0, 0, 100, 100), NULL));
+ surface, true, gfx::Rect(0, 0, 100, 100)));
}
};
@@ -3362,29 +2894,29 @@ class OcclusionTrackerTestSurfaceChildOfSurface
// |surface_child| exercises different code paths as its parent does not
// have a clip rect.
- this->EnterContributingSurface(surface_child, &occlusion, false);
+ this->EnterContributingSurface(surface_child, &occlusion);
// The surface_child's parent does not have a clip rect as it owns a render
// surface. Make sure the unoccluded rect does not get clipped away
// inappropriately.
EXPECT_RECT_EQ(gfx::Rect(0, 40, 100, 10),
occlusion.UnoccludedContributingSurfaceContentRect(
- surface_child, false, gfx::Rect(0, 0, 100, 50), NULL));
+ surface_child, false, gfx::Rect(0, 0, 100, 50)));
this->LeaveContributingSurface(surface_child, &occlusion);
// When the surface_child's occlusion is transformed up to its parent, make
// sure it is not clipped away inappropriately also.
- this->EnterLayer(surface, &occlusion, false);
+ this->EnterLayer(surface, &occlusion);
EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
occlusion.occlusion_from_outside_target().ToString());
EXPECT_EQ(gfx::Rect(0, 10, 100, 50).ToString(),
occlusion.occlusion_from_inside_target().ToString());
this->LeaveLayer(surface, &occlusion);
- this->EnterContributingSurface(surface, &occlusion, false);
+ this->EnterContributingSurface(surface, &occlusion);
// The surface's parent does have a clip rect as it is the root layer.
EXPECT_RECT_EQ(gfx::Rect(0, 50, 100, 50),
occlusion.UnoccludedContributingSurfaceContentRect(
- surface, false, gfx::Rect(0, 0, 100, 100), NULL));
+ surface, false, gfx::Rect(0, 0, 100, 100)));
}
};
@@ -3420,12 +2952,12 @@ class OcclusionTrackerTestTopmostSurfaceIsClippedToViewport
// The root layer always has a clip rect. So the parent of |surface| has a
// clip rect giving the surface itself a clip rect.
- this->EnterContributingSurface(surface, &occlusion, false);
+ this->EnterContributingSurface(surface, &occlusion);
// Make sure the parent's clip rect clips the unoccluded region of the
// child surface.
EXPECT_RECT_EQ(gfx::Rect(0, 0, 100, 200),
occlusion.UnoccludedContributingSurfaceContentRect(
- surface, false, gfx::Rect(0, 0, 100, 300), NULL));
+ surface, false, gfx::Rect(0, 0, 100, 300)));
}
this->ResetLayerIterator();
{
@@ -3438,12 +2970,12 @@ class OcclusionTrackerTestTopmostSurfaceIsClippedToViewport
// The root layer always has a clip rect. So the parent of |surface| has a
// clip rect giving the surface itself a clip rect.
- this->EnterContributingSurface(surface, &occlusion, false);
+ this->EnterContributingSurface(surface, &occlusion);
// Make sure the viewport rect clips the unoccluded region of the child
// surface.
EXPECT_RECT_EQ(gfx::Rect(0, 0, 100, 100),
occlusion.UnoccludedContributingSurfaceContentRect(
- surface, false, gfx::Rect(0, 0, 100, 300), NULL));
+ surface, false, gfx::Rect(0, 0, 100, 300)));
}
}
};
@@ -3508,21 +3040,21 @@ class OcclusionTrackerTestSurfaceChildOfClippingSurface
// |surface_child| exercises different code paths as its parent does not
// have a clip rect.
- this->EnterContributingSurface(surface_child, &occlusion, false);
+ this->EnterContributingSurface(surface_child, &occlusion);
// The surface_child's parent does not have a clip rect as it owns a render
// surface.
EXPECT_EQ(
gfx::Rect(0, 50, 80, 50).ToString(),
occlusion.UnoccludedContributingSurfaceContentRect(
- surface_child, false, gfx::Rect(0, 0, 100, 100), NULL).ToString());
+ surface_child, false, gfx::Rect(0, 0, 100, 100)).ToString());
this->LeaveContributingSurface(surface_child, &occlusion);
this->VisitLayer(surface, &occlusion);
- this->EnterContributingSurface(surface, &occlusion, false);
+ this->EnterContributingSurface(surface, &occlusion);
// The surface's parent does have a clip rect as it is the root layer.
EXPECT_EQ(gfx::Rect(0, 50, 80, 50).ToString(),
occlusion.UnoccludedContributingSurfaceContentRect(
- surface, false, gfx::Rect(0, 0, 100, 100), NULL).ToString());
+ surface, false, gfx::Rect(0, 0, 100, 100)).ToString());
}
};
@@ -3539,30 +3071,25 @@ class OcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilter
gfx::Transform scale_by_half;
scale_by_half.Scale(0.5, 0.5);
- // Make a surface and its replica, each 50x50, that are completely
- // surrounded by opaque layers which are above them in the z-order. The
- // surface is scaled to test that the pixel moving is done in the target
- // space, where the background filter is applied, but the surface appears at
- // 50, 50 and the replica at 200, 50.
+ // Make a 50x50 filtered surface that is completely surrounded by opaque
+ // layers which are above it in the z-order. The surface is scaled to test
+ // that the pixel moving is done in the target space, where the background
+ // filter is applied.
typename Types::ContentLayerType* parent = this->CreateRoot(
- this->identity_matrix, gfx::PointF(), gfx::Size(300, 150));
+ this->identity_matrix, gfx::PointF(), gfx::Size(200, 150));
typename Types::LayerType* filtered_surface =
this->CreateDrawingLayer(parent,
scale_by_half,
gfx::PointF(50.f, 50.f),
gfx::Size(100, 100),
false);
- this->CreateReplicaLayer(filtered_surface,
- this->identity_matrix,
- gfx::PointF(300.f, 0.f),
- gfx::Size());
typename Types::LayerType* occluding_layer1 = this->CreateDrawingLayer(
- parent, this->identity_matrix, gfx::PointF(), gfx::Size(300, 50), true);
+ parent, this->identity_matrix, gfx::PointF(), gfx::Size(200, 50), true);
typename Types::LayerType* occluding_layer2 =
this->CreateDrawingLayer(parent,
this->identity_matrix,
gfx::PointF(0.f, 100.f),
- gfx::Size(300, 50),
+ gfx::Size(200, 50),
true);
typename Types::LayerType* occluding_layer3 =
this->CreateDrawingLayer(parent,
@@ -3576,12 +3103,6 @@ class OcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilter
gfx::PointF(100.f, 50.f),
gfx::Size(100, 50),
true);
- typename Types::LayerType* occluding_layer5 =
- this->CreateDrawingLayer(parent,
- this->identity_matrix,
- gfx::PointF(250.f, 50.f),
- gfx::Size(50, 50),
- true);
// Filters make the layer own a surface.
FilterOperations filters;
@@ -3602,18 +3123,16 @@ class OcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilter
// These layers occlude pixels directly beside the filtered_surface. Because
// filtered surface blends pixels in a radius, it will need to see some of
// the pixels (up to radius far) underneath the occluding layers.
- this->VisitLayer(occluding_layer5, &occlusion);
this->VisitLayer(occluding_layer4, &occlusion);
this->VisitLayer(occluding_layer3, &occlusion);
this->VisitLayer(occluding_layer2, &occlusion);
this->VisitLayer(occluding_layer1, &occlusion);
Region expected_occlusion;
- expected_occlusion.Union(gfx::Rect(0, 0, 300, 50));
+ expected_occlusion.Union(gfx::Rect(0, 0, 200, 50));
expected_occlusion.Union(gfx::Rect(0, 50, 50, 50));
expected_occlusion.Union(gfx::Rect(100, 50, 100, 50));
- expected_occlusion.Union(gfx::Rect(250, 50, 50, 50));
- expected_occlusion.Union(gfx::Rect(0, 100, 300, 50));
+ expected_occlusion.Union(gfx::Rect(0, 100, 200, 50));
EXPECT_EQ(expected_occlusion.ToString(),
occlusion.occlusion_from_inside_target().ToString());
@@ -3622,13 +3141,12 @@ class OcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilter
this->VisitLayer(filtered_surface, &occlusion);
- // The filtered layer/replica does not occlude.
+ // The filtered layer does not occlude.
Region expected_occlusion_outside_surface;
- expected_occlusion_outside_surface.Union(gfx::Rect(-50, -50, 300, 50));
+ expected_occlusion_outside_surface.Union(gfx::Rect(-50, -50, 200, 50));
expected_occlusion_outside_surface.Union(gfx::Rect(-50, 0, 50, 50));
expected_occlusion_outside_surface.Union(gfx::Rect(50, 0, 100, 50));
- expected_occlusion_outside_surface.Union(gfx::Rect(200, 0, 50, 50));
- expected_occlusion_outside_surface.Union(gfx::Rect(-50, 50, 300, 50));
+ expected_occlusion_outside_surface.Union(gfx::Rect(-50, 50, 200, 50));
EXPECT_EQ(expected_occlusion_outside_surface.ToString(),
occlusion.occlusion_from_outside_target().ToString());
@@ -3641,24 +3159,19 @@ class OcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilter
// are drawn.
this->VisitContributingSurface(filtered_surface, &occlusion);
- this->EnterLayer(parent, &occlusion, false);
+ this->EnterLayer(parent, &occlusion);
Region expected_blurred_occlusion;
- expected_blurred_occlusion.Union(gfx::Rect(0, 0, 300, 50 - outset_top));
+ expected_blurred_occlusion.Union(gfx::Rect(0, 0, 200, 50 - outset_top));
expected_blurred_occlusion.Union(gfx::Rect(
0, 50 - outset_top, 50 - outset_left, 50 + outset_top + outset_bottom));
expected_blurred_occlusion.Union(
gfx::Rect(100 + outset_right,
50 - outset_top,
- 100 - outset_right - outset_left,
- 50 + outset_top + outset_bottom));
- expected_blurred_occlusion.Union(
- gfx::Rect(250 + outset_right,
- 50 - outset_top,
- 50 - outset_right,
+ 100 - outset_right,
50 + outset_top + outset_bottom));
expected_blurred_occlusion.Union(
- gfx::Rect(0, 100 + outset_bottom, 300, 50 - outset_bottom));
+ gfx::Rect(0, 100 + outset_bottom, 200, 50 - outset_bottom));
EXPECT_EQ(expected_blurred_occlusion.ToString(),
occlusion.occlusion_from_inside_target().ToString());
@@ -3699,39 +3212,6 @@ class OcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilter
EXPECT_EQ(
outset_rect.ToString(),
occlusion.UnoccludedLayerContentRect(parent, test_rect).ToString());
-
- // Nothing in the blur outsets for the filtered_surface's replica is
- // occluded.
- outset_rect = gfx::Rect(200 - outset_left,
- 50 - outset_top,
- 50 + outset_left + outset_right,
- 50 + outset_top + outset_bottom);
- test_rect = outset_rect;
- EXPECT_EQ(
- outset_rect.ToString(),
- occlusion.UnoccludedLayerContentRect(parent, test_rect).ToString());
-
- // Stuff outside the blur outsets is still occluded though.
- test_rect = outset_rect;
- test_rect.Inset(0, 0, -1, 0);
- EXPECT_EQ(
- outset_rect.ToString(),
- occlusion.UnoccludedLayerContentRect(parent, test_rect).ToString());
- test_rect = outset_rect;
- test_rect.Inset(0, 0, 0, -1);
- EXPECT_EQ(
- outset_rect.ToString(),
- occlusion.UnoccludedLayerContentRect(parent, test_rect).ToString());
- test_rect = outset_rect;
- test_rect.Inset(-1, 0, 0, 0);
- EXPECT_EQ(
- outset_rect.ToString(),
- occlusion.UnoccludedLayerContentRect(parent, test_rect).ToString());
- test_rect = outset_rect;
- test_rect.Inset(0, -1, 0, 0);
- EXPECT_EQ(
- outset_rect.ToString(),
- occlusion.UnoccludedLayerContentRect(parent, test_rect).ToString());
}
};
@@ -3815,238 +3295,6 @@ ALL_OCCLUSIONTRACKER_TEST(
OcclusionTrackerTestTwoBackgroundFiltersReduceOcclusionTwice);
template <class Types>
-class OcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilterWithClip
- : public OcclusionTrackerTest<Types> {
- protected:
- explicit
- OcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilterWithClip(
- bool opaque_layers)
- : OcclusionTrackerTest<Types>(opaque_layers) {}
- void RunMyTest() {
- // Make a surface and its replica, Each 50x50, that are completely
- // surrounded by opaque layers which are above them in the z-order.
- typename Types::ContentLayerType* parent = this->CreateRoot(
- this->identity_matrix, gfx::PointF(), gfx::Size(300, 150));
- // We stick the filtered surface inside a clipping surface so that we can
- // make sure the clip is honored when exposing pixels for
- // the background filter.
- typename Types::LayerType* clipping_surface =
- this->CreateDrawingSurface(parent,
- this->identity_matrix,
- gfx::PointF(),
- gfx::Size(300, 70),
- false);
- clipping_surface->SetMasksToBounds(true);
- typename Types::LayerType* filtered_surface =
- this->CreateDrawingLayer(clipping_surface,
- this->identity_matrix,
- gfx::PointF(50.f, 50.f),
- gfx::Size(50, 50),
- false);
- this->CreateReplicaLayer(filtered_surface,
- this->identity_matrix,
- gfx::PointF(150.f, 0.f),
- gfx::Size());
- typename Types::LayerType* occluding_layer1 = this->CreateDrawingLayer(
- parent, this->identity_matrix, gfx::PointF(), gfx::Size(300, 50), true);
- typename Types::LayerType* occluding_layer2 =
- this->CreateDrawingLayer(parent,
- this->identity_matrix,
- gfx::PointF(0.f, 100.f),
- gfx::Size(300, 50),
- true);
- typename Types::LayerType* occluding_layer3 =
- this->CreateDrawingLayer(parent,
- this->identity_matrix,
- gfx::PointF(0.f, 50.f),
- gfx::Size(50, 50),
- true);
- typename Types::LayerType* occluding_layer4 =
- this->CreateDrawingLayer(parent,
- this->identity_matrix,
- gfx::PointF(100.f, 50.f),
- gfx::Size(100, 50),
- true);
- typename Types::LayerType* occluding_layer5 =
- this->CreateDrawingLayer(parent,
- this->identity_matrix,
- gfx::PointF(250.f, 50.f),
- gfx::Size(50, 50),
- true);
-
- // Filters make the layer own a surface. This filter is large enough that it
- // goes outside the bottom of the clipping_surface.
- FilterOperations filters;
- filters.Append(FilterOperation::CreateBlurFilter(12.f));
- filtered_surface->SetBackgroundFilters(filters);
-
- // Save the distance of influence for the blur effect.
- int outset_top, outset_right, outset_bottom, outset_left;
- filters.GetOutsets(
- &outset_top, &outset_right, &outset_bottom, &outset_left);
-
- this->CalcDrawEtc(parent);
-
- TestOcclusionTrackerWithClip<typename Types::LayerType,
- typename Types::RenderSurfaceType> occlusion(
- gfx::Rect(0, 0, 1000, 1000));
-
- // These layers occlude pixels directly beside the filtered_surface. Because
- // filtered surface blends pixels in a radius, it will need to see some of
- // the pixels (up to radius far) underneath the occluding layers.
- this->VisitLayer(occluding_layer5, &occlusion);
- this->VisitLayer(occluding_layer4, &occlusion);
- this->VisitLayer(occluding_layer3, &occlusion);
- this->VisitLayer(occluding_layer2, &occlusion);
- this->VisitLayer(occluding_layer1, &occlusion);
-
- Region expected_occlusion;
- expected_occlusion.Union(gfx::Rect(0, 0, 300, 50));
- expected_occlusion.Union(gfx::Rect(0, 50, 50, 50));
- expected_occlusion.Union(gfx::Rect(100, 50, 100, 50));
- expected_occlusion.Union(gfx::Rect(250, 50, 50, 50));
- expected_occlusion.Union(gfx::Rect(0, 100, 300, 50));
-
- EXPECT_EQ(expected_occlusion.ToString(),
- occlusion.occlusion_from_inside_target().ToString());
- EXPECT_EQ(gfx::Rect().ToString(),
- occlusion.occlusion_from_outside_target().ToString());
-
- // Everything outside the surface/replica is occluded but the
- // surface/replica itself is not.
- this->VisitLayer(filtered_surface, &occlusion);
-
- // The filtered layer/replica does not occlude.
- Region expected_occlusion_outside_surface;
- expected_occlusion_outside_surface.Union(gfx::Rect(-50, -50, 300, 50));
- expected_occlusion_outside_surface.Union(gfx::Rect(-50, 0, 50, 50));
- expected_occlusion_outside_surface.Union(gfx::Rect(50, 0, 100, 50));
- expected_occlusion_outside_surface.Union(gfx::Rect(200, 0, 50, 50));
- expected_occlusion_outside_surface.Union(gfx::Rect(-50, 50, 300, 50));
-
- EXPECT_EQ(expected_occlusion_outside_surface.ToString(),
- occlusion.occlusion_from_outside_target().ToString());
- EXPECT_EQ(gfx::Rect().ToString(),
- occlusion.occlusion_from_inside_target().ToString());
-
- // The surface has a background blur, so it needs pixels that are currently
- // considered occluded in order to be drawn. So the pixels it needs should
- // be removed some the occluded area so that when we get to the parent they
- // are drawn.
- this->VisitContributingSurface(filtered_surface, &occlusion);
-
- this->VisitLayer(clipping_surface, &occlusion);
- this->EnterContributingSurface(clipping_surface, &occlusion, false);
-
- Region expected_blurred_occlusion;
- expected_blurred_occlusion.Union(gfx::Rect(0, 0, 300, 50 - outset_top));
- expected_blurred_occlusion.Union(gfx::Rect(
- 0, 50 - outset_top, 50 - outset_left, 20 + outset_top + outset_bottom));
- expected_blurred_occlusion.Union(
- gfx::Rect(100 + outset_right,
- 50 - outset_top,
- 100 - outset_right - outset_left,
- 20 + outset_top + outset_bottom));
- expected_blurred_occlusion.Union(
- gfx::Rect(250 + outset_right,
- 50 - outset_top,
- 50 - outset_right,
- 20 + outset_top + outset_bottom));
- expected_blurred_occlusion.Union(gfx::Rect(0, 100 + 5, 300, 50 - 5));
-
- EXPECT_EQ(expected_blurred_occlusion.ToString(),
- occlusion.occlusion_from_outside_target().ToString());
- EXPECT_EQ(gfx::Rect().ToString(),
- occlusion.occlusion_from_inside_target().ToString());
-
- gfx::Rect outset_rect;
- gfx::Rect clipped_outset_rect;
- gfx::Rect test_rect;
-
- // Nothing in the (clipped) blur outsets for the filtered_surface is
- // occluded.
- outset_rect = gfx::Rect(50 - outset_left,
- 50 - outset_top,
- 50 + outset_left + outset_right,
- 50 + outset_top + outset_bottom);
- clipped_outset_rect = outset_rect;
- clipped_outset_rect.Intersect(gfx::Rect(0 - outset_left,
- 0 - outset_top,
- 300 + outset_left + outset_right,
- 70 + outset_top + outset_bottom));
- clipped_outset_rect.Intersect(gfx::Rect(0, 0, 300, 70));
- test_rect = outset_rect;
- EXPECT_RECT_EQ(
- clipped_outset_rect,
- occlusion.UnoccludedLayerContentRect(clipping_surface, test_rect));
-
- // Stuff outside the (clipped) blur outsets is still occluded though.
- test_rect = outset_rect;
- test_rect.Inset(0, 0, -1, 0);
- EXPECT_RECT_EQ(
- clipped_outset_rect,
- occlusion.UnoccludedLayerContentRect(clipping_surface, test_rect));
- test_rect = outset_rect;
- test_rect.Inset(0, 0, 0, -1);
- EXPECT_RECT_EQ(
- clipped_outset_rect,
- occlusion.UnoccludedLayerContentRect(clipping_surface, test_rect));
- test_rect = outset_rect;
- test_rect.Inset(-1, 0, 0, 0);
- EXPECT_RECT_EQ(
- clipped_outset_rect,
- occlusion.UnoccludedLayerContentRect(clipping_surface, test_rect));
- test_rect = outset_rect;
- test_rect.Inset(0, -1, 0, 0);
- EXPECT_RECT_EQ(
- clipped_outset_rect,
- occlusion.UnoccludedLayerContentRect(clipping_surface, test_rect));
-
- // Nothing in the (clipped) blur outsets for the filtered_surface's replica
- // is occluded.
- outset_rect = gfx::Rect(200 - outset_left,
- 50 - outset_top,
- 50 + outset_left + outset_right,
- 50 + outset_top + outset_bottom);
- clipped_outset_rect = outset_rect;
- clipped_outset_rect.Intersect(gfx::Rect(0 - outset_left,
- 0 - outset_top,
- 300 + outset_left + outset_right,
- 70 + outset_top + outset_bottom));
- clipped_outset_rect.Intersect(gfx::Rect(0, 0, 300, 70));
- test_rect = outset_rect;
- EXPECT_RECT_EQ(
- clipped_outset_rect,
- occlusion.UnoccludedLayerContentRect(clipping_surface, test_rect));
-
- // Stuff outside the (clipped) blur outsets is still occluded though.
- test_rect = outset_rect;
- test_rect.Inset(0, 0, -1, 0);
- EXPECT_RECT_EQ(
- clipped_outset_rect,
- occlusion.UnoccludedLayerContentRect(clipping_surface, test_rect));
- test_rect = outset_rect;
- test_rect.Inset(0, 0, 0, -1);
- EXPECT_RECT_EQ(
- clipped_outset_rect,
- occlusion.UnoccludedLayerContentRect(clipping_surface, test_rect));
- test_rect = outset_rect;
- test_rect.Inset(-1, 0, 0, 0);
- EXPECT_RECT_EQ(
- clipped_outset_rect,
- occlusion.UnoccludedLayerContentRect(clipping_surface, test_rect));
- test_rect = outset_rect;
- test_rect.Inset(0, -1, 0, 0);
- EXPECT_RECT_EQ(
- clipped_outset_rect,
- occlusion.UnoccludedLayerContentRect(clipping_surface, test_rect));
- }
-};
-
-ALL_OCCLUSIONTRACKER_TEST(
- OcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilterWithClip);
-
-template <class Types>
class OcclusionTrackerTestDontReduceOcclusionBelowBackgroundFilter
: public OcclusionTrackerTest<Types> {
protected:
@@ -4135,35 +3383,24 @@ class OcclusionTrackerTestDontReduceOcclusionIfBackgroundFilterIsOccluded
gfx::Transform scale_by_half;
scale_by_half.Scale(0.5, 0.5);
- // Make a surface and its replica, each 50x50, that are completely occluded
- // by opaque layers which are above them in the z-order. The surface is
+ // Make a 50x50 filtered surface that is completely occluded by an opaque
+ // layer which is above it in the z-order. The surface is
// scaled to test that the pixel moving is done in the target space, where
- // the background filter is applied, but the surface appears at 50, 50 and
- // the replica at 200, 50.
+ // the background filter is applied, but the surface appears at 50, 50.
typename Types::ContentLayerType* parent = this->CreateRoot(
- this->identity_matrix, gfx::PointF(), gfx::Size(300, 150));
+ this->identity_matrix, gfx::PointF(), gfx::Size(200, 150));
typename Types::LayerType* filtered_surface =
this->CreateDrawingLayer(parent,
scale_by_half,
gfx::PointF(50.f, 50.f),
gfx::Size(100, 100),
false);
- this->CreateReplicaLayer(filtered_surface,
- this->identity_matrix,
- gfx::PointF(300.f, 0.f),
- gfx::Size());
- typename Types::LayerType* above_surface_layer =
+ typename Types::LayerType* occluding_layer =
this->CreateDrawingLayer(parent,
this->identity_matrix,
gfx::PointF(50.f, 50.f),
gfx::Size(50, 50),
true);
- typename Types::LayerType* above_replica_layer =
- this->CreateDrawingLayer(parent,
- this->identity_matrix,
- gfx::PointF(200.f, 50.f),
- gfx::Size(50, 50),
- true);
// Filters make the layer own a surface.
FilterOperations filters;
@@ -4176,20 +3413,16 @@ class OcclusionTrackerTestDontReduceOcclusionIfBackgroundFilterIsOccluded
typename Types::RenderSurfaceType> occlusion(
gfx::Rect(0, 0, 1000, 1000));
- this->VisitLayer(above_replica_layer, &occlusion);
- this->VisitLayer(above_surface_layer, &occlusion);
+ this->VisitLayer(occluding_layer, &occlusion);
this->VisitLayer(filtered_surface, &occlusion);
{
// The layers above the filtered surface occlude from outside.
gfx::Rect occlusion_above_surface = gfx::Rect(0, 0, 50, 50);
- gfx::Rect occlusion_above_replica = gfx::Rect(150, 0, 50, 50);
- Region expected_opaque_region =
- UnionRegions(occlusion_above_surface, occlusion_above_replica);
EXPECT_EQ(gfx::Rect().ToString(),
occlusion.occlusion_from_inside_target().ToString());
- EXPECT_EQ(expected_opaque_region.ToString(),
+ EXPECT_EQ(occlusion_above_surface.ToString(),
occlusion.occlusion_from_outside_target().ToString());
}
@@ -4200,11 +3433,8 @@ class OcclusionTrackerTestDontReduceOcclusionIfBackgroundFilterIsOccluded
// The filter is completely occluded, so it should not blur anything and
// reduce any occlusion.
gfx::Rect occlusion_above_surface = gfx::Rect(50, 50, 50, 50);
- gfx::Rect occlusion_above_replica = gfx::Rect(200, 50, 50, 50);
- Region expected_opaque_region =
- UnionRegions(occlusion_above_surface, occlusion_above_replica);
- EXPECT_EQ(expected_opaque_region.ToString(),
+ EXPECT_EQ(occlusion_above_surface.ToString(),
occlusion.occlusion_from_inside_target().ToString());
EXPECT_EQ(gfx::Rect().ToString(),
occlusion.occlusion_from_outside_target().ToString());
@@ -4381,379 +3611,6 @@ class OcclusionTrackerTestMinimumTrackingSize
ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestMinimumTrackingSize);
template <class Types>
-class OcclusionTrackerTestViewportClipIsExternalOcclusion
- : public OcclusionTrackerTest<Types> {
- protected:
- explicit OcclusionTrackerTestViewportClipIsExternalOcclusion(
- bool opaque_layers)
- : OcclusionTrackerTest<Types>(opaque_layers) {}
- void RunMyTest() {
- typename Types::ContentLayerType* parent = this->CreateRoot(
- this->identity_matrix, gfx::PointF(), gfx::Size(400, 400));
- typename Types::LayerType* small =
- this->CreateDrawingSurface(parent,
- this->identity_matrix,
- gfx::PointF(),
- gfx::Size(200, 200),
- false);
- typename Types::LayerType* large =
- this->CreateDrawingLayer(small,
- this->identity_matrix,
- gfx::PointF(),
- gfx::Size(400, 400),
- false);
- small->SetMasksToBounds(true);
- this->CalcDrawEtc(parent);
-
- TestOcclusionTrackerWithClip<typename Types::LayerType,
- typename Types::RenderSurfaceType> occlusion(
- gfx::Rect(0, 0, 100, 100));
-
- this->EnterLayer(large, &occlusion, false);
-
- bool has_occlusion_from_outside_target_surface = false;
- EXPECT_RECT_EQ(gfx::Rect(0, 0, 100, 100),
- occlusion.UnoccludedLayerContentRect(
- large,
- gfx::Rect(0, 0, 400, 400),
- &has_occlusion_from_outside_target_surface));
- EXPECT_TRUE(has_occlusion_from_outside_target_surface);
-
- has_occlusion_from_outside_target_surface = false;
- EXPECT_FALSE(
- occlusion.OccludedLayer(large,
- gfx::Rect(0, 0, 400, 400),
- &has_occlusion_from_outside_target_surface));
- EXPECT_TRUE(has_occlusion_from_outside_target_surface);
-
- this->LeaveLayer(large, &occlusion);
- this->VisitLayer(small, &occlusion);
-
- has_occlusion_from_outside_target_surface = false;
- EXPECT_RECT_EQ(gfx::Rect(0, 0, 100, 100),
- occlusion.UnoccludedLayerContentRect(
- small,
- gfx::Rect(0, 0, 200, 200),
- &has_occlusion_from_outside_target_surface));
- EXPECT_TRUE(has_occlusion_from_outside_target_surface);
-
- has_occlusion_from_outside_target_surface = false;
- EXPECT_FALSE(
- occlusion.OccludedLayer(small,
- gfx::Rect(0, 0, 200, 200),
- &has_occlusion_from_outside_target_surface));
- EXPECT_TRUE(has_occlusion_from_outside_target_surface);
-
- this->EnterContributingSurface(small, &occlusion, false);
-
- has_occlusion_from_outside_target_surface = false;
- EXPECT_RECT_EQ(gfx::Rect(0, 0, 100, 100),
- occlusion.UnoccludedContributingSurfaceContentRect(
- small,
- false,
- gfx::Rect(0, 0, 200, 200),
- &has_occlusion_from_outside_target_surface));
- EXPECT_TRUE(has_occlusion_from_outside_target_surface);
- }
-};
-
-ALL_OCCLUSIONTRACKER_TEST(
- OcclusionTrackerTestViewportClipIsExternalOcclusion)
-
-template <class Types>
-class OcclusionTrackerTestLayerClipIsExternalOcclusion
- : public OcclusionTrackerTest<Types> {
- protected:
- explicit OcclusionTrackerTestLayerClipIsExternalOcclusion(bool opaque_layers)
- : OcclusionTrackerTest<Types>(opaque_layers) {}
- void RunMyTest() {
- typename Types::ContentLayerType* parent = this->CreateRoot(
- this->identity_matrix, gfx::PointF(), gfx::Size(400, 400));
- typename Types::LayerType* smallest = this->CreateDrawingLayer(
- parent, this->identity_matrix, gfx::PointF(), gfx::Size(50, 50), false);
- typename Types::LayerType* smaller =
- this->CreateDrawingSurface(smallest,
- this->identity_matrix,
- gfx::PointF(),
- gfx::Size(100, 100),
- false);
- typename Types::LayerType* small =
- this->CreateDrawingSurface(smaller,
- this->identity_matrix,
- gfx::PointF(),
- gfx::Size(200, 200),
- false);
- typename Types::LayerType* large =
- this->CreateDrawingLayer(small,
- this->identity_matrix,
- gfx::PointF(),
- gfx::Size(400, 400),
- false);
- smallest->SetMasksToBounds(true);
- smaller->SetMasksToBounds(true);
- small->SetMasksToBounds(true);
- this->CalcDrawEtc(parent);
-
- TestOcclusionTrackerWithClip<typename Types::LayerType,
- typename Types::RenderSurfaceType> occlusion(
- gfx::Rect(0, 0, 1000, 1000));
-
- this->EnterLayer(large, &occlusion, false);
-
- // Clipping from the smaller layer is from outside the target surface.
- bool has_occlusion_from_outside_target_surface = false;
- EXPECT_RECT_EQ(gfx::Rect(0, 0, 100, 100),
- occlusion.UnoccludedLayerContentRect(
- large,
- gfx::Rect(0, 0, 400, 400),
- &has_occlusion_from_outside_target_surface));
- EXPECT_TRUE(has_occlusion_from_outside_target_surface);
-
- has_occlusion_from_outside_target_surface = false;
- EXPECT_FALSE(
- occlusion.OccludedLayer(large,
- gfx::Rect(0, 0, 400, 400),
- &has_occlusion_from_outside_target_surface));
- EXPECT_TRUE(has_occlusion_from_outside_target_surface);
-
- this->LeaveLayer(large, &occlusion);
- this->VisitLayer(small, &occlusion);
-
- // Clipping from the smaller layer is from outside the target surface.
- has_occlusion_from_outside_target_surface = false;
- EXPECT_RECT_EQ(gfx::Rect(0, 0, 100, 100),
- occlusion.UnoccludedLayerContentRect(
- small,
- gfx::Rect(0, 0, 200, 200),
- &has_occlusion_from_outside_target_surface));
- EXPECT_TRUE(has_occlusion_from_outside_target_surface);
-
- has_occlusion_from_outside_target_surface = false;
- EXPECT_FALSE(
- occlusion.OccludedLayer(small,
- gfx::Rect(0, 0, 200, 200),
- &has_occlusion_from_outside_target_surface));
- EXPECT_TRUE(has_occlusion_from_outside_target_surface);
-
- this->EnterContributingSurface(small, &occlusion, false);
-
- // The |small| surface is clipped from outside its target by |smallest|.
- has_occlusion_from_outside_target_surface = false;
- EXPECT_RECT_EQ(gfx::Rect(0, 0, 50, 50),
- occlusion.UnoccludedContributingSurfaceContentRect(
- small,
- false,
- gfx::Rect(0, 0, 200, 200),
- &has_occlusion_from_outside_target_surface));
- EXPECT_TRUE(has_occlusion_from_outside_target_surface);
-
- this->LeaveContributingSurface(small, &occlusion);
- this->VisitLayer(smaller, &occlusion);
- this->EnterContributingSurface(smaller, &occlusion, false);
-
- // The |smaller| surface is clipped from inside its target by |smallest|.
- has_occlusion_from_outside_target_surface = false;
- EXPECT_RECT_EQ(gfx::Rect(0, 0, 50, 50),
- occlusion.UnoccludedContributingSurfaceContentRect(
- smaller,
- false,
- gfx::Rect(0, 0, 100, 100),
- &has_occlusion_from_outside_target_surface));
- EXPECT_FALSE(has_occlusion_from_outside_target_surface);
- }
-};
-
-ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestLayerClipIsExternalOcclusion)
-
-template <class Types>
-class OcclusionTrackerTestPreventOcclusionOnLayer
- : public OcclusionTrackerTest<Types> {
- protected:
- explicit OcclusionTrackerTestPreventOcclusionOnLayer(bool opaque_layers)
- : OcclusionTrackerTest<Types>(opaque_layers) {}
- void RunMyTest() {
- typename Types::ContentLayerType* parent = this->CreateRoot(
- this->identity_matrix, gfx::PointF(), gfx::Size(400, 400));
- typename Types::LayerType* unprevented = this->CreateDrawingLayer(
- parent, this->identity_matrix, gfx::PointF(), gfx::Size(50, 50), false);
- typename Types::LayerType* prevented = this->CreateDrawingLayer(
- parent, this->identity_matrix, gfx::PointF(), gfx::Size(50, 50), false);
- typename Types::LayerType* occluding = this->CreateDrawingLayer(
- parent, this->identity_matrix, gfx::PointF(), gfx::Size(50, 50), true);
- this->CalcDrawEtc(parent);
-
- TestOcclusionTrackerWithClip<typename Types::LayerType,
- typename Types::RenderSurfaceType> occlusion(
- gfx::Rect(0, 0, 1000, 1000));
- bool external_occlusion = false;
-
- this->VisitLayer(occluding, &occlusion);
- this->EnterLayer(prevented, &occlusion, true);
-
- // This layer is not occluded because it is prevented.
- EXPECT_FALSE(occlusion.OccludedLayer(prevented,
- gfx::Rect(50, 50),
- &external_occlusion));
- EXPECT_FALSE(external_occlusion);
-
- EXPECT_EQ(gfx::Rect(50, 50).ToString(),
- occlusion.UnoccludedLayerContentRect(
- prevented,
- gfx::Rect(50, 50),
- &external_occlusion).ToString());
- EXPECT_FALSE(external_occlusion);
-
- this->LeaveLayer(prevented, &occlusion);
- this->EnterLayer(unprevented, &occlusion, false);
-
- // This layer is fully occluded.
- EXPECT_TRUE(occlusion.OccludedLayer(unprevented,
- gfx::Rect(50, 50),
- &external_occlusion));
- EXPECT_FALSE(external_occlusion);
-
- EXPECT_EQ(gfx::Rect().ToString(),
- occlusion.UnoccludedLayerContentRect(
- unprevented,
- gfx::Rect(50, 50),
- &external_occlusion).ToString());
- EXPECT_FALSE(external_occlusion);
-
- this->LeaveLayer(unprevented, &occlusion);
- }
-};
-
-ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestPreventOcclusionOnLayer)
-
-template <class Types>
-class OcclusionTrackerTestPreventOcclusionOnContributingSurface
- : public OcclusionTrackerTest<Types> {
- protected:
- explicit OcclusionTrackerTestPreventOcclusionOnContributingSurface(
- bool opaque_layers)
- : OcclusionTrackerTest<Types>(opaque_layers) {}
- void RunMyTest() {
- typename Types::ContentLayerType* parent = this->CreateRoot(
- this->identity_matrix, gfx::PointF(), gfx::Size(400, 400));
- typename Types::LayerType* unprevented = this->CreateDrawingSurface(
- parent, this->identity_matrix, gfx::PointF(), gfx::Size(50, 50), false);
- typename Types::LayerType* prevented = this->CreateDrawingSurface(
- parent, this->identity_matrix, gfx::PointF(), gfx::Size(50, 50), false);
- typename Types::LayerType* occluding = this->CreateDrawingLayer(
- parent, this->identity_matrix, gfx::PointF(), gfx::Size(50, 50), true);
- this->CalcDrawEtc(parent);
-
- TestOcclusionTrackerWithClip<typename Types::LayerType,
- typename Types::RenderSurfaceType> occlusion(
- gfx::Rect(0, 0, 1000, 1000));
- bool external_occlusion = false;
-
- this->VisitLayer(occluding, &occlusion);
- this->EnterLayer(prevented, &occlusion, true);
-
- // This layer is not occluded because it is prevented.
- EXPECT_EQ(gfx::Rect(50, 50).ToString(),
- occlusion.UnoccludedLayerContentRect(
- prevented,
- gfx::Rect(50, 50),
- &external_occlusion).ToString());
- EXPECT_FALSE(external_occlusion);
-
- this->LeaveLayer(prevented, &occlusion);
- this->EnterContributingSurface(prevented, &occlusion, true);
-
- // This contributing surface is not occluded because it is prevented.
- EXPECT_EQ(gfx::Rect(50, 50).ToString(),
- occlusion.UnoccludedContributingSurfaceContentRect(
- prevented,
- false, // is_replica
- gfx::Rect(50, 50),
- &external_occlusion).ToString());
- EXPECT_FALSE(external_occlusion);
-
- this->LeaveContributingSurface(prevented, &occlusion);
- this->EnterLayer(unprevented, &occlusion, false);
-
- // This layer is fully occluded from outside its surface.
- EXPECT_EQ(gfx::Rect().ToString(),
- occlusion.UnoccludedLayerContentRect(
- unprevented,
- gfx::Rect(50, 50),
- &external_occlusion).ToString());
- EXPECT_TRUE(external_occlusion);
-
- this->LeaveLayer(unprevented, &occlusion);
- this->EnterContributingSurface(unprevented, &occlusion, false);
-
- // This contributing surface is fully occluded.
- EXPECT_EQ(gfx::Rect().ToString(),
- occlusion.UnoccludedContributingSurfaceContentRect(
- unprevented,
- false, // is_replica
- gfx::Rect(50, 50),
- &external_occlusion).ToString());
- EXPECT_FALSE(external_occlusion);
-
- this->LeaveContributingSurface(unprevented, &occlusion);
- }
-};
-
-ALL_OCCLUSIONTRACKER_TEST(
- OcclusionTrackerTestPreventOcclusionOnContributingSurface)
-
-template <class Types>
-class OcclusionTrackerTestPreventOcclusionByClipping
- : public OcclusionTrackerTest<Types> {
- protected:
- explicit OcclusionTrackerTestPreventOcclusionByClipping(bool opaque_layers)
- : OcclusionTrackerTest<Types>(opaque_layers) {}
- void RunMyTest() {
- typename Types::ContentLayerType* parent = this->CreateRoot(
- this->identity_matrix, gfx::PointF(), gfx::Size(400, 400));
- typename Types::LayerType* unprevented = this->CreateDrawingLayer(
- parent, this->identity_matrix, gfx::PointF(), gfx::Size(50, 50), false);
- typename Types::LayerType* prevented = this->CreateDrawingLayer(
- parent, this->identity_matrix, gfx::PointF(), gfx::Size(50, 50), false);
- this->CalcDrawEtc(parent);
-
- TestOcclusionTrackerWithClip<typename Types::LayerType,
- typename Types::RenderSurfaceType> occlusion(
- gfx::Rect(0, 0, 10, 10));
- bool external_occlusion = false;
-
- this->EnterLayer(prevented, &occlusion, true);
-
- // This layer is not occluded because it is prevented.
- EXPECT_FALSE(occlusion.OccludedLayer(prevented,
- gfx::Rect(50, 50),
- &external_occlusion));
- EXPECT_FALSE(external_occlusion);
-
- EXPECT_EQ(gfx::Rect(50, 50).ToString(),
- occlusion.UnoccludedLayerContentRect(
- prevented,
- gfx::Rect(50, 50),
- &external_occlusion).ToString());
- EXPECT_FALSE(external_occlusion);
-
- this->LeaveLayer(prevented, &occlusion);
- this->EnterLayer(unprevented, &occlusion, false);
-
- // This layer is clipped by the screen space clip rect.
- EXPECT_EQ(gfx::Rect(10, 10).ToString(),
- occlusion.UnoccludedLayerContentRect(
- unprevented,
- gfx::Rect(50, 50),
- &external_occlusion).ToString());
- EXPECT_TRUE(external_occlusion);
-
- this->LeaveLayer(unprevented, &occlusion);
- }
-};
-
-ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestPreventOcclusionByClipping)
-
-template <class Types>
class OcclusionTrackerTestScaledLayerIsClipped
: public OcclusionTrackerTest<Types> {
protected:
@@ -4929,5 +3786,37 @@ class OcclusionTrackerTestHiddenCopyRequestDoesNotOcclude
ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestHiddenCopyRequestDoesNotOcclude)
+template <class Types>
+class OcclusionTrackerTestEmptyEventLayerDoesNotOcclude
+ : public OcclusionTrackerTest<Types> {
+ protected:
+ explicit OcclusionTrackerTestEmptyEventLayerDoesNotOcclude(
+ bool opaque_layers)
+ : OcclusionTrackerTest<Types>(opaque_layers) {}
+ void RunMyTest() {
+ typename Types::ContentLayerType* root = this->CreateRoot(
+ this->identity_matrix, gfx::Point(), gfx::Size(400, 400));
+ typename Types::ContentLayerType* empty_layer = this->CreateDrawingLayer(
+ root, this->identity_matrix, gfx::Point(), gfx::Size(200, 200), true);
+ this->SetDrawsContent(empty_layer, false);
+ empty_layer->SetTouchEventHandlerRegion(gfx::Rect(10, 10, 10, 10));
+
+ this->CalcDrawEtc(root);
+
+ TestOcclusionTrackerWithClip<typename Types::LayerType,
+ typename Types::RenderSurfaceType> occlusion(
+ gfx::Rect(0, 0, 1000, 1000), false);
+
+ this->VisitLayer(empty_layer, &occlusion);
+
+ EXPECT_EQ(gfx::Rect().ToString(),
+ occlusion.occlusion_from_outside_target().ToString());
+ EXPECT_EQ(gfx::Rect().ToString(),
+ occlusion.occlusion_from_inside_target().ToString());
+ }
+};
+
+ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestEmptyEventLayerDoesNotOcclude)
+
} // namespace
} // namespace cc
diff --git a/chromium/cc/trees/proxy.h b/chromium/cc/trees/proxy.h
index 84844c89497..69975a6dd7f 100644
--- a/chromium/cc/trees/proxy.h
+++ b/chromium/cc/trees/proxy.h
@@ -81,6 +81,7 @@ class CC_EXPORT Proxy {
virtual void MainThreadHasStoppedFlinging() = 0;
virtual bool CommitRequested() const = 0;
+ virtual bool BeginMainFrameRequested() const = 0;
// Must be called before using the proxy.
virtual void Start(scoped_ptr<OutputSurface> first_output_surface) = 0;
diff --git a/chromium/cc/trees/quad_culler.cc b/chromium/cc/trees/quad_culler.cc
index 760c79dad8d..2fc8aaa6caa 100644
--- a/chromium/cc/trees/quad_culler.cc
+++ b/chromium/cc/trees/quad_culler.cc
@@ -84,29 +84,19 @@ bool QuadCuller::Append(scoped_ptr<DrawQuad> draw_quad,
DCHECK(shared_quad_state_list_->back() == current_shared_quad_state_);
gfx::Rect culled_rect;
- bool has_occlusion_from_outside_target_surface;
bool impl_draw_transform_is_unknown = false;
if (for_surface_) {
culled_rect = occlusion_tracker_.UnoccludedContributingSurfaceContentRect(
- layer_,
- false,
- draw_quad->rect,
- &has_occlusion_from_outside_target_surface);
+ layer_, false, draw_quad->visible_rect);
} else {
culled_rect = occlusion_tracker_.UnoccludedContentRect(
layer_->render_target(),
- draw_quad->rect,
+ draw_quad->visible_rect,
draw_quad->quadTransform(),
- impl_draw_transform_is_unknown,
- draw_quad->isClipped(),
- draw_quad->clipRect(),
- &has_occlusion_from_outside_target_surface);
+ impl_draw_transform_is_unknown);
}
- append_quads_data->had_occlusion_from_outside_target_surface |=
- has_occlusion_from_outside_target_surface;
-
return AppendQuadInternal(draw_quad.Pass(),
culled_rect,
quad_list_,
diff --git a/chromium/cc/trees/quad_culler_unittest.cc b/chromium/cc/trees/quad_culler_unittest.cc
index 120e0072087..c07a0a79e04 100644
--- a/chromium/cc/trees/quad_culler_unittest.cc
+++ b/chromium/cc/trees/quad_culler_unittest.cc
@@ -11,10 +11,13 @@
#include "cc/layers/append_quads_data.h"
#include "cc/layers/render_surface_impl.h"
#include "cc/layers/tiled_layer_impl.h"
+#include "cc/quads/render_pass_draw_quad.h"
+#include "cc/quads/solid_color_draw_quad.h"
#include "cc/quads/tile_draw_quad.h"
#include "cc/resources/layer_tiling_data.h"
#include "cc/test/fake_impl_proxy.h"
#include "cc/test/fake_layer_tree_host_impl.h"
+#include "cc/test/occlusion_tracker_test_common.h"
#include "cc/trees/occlusion_tracker.h"
#include "cc/trees/single_thread_proxy.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -24,22 +27,15 @@
namespace cc {
namespace {
-class TestOcclusionTrackerImpl : public OcclusionTrackerImpl {
+class TestOcclusionTrackerImpl
+ : public TestOcclusionTrackerBase<LayerImpl, RenderSurfaceImpl> {
public:
TestOcclusionTrackerImpl(gfx::Rect scissor_rect_in_screen,
bool record_metrics_for_frame = true)
- : OcclusionTrackerImpl(scissor_rect_in_screen, record_metrics_for_frame),
- scissor_rect_in_screen_(scissor_rect_in_screen) {}
-
- protected:
- virtual gfx::Rect LayerScissorRectInTargetSurface(
- const LayerImpl* layer) const {
- return scissor_rect_in_screen_;
- }
+ : TestOcclusionTrackerBase(scissor_rect_in_screen,
+ record_metrics_for_frame) {}
private:
- gfx::Rect scissor_rect_in_screen_;
-
DISALLOW_COPY_AND_ASSIGN(TestOcclusionTrackerImpl);
};
@@ -54,14 +50,13 @@ class QuadCullerTest : public testing::Test {
: host_impl_(&proxy_),
layer_id_(1) {}
- scoped_ptr<TiledLayerImpl> MakeLayer(
- TiledLayerImpl* parent,
- const gfx::Transform& draw_transform,
- gfx::Rect layer_rect,
- float opacity,
- bool opaque,
- gfx::Rect layer_opaque_rect,
- LayerImplList& surface_layer_list) {
+ scoped_ptr<TiledLayerImpl> MakeLayer(TiledLayerImpl* parent,
+ const gfx::Transform& draw_transform,
+ gfx::Rect layer_rect,
+ float opacity,
+ bool opaque,
+ gfx::Rect layer_opaque_rect,
+ LayerImplList& surface_layer_list) {
scoped_ptr<TiledLayerImpl> layer =
TiledLayerImpl::Create(host_impl_.active_tree(), layer_id_++);
scoped_ptr<LayerTilingData> tiler = LayerTilingData::Create(
@@ -69,6 +64,7 @@ class QuadCullerTest : public testing::Test {
tiler->SetBounds(layer_rect.size());
layer->SetTilingData(*tiler);
layer->set_skips_draw(false);
+ layer->SetDrawsContent(true);
layer->draw_properties().target_space_transform = draw_transform;
layer->draw_properties().screen_space_transform = draw_transform;
layer->draw_properties().visible_content_rect = layer_rect;
@@ -112,7 +108,7 @@ class QuadCullerTest : public testing::Test {
TiledLayerImpl* layer,
LayerIteratorType* it,
OcclusionTrackerImpl* occlusion_tracker) {
- occlusion_tracker->EnterLayer(*it, false);
+ occlusion_tracker->EnterLayer(*it);
QuadCuller quad_culler(
quad_list, shared_state_list, layer, *occlusion_tracker, false, false);
AppendQuadsData data;
@@ -126,6 +122,7 @@ class QuadCullerTest : public testing::Test {
FakeLayerTreeHostImpl host_impl_;
int layer_id_;
+ private:
DISALLOW_COPY_AND_ASSIGN(QuadCullerTest);
};
@@ -139,21 +136,20 @@ class QuadCullerTest : public testing::Test {
gfx::Size child_size = gfx::Size(200, 200); \
gfx::Rect child_rect = gfx::Rect(child_size);
-TEST_F(QuadCullerTest, VerifyNoCulling) {
+TEST_F(QuadCullerTest, NoCulling) {
DECLARE_AND_INITIALIZE_TEST_QUADS();
- scoped_ptr<TiledLayerImpl> root_layer =
- MakeLayer(NULL,
- gfx::Transform(),
- root_rect,
- 1,
- true,
- gfx::Rect(),
- render_surface_layer_list);
+ scoped_ptr<TiledLayerImpl> root_layer = MakeLayer(NULL,
+ gfx::Transform(),
+ root_rect,
+ 1.f,
+ true,
+ gfx::Rect(),
+ render_surface_layer_list);
scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
gfx::Transform(),
child_rect,
- 1,
+ 1.f,
false,
gfx::Rect(),
render_surface_layer_list);
@@ -170,7 +166,7 @@ TEST_F(QuadCullerTest, VerifyNoCulling) {
root_layer.get(),
&it,
&occlusion_tracker);
- EXPECT_EQ(quad_list.size(), 13u);
+ EXPECT_EQ(13u, quad_list.size());
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_opaque(), 90000, 1);
EXPECT_NEAR(occlusion_tracker.overdraw_metrics()->pixels_drawn_translucent(),
@@ -180,21 +176,20 @@ TEST_F(QuadCullerTest, VerifyNoCulling) {
occlusion_tracker.overdraw_metrics()->pixels_culled_for_drawing(), 0, 1);
}
-TEST_F(QuadCullerTest, VerifyCullChildLinesUpTopLeft) {
+TEST_F(QuadCullerTest, CullChildLinesUpTopLeft) {
DECLARE_AND_INITIALIZE_TEST_QUADS();
- scoped_ptr<TiledLayerImpl> root_layer =
- MakeLayer(NULL,
- gfx::Transform(),
- root_rect,
- 1,
- true,
- gfx::Rect(),
- render_surface_layer_list);
+ scoped_ptr<TiledLayerImpl> root_layer = MakeLayer(NULL,
+ gfx::Transform(),
+ root_rect,
+ 1.f,
+ true,
+ gfx::Rect(),
+ render_surface_layer_list);
scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
gfx::Transform(),
child_rect,
- 1,
+ 1.f,
true,
gfx::Rect(),
render_surface_layer_list);
@@ -211,7 +206,7 @@ TEST_F(QuadCullerTest, VerifyCullChildLinesUpTopLeft) {
root_layer.get(),
&it,
&occlusion_tracker);
- EXPECT_EQ(quad_list.size(), 9u);
+ EXPECT_EQ(9u, quad_list.size());
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_opaque(), 90000, 1);
EXPECT_NEAR(
@@ -221,17 +216,16 @@ TEST_F(QuadCullerTest, VerifyCullChildLinesUpTopLeft) {
1);
}
-TEST_F(QuadCullerTest, VerifyCullWhenChildOpacityNotOne) {
+TEST_F(QuadCullerTest, CullWhenChildOpacityNotOne) {
DECLARE_AND_INITIALIZE_TEST_QUADS();
- scoped_ptr<TiledLayerImpl> root_layer =
- MakeLayer(NULL,
- gfx::Transform(),
- root_rect,
- 1,
- true,
- gfx::Rect(),
- render_surface_layer_list);
+ scoped_ptr<TiledLayerImpl> root_layer = MakeLayer(NULL,
+ gfx::Transform(),
+ root_rect,
+ 1.f,
+ true,
+ gfx::Rect(),
+ render_surface_layer_list);
scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
child_transform,
child_rect,
@@ -252,7 +246,7 @@ TEST_F(QuadCullerTest, VerifyCullWhenChildOpacityNotOne) {
root_layer.get(),
&it,
&occlusion_tracker);
- EXPECT_EQ(quad_list.size(), 13u);
+ EXPECT_EQ(13u, quad_list.size());
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_opaque(), 90000, 1);
EXPECT_NEAR(occlusion_tracker.overdraw_metrics()->pixels_drawn_translucent(),
@@ -262,21 +256,20 @@ TEST_F(QuadCullerTest, VerifyCullWhenChildOpacityNotOne) {
occlusion_tracker.overdraw_metrics()->pixels_culled_for_drawing(), 0, 1);
}
-TEST_F(QuadCullerTest, VerifyCullWhenChildOpaqueFlagFalse) {
+TEST_F(QuadCullerTest, CullWhenChildOpaqueFlagFalse) {
DECLARE_AND_INITIALIZE_TEST_QUADS();
- scoped_ptr<TiledLayerImpl> root_layer =
- MakeLayer(NULL,
- gfx::Transform(),
- root_rect,
- 1,
- true,
- gfx::Rect(),
- render_surface_layer_list);
+ scoped_ptr<TiledLayerImpl> root_layer = MakeLayer(NULL,
+ gfx::Transform(),
+ root_rect,
+ 1.f,
+ true,
+ gfx::Rect(),
+ render_surface_layer_list);
scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
child_transform,
child_rect,
- 1,
+ 1.f,
false,
gfx::Rect(),
render_surface_layer_list);
@@ -293,7 +286,7 @@ TEST_F(QuadCullerTest, VerifyCullWhenChildOpaqueFlagFalse) {
root_layer.get(),
&it,
&occlusion_tracker);
- EXPECT_EQ(quad_list.size(), 13u);
+ EXPECT_EQ(13u, quad_list.size());
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_opaque(), 90000, 1);
EXPECT_NEAR(occlusion_tracker.overdraw_metrics()->pixels_drawn_translucent(),
@@ -303,21 +296,21 @@ TEST_F(QuadCullerTest, VerifyCullWhenChildOpaqueFlagFalse) {
occlusion_tracker.overdraw_metrics()->pixels_culled_for_drawing(), 0, 1);
}
-TEST_F(QuadCullerTest, VerifyCullCenterTileOnly) {
+TEST_F(QuadCullerTest, CullCenterTileOnly) {
DECLARE_AND_INITIALIZE_TEST_QUADS();
child_transform.Translate(50, 50);
scoped_ptr<TiledLayerImpl> root_layer = MakeLayer(NULL,
gfx::Transform(),
root_rect,
- 1,
+ 1.f,
true,
gfx::Rect(),
render_surface_layer_list);
scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
child_transform,
child_rect,
- 1,
+ 1.f,
true,
gfx::Rect(),
render_surface_layer_list);
@@ -337,19 +330,19 @@ TEST_F(QuadCullerTest, VerifyCullCenterTileOnly) {
ASSERT_EQ(quad_list.size(), 12u);
gfx::Rect quad_visible_rect1 = quad_list[5]->visible_rect;
- EXPECT_EQ(quad_visible_rect1.height(), 50);
+ EXPECT_EQ(50, quad_visible_rect1.height());
gfx::Rect quad_visible_rect3 = quad_list[7]->visible_rect;
- EXPECT_EQ(quad_visible_rect3.width(), 50);
+ EXPECT_EQ(50, quad_visible_rect3.width());
// Next index is 8, not 9, since centre quad culled.
gfx::Rect quad_visible_rect4 = quad_list[8]->visible_rect;
- EXPECT_EQ(quad_visible_rect4.width(), 50);
- EXPECT_EQ(quad_visible_rect4.x(), 250);
+ EXPECT_EQ(50, quad_visible_rect4.width());
+ EXPECT_EQ(250, quad_visible_rect4.x());
gfx::Rect quad_visible_rect6 = quad_list[10]->visible_rect;
- EXPECT_EQ(quad_visible_rect6.height(), 50);
- EXPECT_EQ(quad_visible_rect6.y(), 250);
+ EXPECT_EQ(50, quad_visible_rect6.height());
+ EXPECT_EQ(250, quad_visible_rect6.y());
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_opaque(), 100000, 1);
@@ -360,7 +353,7 @@ TEST_F(QuadCullerTest, VerifyCullCenterTileOnly) {
1);
}
-TEST_F(QuadCullerTest, VerifyCullCenterTileNonIntegralSize1) {
+TEST_F(QuadCullerTest, CullCenterTileNonIntegralSize1) {
DECLARE_AND_INITIALIZE_TEST_QUADS();
child_transform.Translate(100, 100);
@@ -368,22 +361,22 @@ TEST_F(QuadCullerTest, VerifyCullCenterTileNonIntegralSize1) {
// Make the root layer's quad have extent (99.1, 99.1) -> (200.9, 200.9) to
// make sure it doesn't get culled due to transform rounding.
gfx::Transform root_transform;
- root_transform.Translate(99.1, 99.1);
- root_transform.Scale(1.018, 1.018);
+ root_transform.Translate(99.1f, 99.1f);
+ root_transform.Scale(1.018f, 1.018f);
root_rect = child_rect = gfx::Rect(0, 0, 100, 100);
scoped_ptr<TiledLayerImpl> root_layer = MakeLayer(NULL,
root_transform,
root_rect,
- 1,
+ 1.f,
true,
gfx::Rect(),
render_surface_layer_list);
scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
child_transform,
child_rect,
- 1,
+ 1.f,
true,
gfx::Rect(),
render_surface_layer_list);
@@ -400,7 +393,7 @@ TEST_F(QuadCullerTest, VerifyCullCenterTileNonIntegralSize1) {
root_layer.get(),
&it,
&occlusion_tracker);
- EXPECT_EQ(quad_list.size(), 2u);
+ EXPECT_EQ(2u, quad_list.size());
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_opaque(), 20363, 1);
@@ -410,14 +403,14 @@ TEST_F(QuadCullerTest, VerifyCullCenterTileNonIntegralSize1) {
occlusion_tracker.overdraw_metrics()->pixels_culled_for_drawing(), 0, 1);
}
-TEST_F(QuadCullerTest, VerifyCullCenterTileNonIntegralSize2) {
+TEST_F(QuadCullerTest, CullCenterTileNonIntegralSize2) {
DECLARE_AND_INITIALIZE_TEST_QUADS();
// Make the child's quad slightly smaller than, and centred over, the root
// layer tile. Verify the child does not cause the quad below to be culled
// due to rounding.
- child_transform.Translate(100.1, 100.1);
- child_transform.Scale(0.982, 0.982);
+ child_transform.Translate(100.1f, 100.1f);
+ child_transform.Scale(0.982f, 0.982f);
gfx::Transform root_transform;
root_transform.Translate(100, 100);
@@ -427,14 +420,14 @@ TEST_F(QuadCullerTest, VerifyCullCenterTileNonIntegralSize2) {
scoped_ptr<TiledLayerImpl> root_layer = MakeLayer(NULL,
root_transform,
root_rect,
- 1,
+ 1.f,
true,
gfx::Rect(),
render_surface_layer_list);
scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
child_transform,
child_rect,
- 1,
+ 1.f,
true,
gfx::Rect(),
render_surface_layer_list);
@@ -451,7 +444,7 @@ TEST_F(QuadCullerTest, VerifyCullCenterTileNonIntegralSize2) {
root_layer.get(),
&it,
&occlusion_tracker);
- EXPECT_EQ(quad_list.size(), 2u);
+ EXPECT_EQ(2u, quad_list.size());
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_opaque(), 19643, 1);
@@ -461,21 +454,21 @@ TEST_F(QuadCullerTest, VerifyCullCenterTileNonIntegralSize2) {
occlusion_tracker.overdraw_metrics()->pixels_culled_for_drawing(), 0, 1);
}
-TEST_F(QuadCullerTest, VerifyCullChildLinesUpBottomRight) {
+TEST_F(QuadCullerTest, CullChildLinesUpBottomRight) {
DECLARE_AND_INITIALIZE_TEST_QUADS();
child_transform.Translate(100, 100);
scoped_ptr<TiledLayerImpl> root_layer = MakeLayer(NULL,
gfx::Transform(),
root_rect,
- 1,
+ 1.f,
true,
gfx::Rect(),
render_surface_layer_list);
scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
child_transform,
child_rect,
- 1,
+ 1.f,
true,
gfx::Rect(),
render_surface_layer_list);
@@ -492,7 +485,7 @@ TEST_F(QuadCullerTest, VerifyCullChildLinesUpBottomRight) {
root_layer.get(),
&it,
&occlusion_tracker);
- EXPECT_EQ(quad_list.size(), 9u);
+ EXPECT_EQ(9u, quad_list.size());
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_opaque(), 90000, 1);
EXPECT_NEAR(
@@ -502,14 +495,14 @@ TEST_F(QuadCullerTest, VerifyCullChildLinesUpBottomRight) {
1);
}
-TEST_F(QuadCullerTest, VerifyCullSubRegion) {
+TEST_F(QuadCullerTest, CullSubRegion) {
DECLARE_AND_INITIALIZE_TEST_QUADS();
child_transform.Translate(50, 50);
scoped_ptr<TiledLayerImpl> root_layer = MakeLayer(NULL,
gfx::Transform(),
root_rect,
- 1,
+ 1.f,
true,
gfx::Rect(),
render_surface_layer_list);
@@ -520,7 +513,7 @@ TEST_F(QuadCullerTest, VerifyCullSubRegion) {
scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
child_transform,
child_rect,
- 1,
+ 1.f,
false,
child_opaque_rect,
render_surface_layer_list);
@@ -537,7 +530,7 @@ TEST_F(QuadCullerTest, VerifyCullSubRegion) {
root_layer.get(),
&it,
&occlusion_tracker);
- EXPECT_EQ(quad_list.size(), 12u);
+ EXPECT_EQ(12u, quad_list.size());
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_opaque(), 90000, 1);
EXPECT_NEAR(occlusion_tracker.overdraw_metrics()->pixels_drawn_translucent(),
@@ -548,14 +541,14 @@ TEST_F(QuadCullerTest, VerifyCullSubRegion) {
1);
}
-TEST_F(QuadCullerTest, VerifyCullSubRegion2) {
+TEST_F(QuadCullerTest, CullSubRegion2) {
DECLARE_AND_INITIALIZE_TEST_QUADS();
child_transform.Translate(50, 10);
scoped_ptr<TiledLayerImpl> root_layer = MakeLayer(NULL,
gfx::Transform(),
root_rect,
- 1,
+ 1.f,
true,
gfx::Rect(),
render_surface_layer_list);
@@ -566,7 +559,7 @@ TEST_F(QuadCullerTest, VerifyCullSubRegion2) {
scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
child_transform,
child_rect,
- 1,
+ 1.f,
false,
child_opaque_rect,
render_surface_layer_list);
@@ -583,7 +576,7 @@ TEST_F(QuadCullerTest, VerifyCullSubRegion2) {
root_layer.get(),
&it,
&occlusion_tracker);
- EXPECT_EQ(quad_list.size(), 12u);
+ EXPECT_EQ(12u, quad_list.size());
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_opaque(), 90000, 1);
EXPECT_NEAR(occlusion_tracker.overdraw_metrics()->pixels_drawn_translucent(),
@@ -594,14 +587,14 @@ TEST_F(QuadCullerTest, VerifyCullSubRegion2) {
1);
}
-TEST_F(QuadCullerTest, VerifyCullSubRegionCheckOvercull) {
+TEST_F(QuadCullerTest, CullSubRegionCheckOvercull) {
DECLARE_AND_INITIALIZE_TEST_QUADS();
child_transform.Translate(50, 49);
scoped_ptr<TiledLayerImpl> root_layer = MakeLayer(NULL,
gfx::Transform(),
root_rect,
- 1,
+ 1.f,
true,
gfx::Rect(),
render_surface_layer_list);
@@ -612,7 +605,7 @@ TEST_F(QuadCullerTest, VerifyCullSubRegionCheckOvercull) {
scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
child_transform,
child_rect,
- 1,
+ 1.f,
false,
child_opaque_rect,
render_surface_layer_list);
@@ -629,7 +622,7 @@ TEST_F(QuadCullerTest, VerifyCullSubRegionCheckOvercull) {
root_layer.get(),
&it,
&occlusion_tracker);
- EXPECT_EQ(quad_list.size(), 13u);
+ EXPECT_EQ(13u, quad_list.size());
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_opaque(), 90000, 1);
EXPECT_NEAR(occlusion_tracker.overdraw_metrics()->pixels_drawn_translucent(),
@@ -640,7 +633,7 @@ TEST_F(QuadCullerTest, VerifyCullSubRegionCheckOvercull) {
1);
}
-TEST_F(QuadCullerTest, VerifyNonAxisAlignedQuadsDontOcclude) {
+TEST_F(QuadCullerTest, NonAxisAlignedQuadsDontOcclude) {
DECLARE_AND_INITIALIZE_TEST_QUADS();
// Use a small rotation so as to not disturb the geometry significantly.
@@ -649,14 +642,14 @@ TEST_F(QuadCullerTest, VerifyNonAxisAlignedQuadsDontOcclude) {
scoped_ptr<TiledLayerImpl> root_layer = MakeLayer(NULL,
gfx::Transform(),
root_rect,
- 1,
+ 1.f,
true,
gfx::Rect(),
render_surface_layer_list);
scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
child_transform,
child_rect,
- 1,
+ 1.f,
true,
gfx::Rect(),
render_surface_layer_list);
@@ -673,7 +666,7 @@ TEST_F(QuadCullerTest, VerifyNonAxisAlignedQuadsDontOcclude) {
root_layer.get(),
&it,
&occlusion_tracker);
- EXPECT_EQ(quad_list.size(), 13u);
+ EXPECT_EQ(13u, quad_list.size());
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_opaque(), 130000, 1);
EXPECT_NEAR(
@@ -688,7 +681,7 @@ TEST_F(QuadCullerTest, VerifyNonAxisAlignedQuadsDontOcclude) {
// child would normally occlude, three will move (slightly) out from under the
// child layer, and one moves further under the child. Only this last tile
// should be culled.
-TEST_F(QuadCullerTest, VerifyNonAxisAlignedQuadsSafelyCulled) {
+TEST_F(QuadCullerTest, NonAxisAlignedQuadsSafelyCulled) {
DECLARE_AND_INITIALIZE_TEST_QUADS();
// Use a small rotation so as to not disturb the geometry significantly.
@@ -698,14 +691,14 @@ TEST_F(QuadCullerTest, VerifyNonAxisAlignedQuadsSafelyCulled) {
scoped_ptr<TiledLayerImpl> root_layer = MakeLayer(NULL,
parent_transform,
root_rect,
- 1,
+ 1.f,
true,
gfx::Rect(),
render_surface_layer_list);
scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
gfx::Transform(),
child_rect,
- 1,
+ 1.f,
true,
gfx::Rect(),
render_surface_layer_list);
@@ -722,7 +715,7 @@ TEST_F(QuadCullerTest, VerifyNonAxisAlignedQuadsSafelyCulled) {
root_layer.get(),
&it,
&occlusion_tracker);
- EXPECT_EQ(quad_list.size(), 12u);
+ EXPECT_EQ(12u, quad_list.size());
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_opaque(), 100600, 1);
EXPECT_NEAR(
@@ -732,24 +725,25 @@ TEST_F(QuadCullerTest, VerifyNonAxisAlignedQuadsSafelyCulled) {
1);
}
-TEST_F(QuadCullerTest, VerifyCullOutsideScissorOverTile) {
+TEST_F(QuadCullerTest, WithoutMetrics) {
DECLARE_AND_INITIALIZE_TEST_QUADS();
- scoped_ptr<TiledLayerImpl> root_layer =
- MakeLayer(NULL,
- gfx::Transform(),
- root_rect,
- 1,
- true,
- gfx::Rect(),
- render_surface_layer_list);
+ scoped_ptr<TiledLayerImpl> root_layer = MakeLayer(NULL,
+ gfx::Transform(),
+ root_rect,
+ 1.f,
+ true,
+ gfx::Rect(),
+ render_surface_layer_list);
scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
gfx::Transform(),
child_rect,
- 1,
+ 1.f,
true,
gfx::Rect(),
render_surface_layer_list);
- TestOcclusionTrackerImpl occlusion_tracker(gfx::Rect(200, 100, 100, 100));
+ bool record_metrics = false;
+ TestOcclusionTrackerImpl occlusion_tracker(gfx::Rect(-100, -100, 1000, 1000),
+ record_metrics);
LayerIteratorType it = LayerIteratorType::Begin(&render_surface_layer_list);
AppendQuads(&quad_list,
@@ -762,174 +756,163 @@ TEST_F(QuadCullerTest, VerifyCullOutsideScissorOverTile) {
root_layer.get(),
&it,
&occlusion_tracker);
- EXPECT_EQ(quad_list.size(), 1u);
- EXPECT_NEAR(
- occlusion_tracker.overdraw_metrics()->pixels_drawn_opaque(), 10000, 1);
- EXPECT_NEAR(
- occlusion_tracker.overdraw_metrics()->pixels_drawn_translucent(), 0, 1);
- EXPECT_NEAR(occlusion_tracker.overdraw_metrics()->pixels_culled_for_drawing(),
- 120000,
- 1);
+ EXPECT_EQ(9u, quad_list.size());
+ EXPECT_EQ(0.f,
+ occlusion_tracker.overdraw_metrics()->pixels_drawn_opaque());
+ EXPECT_EQ(0.f,
+ occlusion_tracker.overdraw_metrics()->pixels_drawn_translucent());
+ EXPECT_EQ(0.f,
+ occlusion_tracker.overdraw_metrics()->pixels_culled_for_drawing());
}
-TEST_F(QuadCullerTest, VerifyCullOutsideScissorOverCulledTile) {
+TEST_F(QuadCullerTest, PartialCullingNotDestroyed) {
DECLARE_AND_INITIALIZE_TEST_QUADS();
- scoped_ptr<TiledLayerImpl> root_layer =
- MakeLayer(NULL,
- gfx::Transform(),
- root_rect,
- 1,
- true,
- gfx::Rect(),
- render_surface_layer_list);
- scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
- gfx::Transform(),
- child_rect,
- 1,
- true,
- gfx::Rect(),
- render_surface_layer_list);
- TestOcclusionTrackerImpl occlusion_tracker(gfx::Rect(100, 100, 100, 100));
- LayerIteratorType it = LayerIteratorType::Begin(&render_surface_layer_list);
-
- AppendQuads(&quad_list,
- &shared_state_list,
- child_layer.get(),
- &it,
- &occlusion_tracker);
- AppendQuads(&quad_list,
- &shared_state_list,
- root_layer.get(),
- &it,
- &occlusion_tracker);
- EXPECT_EQ(quad_list.size(), 1u);
- EXPECT_NEAR(
- occlusion_tracker.overdraw_metrics()->pixels_drawn_opaque(), 10000, 1);
- EXPECT_NEAR(
- occlusion_tracker.overdraw_metrics()->pixels_drawn_translucent(), 0, 1);
- EXPECT_NEAR(occlusion_tracker.overdraw_metrics()->pixels_culled_for_drawing(),
- 120000,
- 1);
-}
-TEST_F(QuadCullerTest, VerifyCullOutsideScissorOverPartialTiles) {
- DECLARE_AND_INITIALIZE_TEST_QUADS();
- scoped_ptr<TiledLayerImpl> root_layer =
- MakeLayer(NULL,
- gfx::Transform(),
- root_rect,
- 1,
- true,
- gfx::Rect(),
- render_surface_layer_list);
- scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
+ scoped_ptr<TiledLayerImpl> dummy_layer = MakeLayer(NULL,
gfx::Transform(),
- child_rect,
- 1,
- true,
gfx::Rect(),
- render_surface_layer_list);
- TestOcclusionTrackerImpl occlusion_tracker(gfx::Rect(50, 50, 200, 200));
- LayerIteratorType it = LayerIteratorType::Begin(&render_surface_layer_list);
-
- AppendQuads(&quad_list,
- &shared_state_list,
- child_layer.get(),
- &it,
- &occlusion_tracker);
- AppendQuads(&quad_list,
- &shared_state_list,
- root_layer.get(),
- &it,
- &occlusion_tracker);
- EXPECT_EQ(quad_list.size(), 9u);
- EXPECT_NEAR(
- occlusion_tracker.overdraw_metrics()->pixels_drawn_opaque(), 40000, 1);
- EXPECT_NEAR(
- occlusion_tracker.overdraw_metrics()->pixels_drawn_translucent(), 0, 1);
- EXPECT_NEAR(occlusion_tracker.overdraw_metrics()->pixels_culled_for_drawing(),
- 90000,
- 1);
-}
-
-TEST_F(QuadCullerTest, VerifyCullOutsideScissorOverNoTiles) {
- DECLARE_AND_INITIALIZE_TEST_QUADS();
- scoped_ptr<TiledLayerImpl> root_layer =
- MakeLayer(NULL,
- gfx::Transform(),
- root_rect,
- 1,
- true,
- gfx::Rect(),
- render_surface_layer_list);
- scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
- gfx::Transform(),
- child_rect,
- 1,
+ 1.f,
true,
gfx::Rect(),
render_surface_layer_list);
- TestOcclusionTrackerImpl occlusion_tracker(gfx::Rect(500, 500, 100, 100));
+
+ TestOcclusionTrackerImpl occlusion_tracker(gfx::Rect(1000, 1000));
LayerIteratorType it = LayerIteratorType::Begin(&render_surface_layer_list);
- AppendQuads(&quad_list,
- &shared_state_list,
- child_layer.get(),
- &it,
- &occlusion_tracker);
- AppendQuads(&quad_list,
- &shared_state_list,
- root_layer.get(),
- &it,
- &occlusion_tracker);
- EXPECT_EQ(quad_list.size(), 0u);
- EXPECT_NEAR(
- occlusion_tracker.overdraw_metrics()->pixels_drawn_opaque(), 0, 1);
- EXPECT_NEAR(
- occlusion_tracker.overdraw_metrics()->pixels_drawn_translucent(), 0, 1);
- EXPECT_NEAR(occlusion_tracker.overdraw_metrics()->pixels_culled_for_drawing(),
- 130000,
- 1);
+ QuadCuller culler(&quad_list,
+ &shared_state_list,
+ dummy_layer.get(),
+ occlusion_tracker,
+ false,
+ false);
+
+ SharedQuadState* sqs = culler.UseSharedQuadState(SharedQuadState::Create());
+
+ scoped_ptr<SolidColorDrawQuad> color_quad = SolidColorDrawQuad::Create();
+ color_quad->SetNew(sqs, gfx::Rect(100, 100), SK_ColorRED, false);
+
+ scoped_ptr<RenderPassDrawQuad> pass_quad = RenderPassDrawQuad::Create();
+ pass_quad->SetNew(sqs,
+ gfx::Rect(100, 100),
+ RenderPass::Id(10, 10),
+ false,
+ 0,
+ gfx::Rect(),
+ gfx::RectF(),
+ FilterOperations(),
+ FilterOperations());
+
+ scoped_ptr<RenderPassDrawQuad> replica_quad = RenderPassDrawQuad::Create();
+ replica_quad->SetNew(sqs,
+ gfx::Rect(100, 100),
+ RenderPass::Id(10, 10),
+ true,
+ 0,
+ gfx::Rect(),
+ gfx::RectF(),
+ FilterOperations(),
+ FilterOperations());
+
+ // Set a visible rect on the quads.
+ color_quad->visible_rect = gfx::Rect(20, 30, 10, 11);
+ pass_quad->visible_rect = gfx::Rect(50, 60, 13, 14);
+ replica_quad->visible_rect = gfx::Rect(30, 40, 15, 16);
+
+ // Nothing is occluding.
+ occlusion_tracker.EnterLayer(it);
+
+ EXPECT_EQ(0u, quad_list.size());
+
+ AppendQuadsData data;
+ culler.Append(color_quad.PassAs<DrawQuad>(), &data);
+ culler.Append(pass_quad.PassAs<DrawQuad>(), &data);
+ culler.Append(replica_quad.PassAs<DrawQuad>(), &data);
+
+ ASSERT_EQ(3u, quad_list.size());
+
+ // The partial culling is preserved.
+ EXPECT_EQ(gfx::Rect(20, 30, 10, 11).ToString(),
+ quad_list[0]->visible_rect.ToString());
+ EXPECT_EQ(gfx::Rect(50, 60, 13, 14).ToString(),
+ quad_list[1]->visible_rect.ToString());
+ EXPECT_EQ(gfx::Rect(30, 40, 15, 16).ToString(),
+ quad_list[2]->visible_rect.ToString());
}
-TEST_F(QuadCullerTest, VerifyWithoutMetrics) {
+TEST_F(QuadCullerTest, PartialCullingWithOcclusionNotDestroyed) {
DECLARE_AND_INITIALIZE_TEST_QUADS();
- scoped_ptr<TiledLayerImpl> root_layer =
- MakeLayer(NULL,
- gfx::Transform(),
- root_rect,
- 1,
- true,
- gfx::Rect(),
- render_surface_layer_list);
- scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
+
+ scoped_ptr<TiledLayerImpl> dummy_layer = MakeLayer(NULL,
gfx::Transform(),
- child_rect,
- 1,
+ gfx::Rect(),
+ 1.f,
true,
gfx::Rect(),
render_surface_layer_list);
- TestOcclusionTrackerImpl occlusion_tracker(gfx::Rect(50, 50, 200, 200),
- false);
+
+ TestOcclusionTrackerImpl occlusion_tracker(gfx::Rect(1000, 1000));
LayerIteratorType it = LayerIteratorType::Begin(&render_surface_layer_list);
- AppendQuads(&quad_list,
- &shared_state_list,
- child_layer.get(),
- &it,
- &occlusion_tracker);
- AppendQuads(&quad_list,
- &shared_state_list,
- root_layer.get(),
- &it,
- &occlusion_tracker);
- EXPECT_EQ(quad_list.size(), 9u);
- EXPECT_NEAR(
- occlusion_tracker.overdraw_metrics()->pixels_drawn_opaque(), 0, 1);
- EXPECT_NEAR(
- occlusion_tracker.overdraw_metrics()->pixels_drawn_translucent(), 0, 1);
- EXPECT_NEAR(
- occlusion_tracker.overdraw_metrics()->pixels_culled_for_drawing(), 0, 1);
+ QuadCuller culler(&quad_list,
+ &shared_state_list,
+ dummy_layer.get(),
+ occlusion_tracker,
+ false,
+ false);
+
+ SharedQuadState* sqs = culler.UseSharedQuadState(SharedQuadState::Create());
+
+ scoped_ptr<SolidColorDrawQuad> color_quad = SolidColorDrawQuad::Create();
+ color_quad->SetNew(sqs, gfx::Rect(100, 100), SK_ColorRED, false);
+
+ scoped_ptr<RenderPassDrawQuad> pass_quad = RenderPassDrawQuad::Create();
+ pass_quad->SetNew(sqs,
+ gfx::Rect(100, 100),
+ RenderPass::Id(10, 10),
+ false,
+ 0,
+ gfx::Rect(),
+ gfx::RectF(),
+ FilterOperations(),
+ FilterOperations());
+
+ scoped_ptr<RenderPassDrawQuad> replica_quad = RenderPassDrawQuad::Create();
+ replica_quad->SetNew(sqs,
+ gfx::Rect(100, 100),
+ RenderPass::Id(10, 10),
+ true,
+ 0,
+ gfx::Rect(),
+ gfx::RectF(),
+ FilterOperations(),
+ FilterOperations());
+
+ // Set a visible rect on the quads.
+ color_quad->visible_rect = gfx::Rect(10, 10, 10, 11);
+ pass_quad->visible_rect = gfx::Rect(10, 20, 13, 14);
+ replica_quad->visible_rect = gfx::Rect(10, 30, 15, 16);
+
+ // Occlude the left part of the visible rects.
+ occlusion_tracker.EnterLayer(it);
+ occlusion_tracker.set_occlusion_from_outside_target(gfx::Rect(0, 0, 15, 100));
+
+ EXPECT_EQ(0u, quad_list.size());
+
+ AppendQuadsData data;
+ culler.Append(color_quad.PassAs<DrawQuad>(), &data);
+ culler.Append(pass_quad.PassAs<DrawQuad>(), &data);
+ culler.Append(replica_quad.PassAs<DrawQuad>(), &data);
+
+ ASSERT_EQ(3u, quad_list.size());
+
+ // The partial culling is preserved, while the left side of the quads is newly
+ // occluded.
+ EXPECT_EQ(gfx::Rect(15, 10, 5, 11).ToString(),
+ quad_list[0]->visible_rect.ToString());
+ EXPECT_EQ(gfx::Rect(15, 20, 8, 14).ToString(),
+ quad_list[1]->visible_rect.ToString());
+ EXPECT_EQ(gfx::Rect(15, 30, 10, 16).ToString(),
+ quad_list[2]->visible_rect.ToString());
}
} // namespace
diff --git a/chromium/cc/trees/single_thread_proxy.cc b/chromium/cc/trees/single_thread_proxy.cc
index 85db94c6902..f1f8a4f5824 100644
--- a/chromium/cc/trees/single_thread_proxy.cc
+++ b/chromium/cc/trees/single_thread_proxy.cc
@@ -6,6 +6,7 @@
#include "base/auto_reset.h"
#include "base/debug/trace_event.h"
+#include "cc/debug/benchmark_instrumentation.h"
#include "cc/output/context_provider.h"
#include "cc/output/output_surface.h"
#include "cc/quads/draw_quad.h"
@@ -13,18 +14,24 @@
#include "cc/resources/resource_update_controller.h"
#include "cc/trees/blocking_task_runner.h"
#include "cc/trees/layer_tree_host.h"
+#include "cc/trees/layer_tree_host_single_thread_client.h"
#include "cc/trees/layer_tree_impl.h"
+#include "ui/gfx/frame_time.h"
namespace cc {
-scoped_ptr<Proxy> SingleThreadProxy::Create(LayerTreeHost* layer_tree_host) {
+scoped_ptr<Proxy> SingleThreadProxy::Create(
+ LayerTreeHost* layer_tree_host,
+ LayerTreeHostSingleThreadClient* client) {
return make_scoped_ptr(
- new SingleThreadProxy(layer_tree_host)).PassAs<Proxy>();
+ new SingleThreadProxy(layer_tree_host, client)).PassAs<Proxy>();
}
-SingleThreadProxy::SingleThreadProxy(LayerTreeHost* layer_tree_host)
+SingleThreadProxy::SingleThreadProxy(LayerTreeHost* layer_tree_host,
+ LayerTreeHostSingleThreadClient* client)
: Proxy(NULL),
layer_tree_host_(layer_tree_host),
+ client_(client),
created_offscreen_context_provider_(false),
next_frame_is_newly_committed_frame_(false),
inside_draw_(false) {
@@ -58,7 +65,7 @@ bool SingleThreadProxy::CompositeAndReadback(void* pixels, gfx::Rect rect) {
gfx::Rect device_viewport_damage_rect = rect;
LayerTreeHostImpl::FrameData frame;
- if (!CommitAndComposite(base::TimeTicks::Now(),
+ if (!CommitAndComposite(gfx::FrameTime::Now(),
device_viewport_damage_rect,
true, // for_readback
&frame))
@@ -114,11 +121,12 @@ void SingleThreadProxy::CreateAndInitializeOutputSurface() {
return;
}
- scoped_refptr<cc::ContextProvider> offscreen_context_provider;
+ scoped_refptr<ContextProvider> offscreen_context_provider;
if (created_offscreen_context_provider_) {
offscreen_context_provider =
- layer_tree_host_->client()->OffscreenContextProviderForMainThread();
- if (!offscreen_context_provider.get()) {
+ layer_tree_host_->client()->OffscreenContextProvider();
+ if (!offscreen_context_provider.get() ||
+ !offscreen_context_provider->BindToCurrentThread()) {
OnOutputSurfaceInitializeAttempted(false);
return;
}
@@ -169,13 +177,13 @@ const RendererCapabilities& SingleThreadProxy::GetRendererCapabilities() const {
}
void SingleThreadProxy::SetNeedsAnimate() {
- // Thread-only feature.
- NOTREACHED();
+ DCHECK(Proxy::IsMainThread());
+ client_->ScheduleAnimation();
}
void SingleThreadProxy::SetNeedsUpdateLayers() {
DCHECK(Proxy::IsMainThread());
- layer_tree_host_->ScheduleComposite();
+ client_->ScheduleComposite();
}
void SingleThreadProxy::DoCommit(scoped_ptr<ResourceUpdateQueue> queue) {
@@ -190,15 +198,11 @@ void SingleThreadProxy::DoCommit(scoped_ptr<ResourceUpdateQueue> queue) {
// to receive its callbacks before that.
BlockingTaskRunner::CapturePostTasks blocked;
- RenderingStatsInstrumentation* stats_instrumentation =
- layer_tree_host_->rendering_stats_instrumentation();
- base::TimeTicks start_time = stats_instrumentation->StartRecording();
-
layer_tree_host_impl_->BeginCommit();
- if (layer_tree_host_->contents_texture_manager()) {
- layer_tree_host_->contents_texture_manager()->
- PushTexturePrioritiesToBackings();
+ if (PrioritizedResourceManager* contents_texture_manager =
+ layer_tree_host_->contents_texture_manager()) {
+ contents_texture_manager->PushTexturePrioritiesToBackings();
}
layer_tree_host_->BeginCommitOnImplThread(layer_tree_host_impl_.get());
@@ -226,9 +230,10 @@ void SingleThreadProxy::DoCommit(scoped_ptr<ResourceUpdateQueue> queue) {
DCHECK_EQ(1.f, scroll_info->page_scale_delta);
#endif
- base::TimeDelta duration = stats_instrumentation->EndRecording(start_time);
- stats_instrumentation->AddCommit(duration);
- stats_instrumentation->IssueTraceEventForMainThreadStats();
+ RenderingStatsInstrumentation* stats_instrumentation =
+ layer_tree_host_->rendering_stats_instrumentation();
+ BenchmarkInstrumentation::IssueMainThreadRenderingStatsEvent(
+ stats_instrumentation->main_thread_rendering_stats());
stats_instrumentation->AccumulateAndClearMainThreadStats();
}
layer_tree_host_->CommitComplete();
@@ -237,11 +242,12 @@ void SingleThreadProxy::DoCommit(scoped_ptr<ResourceUpdateQueue> queue) {
void SingleThreadProxy::SetNeedsCommit() {
DCHECK(Proxy::IsMainThread());
- layer_tree_host_->ScheduleComposite();
+ client_->ScheduleComposite();
}
void SingleThreadProxy::SetNeedsRedraw(gfx::Rect damage_rect) {
SetNeedsRedrawRectOnImplThread(damage_rect);
+ client_->ScheduleComposite();
}
void SingleThreadProxy::SetNextCommitWaitsForActivation() {
@@ -255,6 +261,8 @@ void SingleThreadProxy::SetDeferCommits(bool defer_commits) {
bool SingleThreadProxy::CommitRequested() const { return false; }
+bool SingleThreadProxy::BeginMainFrameRequested() const { return false; }
+
size_t SingleThreadProxy::MaxPartialTextureUpdates() const {
return std::numeric_limits<size_t>::max();
}
@@ -284,7 +292,7 @@ void SingleThreadProxy::NotifyReadyToActivate() {
}
void SingleThreadProxy::SetNeedsRedrawOnImplThread() {
- layer_tree_host_->ScheduleComposite();
+ client_->ScheduleComposite();
}
void SingleThreadProxy::SetNeedsManageTilesOnImplThread() {
@@ -306,7 +314,7 @@ void SingleThreadProxy::DidInitializeVisibleTileOnImplThread() {
}
void SingleThreadProxy::SetNeedsCommitOnImplThread() {
- layer_tree_host_->ScheduleComposite();
+ client_->ScheduleComposite();
}
void SingleThreadProxy::PostAnimationEventsToMainThreadOnImplThread(
@@ -321,27 +329,28 @@ bool SingleThreadProxy::ReduceContentsTextureMemoryOnImplThread(
size_t limit_bytes,
int priority_cutoff) {
DCHECK(IsImplThread());
- if (!layer_tree_host_->contents_texture_manager())
- return false;
+ PrioritizedResourceManager* contents_texture_manager =
+ layer_tree_host_->contents_texture_manager();
- return layer_tree_host_->contents_texture_manager()->ReduceMemoryOnImplThread(
- limit_bytes, priority_cutoff, layer_tree_host_impl_->resource_provider());
-}
+ ResourceProvider* resource_provider =
+ layer_tree_host_impl_->resource_provider();
-void SingleThreadProxy::ReduceWastedContentsTextureMemoryOnImplThread() {
- // Impl-side painting only.
- NOTREACHED();
+ if (!contents_texture_manager || !resource_provider)
+ return false;
+
+ return contents_texture_manager->ReduceMemoryOnImplThread(
+ limit_bytes, priority_cutoff, resource_provider);
}
void SingleThreadProxy::SendManagedMemoryStats() {
DCHECK(Proxy::IsImplThread());
if (!layer_tree_host_impl_)
return;
- if (!layer_tree_host_->contents_texture_manager())
- return;
-
PrioritizedResourceManager* contents_texture_manager =
layer_tree_host_->contents_texture_manager();
+ if (!contents_texture_manager)
+ return;
+
layer_tree_host_impl_->SendManagedMemoryStats(
contents_texture_manager->MemoryVisibleBytes(),
contents_texture_manager->MemoryVisibleAndNearbyBytes(),
@@ -353,6 +362,15 @@ bool SingleThreadProxy::IsInsideDraw() { return inside_draw_; }
void SingleThreadProxy::DidLoseOutputSurfaceOnImplThread() {
// Cause a commit so we can notice the lost context.
SetNeedsCommitOnImplThread();
+ client_->DidAbortSwapBuffers();
+}
+
+void SingleThreadProxy::DidSwapBuffersOnImplThread() {
+ client_->DidPostSwapBuffers();
+}
+
+void SingleThreadProxy::OnSwapBuffersCompleteOnImplThread() {
+ client_->DidCompleteSwapBuffers();
}
// Called by the legacy scheduling path (e.g. where render_widget does the
@@ -420,21 +438,12 @@ bool SingleThreadProxy::CommitAndComposite(
layer_tree_host_->AnimateLayers(frame_begin_time);
- scoped_refptr<cc::ContextProvider> offscreen_context_provider;
- if (renderer_capabilities_for_main_thread_.using_offscreen_context3d &&
- layer_tree_host_->needs_offscreen_context()) {
- offscreen_context_provider =
- layer_tree_host_->client()->OffscreenContextProviderForMainThread();
- if (offscreen_context_provider.get())
- created_offscreen_context_provider_ = true;
- }
-
- if (layer_tree_host_->contents_texture_manager()) {
- layer_tree_host_->contents_texture_manager()
- ->UnlinkAndClearEvictedBackings();
- layer_tree_host_->contents_texture_manager()->SetMaxMemoryLimitBytes(
+ if (PrioritizedResourceManager* contents_texture_manager =
+ layer_tree_host_->contents_texture_manager()) {
+ contents_texture_manager->UnlinkAndClearEvictedBackings();
+ contents_texture_manager->SetMaxMemoryLimitBytes(
layer_tree_host_impl_->memory_allocation_limit_bytes());
- layer_tree_host_->contents_texture_manager()->SetExternalPriorityCutoff(
+ contents_texture_manager->SetExternalPriorityCutoff(
layer_tree_host_impl_->memory_allocation_priority_cutoff());
}
@@ -443,13 +452,27 @@ bool SingleThreadProxy::CommitAndComposite(
layer_tree_host_->UpdateLayers(queue.get());
layer_tree_host_->WillCommit();
+
+ scoped_refptr<ContextProvider> offscreen_context_provider;
+ if (renderer_capabilities_for_main_thread_.using_offscreen_context3d &&
+ layer_tree_host_->needs_offscreen_context()) {
+ offscreen_context_provider =
+ layer_tree_host_->client()->OffscreenContextProvider();
+ if (offscreen_context_provider.get() &&
+ !offscreen_context_provider->BindToCurrentThread())
+ offscreen_context_provider = NULL;
+
+ if (offscreen_context_provider.get())
+ created_offscreen_context_provider_ = true;
+ }
+
DoCommit(queue.Pass());
bool result = DoComposite(offscreen_context_provider,
frame_begin_time,
device_viewport_damage_rect,
for_readback,
frame);
- layer_tree_host_->DidBeginFrame();
+ layer_tree_host_->DidBeginMainFrame();
return result;
}
@@ -466,7 +489,7 @@ void SingleThreadProxy::UpdateBackgroundAnimateTicking() {
}
bool SingleThreadProxy::DoComposite(
- scoped_refptr<cc::ContextProvider> offscreen_context_provider,
+ scoped_refptr<ContextProvider> offscreen_context_provider,
base::TimeTicks frame_begin_time,
gfx::Rect device_viewport_damage_rect,
bool for_readback,
@@ -497,9 +520,11 @@ bool SingleThreadProxy::DoComposite(
layer_tree_host_impl_->CurrentFrameTime());
UpdateBackgroundAnimateTicking();
- layer_tree_host_impl_->PrepareToDraw(frame, device_viewport_damage_rect);
- layer_tree_host_impl_->DrawLayers(frame, frame_begin_time);
- layer_tree_host_impl_->DidDrawAllLayers(*frame);
+ if (!layer_tree_host_impl_->IsContextLost()) {
+ layer_tree_host_impl_->PrepareToDraw(frame, device_viewport_damage_rect);
+ layer_tree_host_impl_->DrawLayers(frame, frame_begin_time);
+ layer_tree_host_impl_->DidDrawAllLayers(*frame);
+ }
lost_output_surface = layer_tree_host_impl_->IsContextLost();
bool start_ready_animations = true;
@@ -509,7 +534,7 @@ bool SingleThreadProxy::DoComposite(
}
if (lost_output_surface) {
- cc::ContextProvider* offscreen_contexts =
+ ContextProvider* offscreen_contexts =
layer_tree_host_impl_->offscreen_context_provider();
if (offscreen_contexts)
offscreen_contexts->VerifyContexts();
diff --git a/chromium/cc/trees/single_thread_proxy.h b/chromium/cc/trees/single_thread_proxy.h
index 474fb1f1101..463141c1748 100644
--- a/chromium/cc/trees/single_thread_proxy.h
+++ b/chromium/cc/trees/single_thread_proxy.h
@@ -17,10 +17,13 @@ namespace cc {
class ContextProvider;
class LayerTreeHost;
+class LayerTreeHostSingleThreadClient;
class SingleThreadProxy : public Proxy, LayerTreeHostImplClient {
public:
- static scoped_ptr<Proxy> Create(LayerTreeHost* layer_tree_host);
+ static scoped_ptr<Proxy> Create(
+ LayerTreeHost* layer_tree_host,
+ LayerTreeHostSingleThreadClient* client);
virtual ~SingleThreadProxy();
// Proxy implementation
@@ -39,6 +42,7 @@ class SingleThreadProxy : public Proxy, LayerTreeHostImplClient {
virtual void NotifyInputThrottledUntilCommit() OVERRIDE {}
virtual void SetDeferCommits(bool defer_commits) OVERRIDE;
virtual bool CommitRequested() const OVERRIDE;
+ virtual bool BeginMainFrameRequested() const OVERRIDE;
virtual void MainThreadHasStoppedFlinging() OVERRIDE {}
virtual void Start(scoped_ptr<OutputSurface> first_output_surface) OVERRIDE;
virtual void Stop() OVERRIDE;
@@ -50,8 +54,9 @@ class SingleThreadProxy : public Proxy, LayerTreeHostImplClient {
// LayerTreeHostImplClient implementation
virtual void DidLoseOutputSurfaceOnImplThread() OVERRIDE;
- virtual void OnSwapBuffersCompleteOnImplThread() OVERRIDE {}
- virtual void BeginFrameOnImplThread(const BeginFrameArgs& args)
+ virtual void DidSwapBuffersOnImplThread() OVERRIDE;
+ virtual void OnSwapBuffersCompleteOnImplThread() OVERRIDE;
+ virtual void BeginImplFrame(const BeginFrameArgs& args)
OVERRIDE {}
virtual void OnCanDrawStateChanged(bool can_draw) OVERRIDE;
virtual void NotifyReadyToActivate() OVERRIDE;
@@ -66,19 +71,20 @@ class SingleThreadProxy : public Proxy, LayerTreeHostImplClient {
virtual bool ReduceContentsTextureMemoryOnImplThread(
size_t limit_bytes,
int priority_cutoff) OVERRIDE;
- virtual void ReduceWastedContentsTextureMemoryOnImplThread() OVERRIDE;
virtual void SendManagedMemoryStats() OVERRIDE;
virtual bool IsInsideDraw() OVERRIDE;
virtual void RenewTreePriority() OVERRIDE {}
virtual void RequestScrollbarAnimationOnImplThread(base::TimeDelta delay)
OVERRIDE {}
virtual void DidActivatePendingTree() OVERRIDE {}
+ virtual void DidManageTiles() OVERRIDE {}
// Called by the legacy path where RenderWidget does the scheduling.
void CompositeImmediately(base::TimeTicks frame_begin_time);
private:
- explicit SingleThreadProxy(LayerTreeHost* layer_tree_host);
+ SingleThreadProxy(LayerTreeHost* layer_tree_host,
+ LayerTreeHostSingleThreadClient* client);
void OnOutputSurfaceInitializeAttempted(bool success);
bool CommitAndComposite(base::TimeTicks frame_begin_time,
@@ -86,12 +92,11 @@ class SingleThreadProxy : public Proxy, LayerTreeHostImplClient {
bool for_readback,
LayerTreeHostImpl::FrameData* frame);
void DoCommit(scoped_ptr<ResourceUpdateQueue> queue);
- bool DoComposite(
- scoped_refptr<cc::ContextProvider> offscreen_context_provider,
- base::TimeTicks frame_begin_time,
- gfx::Rect device_viewport_damage_rect,
- bool for_readback,
- LayerTreeHostImpl::FrameData* frame);
+ bool DoComposite(scoped_refptr<ContextProvider> offscreen_context_provider,
+ base::TimeTicks frame_begin_time,
+ gfx::Rect device_viewport_damage_rect,
+ bool for_readback,
+ LayerTreeHostImpl::FrameData* frame);
void DidSwapFrame();
bool ShouldComposite() const;
@@ -99,6 +104,7 @@ class SingleThreadProxy : public Proxy, LayerTreeHostImplClient {
// Accessed on main thread only.
LayerTreeHost* layer_tree_host_;
+ LayerTreeHostSingleThreadClient* client_;
bool created_offscreen_context_provider_;
// Holds the first output surface passed from Start. Should not be used for
diff --git a/chromium/cc/trees/thread_proxy.cc b/chromium/cc/trees/thread_proxy.cc
index b5dff0e2bcb..2823182d590 100644
--- a/chromium/cc/trees/thread_proxy.cc
+++ b/chromium/cc/trees/thread_proxy.cc
@@ -10,6 +10,8 @@
#include "base/bind.h"
#include "base/debug/trace_event.h"
#include "base/metrics/histogram.h"
+#include "cc/base/swap_promise.h"
+#include "cc/debug/benchmark_instrumentation.h"
#include "cc/input/input_handler.h"
#include "cc/output/context_provider.h"
#include "cc/output/output_surface.h"
@@ -21,13 +23,11 @@
#include "cc/trees/blocking_task_runner.h"
#include "cc/trees/layer_tree_host.h"
#include "cc/trees/layer_tree_impl.h"
+#include "ui/gfx/frame_time.h"
namespace {
// Measured in seconds.
-const double kContextRecreationTickRate = 0.03;
-
-// Measured in seconds.
const double kSmoothnessTakesPriorityExpirationDelay = 0.25;
const size_t kDurationHistorySize = 60;
@@ -35,6 +35,19 @@ const double kCommitAndActivationDurationEstimationPercentile = 50.0;
const double kDrawDurationEstimationPercentile = 100.0;
const int kDrawDurationEstimatePaddingInMicroseconds = 0;
+class SwapPromiseChecker {
+ public:
+ explicit SwapPromiseChecker(cc::LayerTreeHost* layer_tree_host)
+ : layer_tree_host_(layer_tree_host) {}
+
+ ~SwapPromiseChecker() {
+ layer_tree_host_->BreakSwapPromises(cc::SwapPromise::COMMIT_FAILS);
+ }
+
+ private:
+ cc::LayerTreeHost* layer_tree_host_;
+};
+
} // namespace
namespace cc {
@@ -71,16 +84,15 @@ ThreadProxy::ThreadProxy(
commit_requested_(false),
commit_request_sent_to_impl_thread_(false),
created_offscreen_context_provider_(false),
- layer_tree_host_(layer_tree_host),
+ layer_tree_host_unsafe_(layer_tree_host),
+ contents_texture_manager_unsafe_(NULL),
started_(false),
textures_acquired_(true),
in_composite_and_readback_(false),
manage_tiles_pending_(false),
commit_waits_for_activation_(false),
inside_commit_(false),
- weak_factory_on_impl_thread_(this),
- weak_factory_(this),
- begin_frame_sent_to_main_thread_completion_event_on_impl_thread_(NULL),
+ begin_main_frame_sent_completion_event_on_impl_thread_(NULL),
readback_request_on_impl_thread_(NULL),
commit_completion_event_on_impl_thread_(NULL),
completion_event_for_commit_held_on_tree_activation_(NULL),
@@ -88,8 +100,8 @@ ThreadProxy::ThreadProxy(
next_frame_is_newly_committed_frame_on_impl_thread_(false),
throttle_frame_production_(
layer_tree_host->settings().throttle_frame_production),
- begin_frame_scheduling_enabled_(
- layer_tree_host->settings().begin_frame_scheduling_enabled),
+ begin_impl_frame_scheduling_enabled_(
+ layer_tree_host->settings().begin_impl_frame_scheduling_enabled),
using_synchronous_renderer_compositor_(
layer_tree_host->settings().using_synchronous_renderer_compositor),
inside_draw_(false),
@@ -98,11 +110,14 @@ ThreadProxy::ThreadProxy(
input_throttled_until_commit_(false),
renew_tree_priority_on_impl_thread_pending_(false),
draw_duration_history_(kDurationHistorySize),
- begin_frame_to_commit_duration_history_(kDurationHistorySize),
- commit_to_activate_duration_history_(kDurationHistorySize) {
+ begin_main_frame_to_commit_duration_history_(kDurationHistorySize),
+ commit_to_activate_duration_history_(kDurationHistorySize),
+ weak_factory_on_impl_thread_(this),
+ weak_factory_(this),
+ layer_tree_host_id_(layer_tree_host->id()) {
TRACE_EVENT0("cc", "ThreadProxy::ThreadProxy");
DCHECK(IsMainThread());
- DCHECK(layer_tree_host_);
+ DCHECK(this->layer_tree_host());
}
ThreadProxy::~ThreadProxy() {
@@ -114,14 +129,14 @@ ThreadProxy::~ThreadProxy() {
bool ThreadProxy::CompositeAndReadback(void* pixels, gfx::Rect rect) {
TRACE_EVENT0("cc", "ThreadProxy::CompositeAndReadback");
DCHECK(IsMainThread());
- DCHECK(layer_tree_host_);
+ DCHECK(layer_tree_host());
if (defer_commits_) {
TRACE_EVENT0("cc", "CompositeAndReadback_DeferCommit");
return false;
}
- if (!layer_tree_host_->InitializeOutputSurfaceIfNeeded()) {
+ if (!layer_tree_host()->InitializeOutputSurfaceIfNeeded()) {
TRACE_EVENT0("cc", "CompositeAndReadback_EarlyOut_LR_Uninitialized");
return false;
}
@@ -132,22 +147,22 @@ bool ThreadProxy::CompositeAndReadback(void* pixels, gfx::Rect rect) {
request.pixels = pixels;
{
DebugScopedSetMainThreadBlocked main_thread_blocked(this);
- CompletionEvent begin_frame_sent_to_main_thread_completion;
+ CompletionEvent begin_main_frame_sent_completion;
Proxy::ImplThreadTaskRunner()
->PostTask(FROM_HERE,
base::Bind(&ThreadProxy::ForceCommitForReadbackOnImplThread,
impl_thread_weak_ptr_,
- &begin_frame_sent_to_main_thread_completion,
+ &begin_main_frame_sent_completion,
&request));
- begin_frame_sent_to_main_thread_completion.Wait();
+ begin_main_frame_sent_completion.Wait();
}
in_composite_and_readback_ = true;
// This is the forced commit.
- // Note: The Impl thread also queues a separate BeginFrameOnMainThread on the
+ // Note: The Impl thread also queues a separate BeginMainFrame on the
// main thread, which will be called after this CompositeAndReadback
// completes, to replace the forced commit.
- BeginFrameOnMainThread(scoped_ptr<BeginFrameAndCommitState>());
+ BeginMainFrame(scoped_ptr<BeginMainFrameAndCommitState>());
in_composite_and_readback_ = false;
// Composite and readback requires a second commit to undo any changes
@@ -159,15 +174,15 @@ bool ThreadProxy::CompositeAndReadback(void* pixels, gfx::Rect rect) {
}
void ThreadProxy::ForceCommitForReadbackOnImplThread(
- CompletionEvent* begin_frame_sent_completion,
+ CompletionEvent* begin_main_frame_sent_completion,
ReadbackRequest* request) {
TRACE_EVENT0("cc", "ThreadProxy::ForceCommitForReadbackOnImplThread");
DCHECK(IsImplThread());
- DCHECK(!begin_frame_sent_to_main_thread_completion_event_on_impl_thread_);
+ DCHECK(!begin_main_frame_sent_completion_event_on_impl_thread_);
DCHECK(!readback_request_on_impl_thread_);
if (!layer_tree_host_impl_) {
- begin_frame_sent_completion->Signal();
+ begin_main_frame_sent_completion->Signal();
request->success = false;
request->completion.Signal();
return;
@@ -177,12 +192,12 @@ void ThreadProxy::ForceCommitForReadbackOnImplThread(
scheduler_on_impl_thread_->SetNeedsForcedCommitForReadback();
if (scheduler_on_impl_thread_->CommitPending()) {
- begin_frame_sent_completion->Signal();
+ begin_main_frame_sent_completion->Signal();
return;
}
- begin_frame_sent_to_main_thread_completion_event_on_impl_thread_ =
- begin_frame_sent_completion;
+ begin_main_frame_sent_completion_event_on_impl_thread_ =
+ begin_main_frame_sent_completion;
}
void ThreadProxy::FinishAllRendering() {
@@ -253,7 +268,7 @@ void ThreadProxy::DoCreateAndInitializeOutputSurface() {
scoped_ptr<OutputSurface> output_surface = first_output_surface_.Pass();
if (!output_surface)
- output_surface = layer_tree_host_->CreateOutputSurface();
+ output_surface = layer_tree_host()->CreateOutputSurface();
RendererCapabilities capabilities;
bool success = !!output_surface;
@@ -264,8 +279,8 @@ void ThreadProxy::DoCreateAndInitializeOutputSurface() {
scoped_refptr<ContextProvider> offscreen_context_provider;
if (created_offscreen_context_provider_) {
- offscreen_context_provider = layer_tree_host_->client()->
- OffscreenContextProviderForCompositorThread();
+ offscreen_context_provider =
+ layer_tree_host()->client()->OffscreenContextProvider();
success = !!offscreen_context_provider.get();
if (!success) {
OnOutputSurfaceInitializeAttempted(false, capabilities);
@@ -300,14 +315,14 @@ void ThreadProxy::OnOutputSurfaceInitializeAttempted(
bool success,
const RendererCapabilities& capabilities) {
DCHECK(IsMainThread());
- DCHECK(layer_tree_host_);
+ DCHECK(layer_tree_host());
if (success) {
renderer_capabilities_main_thread_copy_ = capabilities;
}
LayerTreeHost::CreateResult result =
- layer_tree_host_->OnCreateAndInitializeOutputSurfaceAttempted(success);
+ layer_tree_host()->OnCreateAndInitializeOutputSurfaceAttempted(success);
if (result == LayerTreeHost::CreateFailedButTryAgain) {
if (!output_surface_creation_callback_.callback().is_null()) {
Proxy::MainThreadTaskRunner()->PostTask(
@@ -331,7 +346,7 @@ void ThreadProxy::SendCommitRequestToImplThreadIfNeeded() {
const RendererCapabilities& ThreadProxy::GetRendererCapabilities() const {
DCHECK(IsMainThread());
- DCHECK(!layer_tree_host_->output_surface_lost());
+ DCHECK(!layer_tree_host()->output_surface_lost());
return renderer_capabilities_main_thread_copy_;
}
@@ -348,6 +363,11 @@ void ThreadProxy::SetNeedsAnimate() {
void ThreadProxy::SetNeedsUpdateLayers() {
DCHECK(IsMainThread());
+
+ if (commit_request_sent_to_impl_thread_)
+ return;
+ TRACE_EVENT0("cc", "ThreadProxy::SetNeedsUpdateLayers");
+
SendCommitRequestToImplThreadIfNeeded();
}
@@ -375,7 +395,7 @@ void ThreadProxy::CheckOutputSurfaceStatusOnImplThread() {
TRACE_EVENT0("cc", "ThreadProxy::CheckOutputSurfaceStatusOnImplThread");
if (!layer_tree_host_impl_->IsContextLost())
return;
- if (cc::ContextProvider* offscreen_contexts =
+ if (ContextProvider* offscreen_contexts =
layer_tree_host_impl_->offscreen_context_provider())
offscreen_contexts->VerifyContexts();
scheduler_on_impl_thread_->DidLoseOutputSurface();
@@ -389,27 +409,23 @@ void ThreadProxy::OnSwapBuffersCompleteOnImplThread() {
base::Bind(&ThreadProxy::DidCompleteSwapBuffers, main_thread_weak_ptr_));
}
-void ThreadProxy::SetNeedsBeginFrameOnImplThread(bool enable) {
+void ThreadProxy::SetNeedsBeginImplFrame(bool enable) {
DCHECK(IsImplThread());
- TRACE_EVENT1("cc", "ThreadProxy::SetNeedsBeginFrameOnImplThread",
+ TRACE_EVENT1("cc", "ThreadProxy::SetNeedsBeginImplFrame",
"enable", enable);
- layer_tree_host_impl_->SetNeedsBeginFrame(enable);
+ layer_tree_host_impl_->SetNeedsBeginImplFrame(enable);
UpdateBackgroundAnimateTicking();
}
-void ThreadProxy::BeginFrameOnImplThread(const BeginFrameArgs& args) {
+void ThreadProxy::BeginImplFrame(const BeginFrameArgs& args) {
DCHECK(IsImplThread());
- TRACE_EVENT0("cc", "ThreadProxy::BeginFrameOnImplThread");
+ TRACE_EVENT0("cc", "ThreadProxy::BeginImplFrame");
// Sample the frame time now. This time will be used for updating animations
// when we draw.
layer_tree_host_impl_->CurrentFrameTimeTicks();
- scheduler_on_impl_thread_->BeginFrame(args);
-}
-
-void ThreadProxy::DidBeginFrameDeadlineOnImplThread() {
- layer_tree_host_impl_->ResetCurrentFrameTimeForNextFrame();
+ scheduler_on_impl_thread_->BeginImplFrame(args);
}
void ThreadProxy::OnCanDrawStateChanged(bool can_draw) {
@@ -449,10 +465,12 @@ bool ThreadProxy::ReduceContentsTextureMemoryOnImplThread(size_t limit_bytes,
int priority_cutoff) {
DCHECK(IsImplThread());
- if (!layer_tree_host_->contents_texture_manager())
+ if (!contents_texture_manager_on_impl_thread())
+ return false;
+ if (!layer_tree_host_impl_->resource_provider())
return false;
- bool reduce_result = layer_tree_host_->contents_texture_manager()->
+ bool reduce_result = contents_texture_manager_on_impl_thread()->
ReduceMemoryOnImplThread(limit_bytes,
priority_cutoff,
layer_tree_host_impl_->resource_provider());
@@ -468,34 +486,24 @@ bool ThreadProxy::ReduceContentsTextureMemoryOnImplThread(size_t limit_bytes,
return true;
}
-void ThreadProxy::ReduceWastedContentsTextureMemoryOnImplThread() {
- DCHECK(IsImplThread());
-
- if (!layer_tree_host_->contents_texture_manager())
- return;
-
- layer_tree_host_->contents_texture_manager()->ReduceWastedMemoryOnImplThread(
- layer_tree_host_impl_->resource_provider());
-}
-
void ThreadProxy::SendManagedMemoryStats() {
DCHECK(IsImplThread());
if (!layer_tree_host_impl_)
return;
- if (!layer_tree_host_->contents_texture_manager())
+ if (!contents_texture_manager_on_impl_thread())
return;
// If we are using impl-side painting, then SendManagedMemoryStats is called
// directly after the tile manager's manage function, and doesn't need to
// interact with main thread's layer tree.
- if (layer_tree_host_->settings().impl_side_painting)
+ if (layer_tree_host_impl_->settings().impl_side_painting)
return;
layer_tree_host_impl_->SendManagedMemoryStats(
- layer_tree_host_->contents_texture_manager()->MemoryVisibleBytes(),
- layer_tree_host_->contents_texture_manager()->
+ contents_texture_manager_on_impl_thread()->MemoryVisibleBytes(),
+ contents_texture_manager_on_impl_thread()->
MemoryVisibleAndNearbyBytes(),
- layer_tree_host_->contents_texture_manager()->MemoryUseBytes());
+ contents_texture_manager_on_impl_thread()->MemoryUseBytes());
}
bool ThreadProxy::IsInsideDraw() { return inside_draw_; }
@@ -529,7 +537,7 @@ void ThreadProxy::SetDeferCommits(bool defer_commits) {
if (!defer_commits_ && pending_deferred_commit_)
Proxy::MainThreadTaskRunner()->PostTask(
FROM_HERE,
- base::Bind(&ThreadProxy::BeginFrameOnMainThread,
+ base::Bind(&ThreadProxy::BeginMainFrame,
main_thread_weak_ptr_,
base::Passed(&pending_deferred_commit_)));
}
@@ -539,6 +547,11 @@ bool ThreadProxy::CommitRequested() const {
return commit_requested_;
}
+bool ThreadProxy::BeginMainFrameRequested() const {
+ DCHECK(IsMainThread());
+ return commit_request_sent_to_impl_thread_;
+}
+
void ThreadProxy::SetNeedsRedrawOnImplThread() {
DCHECK(IsImplThread());
TRACE_EVENT0("cc", "ThreadProxy::SetNeedsRedrawOnImplThread");
@@ -547,7 +560,6 @@ void ThreadProxy::SetNeedsRedrawOnImplThread() {
void ThreadProxy::SetNeedsManageTilesOnImplThread() {
DCHECK(IsImplThread());
- TRACE_EVENT0("cc", "ThreadProxy::SetNeedsManageTilesOnImplThread");
scheduler_on_impl_thread_->SetNeedsManageTiles();
}
@@ -607,6 +619,28 @@ void ThreadProxy::SetInputThrottledUntilCommitOnImplThread(
RenewTreePriority();
}
+LayerTreeHost* ThreadProxy::layer_tree_host() {
+ DCHECK(IsMainThread() || IsMainThreadBlocked());
+ return layer_tree_host_unsafe_;
+}
+
+const LayerTreeHost* ThreadProxy::layer_tree_host() const {
+ DCHECK(IsMainThread() || IsMainThreadBlocked());
+ return layer_tree_host_unsafe_;
+}
+
+PrioritizedResourceManager*
+ThreadProxy::contents_texture_manager_on_main_thread() {
+ DCHECK(IsMainThread() || IsMainThreadBlocked());
+ return layer_tree_host()->contents_texture_manager();
+}
+
+PrioritizedResourceManager*
+ThreadProxy::contents_texture_manager_on_impl_thread() {
+ DCHECK(IsImplThread());
+ return contents_texture_manager_unsafe_;
+}
+
void ThreadProxy::Start(scoped_ptr<OutputSurface> first_output_surface) {
DCHECK(IsMainThread());
DCHECK(Proxy::HasImplThread());
@@ -663,7 +697,8 @@ void ThreadProxy::Stop() {
weak_factory_.InvalidateWeakPtrs();
DCHECK(!layer_tree_host_impl_.get()); // verify that the impl deleted.
- layer_tree_host_ = NULL;
+ contents_texture_manager_unsafe_ = NULL;
+ layer_tree_host_unsafe_ = NULL;
started_ = false;
}
@@ -692,54 +727,59 @@ void ThreadProxy::FinishAllRenderingOnImplThread(CompletionEvent* completion) {
completion->Signal();
}
-void ThreadProxy::ScheduledActionSendBeginFrameToMainThread() {
- TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionSendBeginFrameToMainThread");
- scoped_ptr<BeginFrameAndCommitState> begin_frame_state(
- new BeginFrameAndCommitState);
- begin_frame_state->monotonic_frame_begin_time =
+void ThreadProxy::ScheduledActionSendBeginMainFrame() {
+ TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionSendBeginMainFrame");
+ scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state(
+ new BeginMainFrameAndCommitState);
+ begin_main_frame_state->monotonic_frame_begin_time =
layer_tree_host_impl_->CurrentPhysicalTimeTicks();
- begin_frame_state->scroll_info =
+ begin_main_frame_state->scroll_info =
layer_tree_host_impl_->ProcessScrollDeltas();
if (!layer_tree_host_impl_->settings().impl_side_painting) {
DCHECK_GT(layer_tree_host_impl_->memory_allocation_limit_bytes(), 0u);
}
- begin_frame_state->memory_allocation_limit_bytes =
+ begin_main_frame_state->memory_allocation_limit_bytes =
layer_tree_host_impl_->memory_allocation_limit_bytes();
- begin_frame_state->memory_allocation_priority_cutoff =
+ begin_main_frame_state->memory_allocation_priority_cutoff =
layer_tree_host_impl_->memory_allocation_priority_cutoff();
- begin_frame_state->evicted_ui_resources =
+ begin_main_frame_state->evicted_ui_resources =
layer_tree_host_impl_->EvictedUIResourcesExist();
Proxy::MainThreadTaskRunner()->PostTask(
FROM_HERE,
- base::Bind(&ThreadProxy::BeginFrameOnMainThread,
+ base::Bind(&ThreadProxy::BeginMainFrame,
main_thread_weak_ptr_,
- base::Passed(&begin_frame_state)));
+ base::Passed(&begin_main_frame_state)));
- if (begin_frame_sent_to_main_thread_completion_event_on_impl_thread_) {
- begin_frame_sent_to_main_thread_completion_event_on_impl_thread_->Signal();
- begin_frame_sent_to_main_thread_completion_event_on_impl_thread_ = NULL;
+ if (begin_main_frame_sent_completion_event_on_impl_thread_) {
+ begin_main_frame_sent_completion_event_on_impl_thread_->Signal();
+ begin_main_frame_sent_completion_event_on_impl_thread_ = NULL;
}
- begin_frame_sent_to_main_thread_time_ = base::TimeTicks::HighResNow();
+ begin_main_frame_sent_time_ = base::TimeTicks::HighResNow();
}
-void ThreadProxy::BeginFrameOnMainThread(
- scoped_ptr<BeginFrameAndCommitState> begin_frame_state) {
- TRACE_EVENT0("cc", "ThreadProxy::BeginFrameOnMainThread");
+void ThreadProxy::BeginMainFrame(
+ scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state) {
+ TRACE_EVENT0("cc", "ThreadProxy::BeginMainFrame");
DCHECK(IsMainThread());
- if (!layer_tree_host_)
+ if (!layer_tree_host())
return;
if (defer_commits_) {
- pending_deferred_commit_ = begin_frame_state.Pass();
- layer_tree_host_->DidDeferCommit();
+ pending_deferred_commit_ = begin_main_frame_state.Pass();
+ layer_tree_host()->DidDeferCommit();
TRACE_EVENT0("cc", "EarlyOut_DeferCommits");
return;
}
+ // If the commit finishes, LayerTreeHost will transfer its swap promises to
+ // LayerTreeImpl. The destructor of SwapPromiseChecker checks LayerTressHost's
+ // swap promises.
+ SwapPromiseChecker swap_promise_checker(layer_tree_host());
+
// Do not notify the impl thread of commit requests that occur during
- // the apply/animate/layout part of the BeginFrameAndCommit process since
+ // the apply/animate/layout part of the BeginMainFrameAndCommit process since
// those commit requests will get painted immediately. Once we have done
// the paint, commit_requested_ will be set to false to allow new commit
// requests to be scheduled.
@@ -751,7 +791,7 @@ void ThreadProxy::BeginFrameOnMainThread(
// callbacks will trigger another frame.
animate_requested_ = false;
- if (!in_composite_and_readback_ && !layer_tree_host_->visible()) {
+ if (!in_composite_and_readback_ && !layer_tree_host()->visible()) {
commit_requested_ = false;
commit_request_sent_to_impl_thread_ = false;
@@ -759,46 +799,49 @@ void ThreadProxy::BeginFrameOnMainThread(
bool did_handle = false;
Proxy::ImplThreadTaskRunner()->PostTask(
FROM_HERE,
- base::Bind(&ThreadProxy::BeginFrameAbortedByMainThreadOnImplThread,
+ base::Bind(&ThreadProxy::BeginMainFrameAbortedOnImplThread,
impl_thread_weak_ptr_,
did_handle));
return;
}
- if (begin_frame_state)
- layer_tree_host_->ApplyScrollAndScale(*begin_frame_state->scroll_info);
+ if (begin_main_frame_state) {
+ layer_tree_host()->ApplyScrollAndScale(
+ *begin_main_frame_state->scroll_info);
+ }
- layer_tree_host_->WillBeginFrame();
+ layer_tree_host()->WillBeginMainFrame();
- if (begin_frame_state) {
- layer_tree_host_->UpdateClientAnimations(
- begin_frame_state->monotonic_frame_begin_time);
- layer_tree_host_->AnimateLayers(
- begin_frame_state->monotonic_frame_begin_time);
+ if (begin_main_frame_state) {
+ layer_tree_host()->UpdateClientAnimations(
+ begin_main_frame_state->monotonic_frame_begin_time);
+ layer_tree_host()->AnimateLayers(
+ begin_main_frame_state->monotonic_frame_begin_time);
}
// Unlink any backings that the impl thread has evicted, so that we know to
// re-paint them in UpdateLayers.
- if (layer_tree_host_->contents_texture_manager()) {
- layer_tree_host_->contents_texture_manager()->
+ if (contents_texture_manager_on_main_thread()) {
+ contents_texture_manager_on_main_thread()->
UnlinkAndClearEvictedBackings();
- if (begin_frame_state) {
- layer_tree_host_->contents_texture_manager()->SetMaxMemoryLimitBytes(
- begin_frame_state->memory_allocation_limit_bytes);
- layer_tree_host_->contents_texture_manager()->SetExternalPriorityCutoff(
- begin_frame_state->memory_allocation_priority_cutoff);
+ if (begin_main_frame_state) {
+ contents_texture_manager_on_main_thread()->SetMaxMemoryLimitBytes(
+ begin_main_frame_state->memory_allocation_limit_bytes);
+ contents_texture_manager_on_main_thread()->SetExternalPriorityCutoff(
+ begin_main_frame_state->memory_allocation_priority_cutoff);
}
}
// Recreate all UI resources if there were evicted UI resources when the impl
// thread initiated the commit.
- bool evicted_ui_resources =
- begin_frame_state ? begin_frame_state->evicted_ui_resources : false;
+ bool evicted_ui_resources = begin_main_frame_state
+ ? begin_main_frame_state->evicted_ui_resources
+ : false;
if (evicted_ui_resources)
- layer_tree_host_->RecreateUIResources();
+ layer_tree_host()->RecreateUIResources();
- layer_tree_host_->Layout();
+ layer_tree_host()->Layout();
// Clear the commit flag after updating animations and layout here --- objects
// that only layout when painted will trigger another SetNeedsCommit inside
@@ -814,28 +857,28 @@ void ThreadProxy::BeginFrameOnMainThread(
scoped_ptr<ResourceUpdateQueue> queue =
make_scoped_ptr(new ResourceUpdateQueue);
- bool updated = layer_tree_host_->UpdateLayers(queue.get());
+ bool updated = layer_tree_host()->UpdateLayers(queue.get());
// Once single buffered layers are committed, they cannot be modified until
// they are drawn by the impl thread.
textures_acquired_ = false;
- layer_tree_host_->WillCommit();
+ layer_tree_host()->WillCommit();
if (!updated && can_cancel_this_commit) {
TRACE_EVENT0("cc", "EarlyOut_NoUpdates");
bool did_handle = true;
Proxy::ImplThreadTaskRunner()->PostTask(
FROM_HERE,
- base::Bind(&ThreadProxy::BeginFrameAbortedByMainThreadOnImplThread,
+ base::Bind(&ThreadProxy::BeginMainFrameAbortedOnImplThread,
impl_thread_weak_ptr_,
did_handle));
// 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.
- layer_tree_host_->CommitComplete();
- layer_tree_host_->DidBeginFrame();
+ layer_tree_host()->CommitComplete();
+ layer_tree_host()->DidBeginMainFrame();
return;
}
@@ -849,11 +892,11 @@ void ThreadProxy::BeginFrameOnMainThread(
SetNeedsAnimate();
}
- scoped_refptr<cc::ContextProvider> offscreen_context_provider;
+ scoped_refptr<ContextProvider> offscreen_context_provider;
if (renderer_capabilities_main_thread_copy_.using_offscreen_context3d &&
- layer_tree_host_->needs_offscreen_context()) {
- offscreen_context_provider = layer_tree_host_->client()->
- OffscreenContextProviderForCompositorThread();
+ layer_tree_host()->needs_offscreen_context()) {
+ offscreen_context_provider =
+ layer_tree_host()->client()->OffscreenContextProvider();
if (offscreen_context_provider.get())
created_offscreen_context_provider_ = true;
}
@@ -863,7 +906,7 @@ void ThreadProxy::BeginFrameOnMainThread(
// point of view, but asynchronously performed on the impl thread,
// coordinated by the Scheduler.
{
- TRACE_EVENT0("cc", "ThreadProxy::BeginFrameOnMainThread::commit");
+ TRACE_EVENT0("cc", "ThreadProxy::BeginMainFrame::commit");
DebugScopedSetMainThreadBlocked main_thread_blocked(this);
@@ -872,10 +915,6 @@ void ThreadProxy::BeginFrameOnMainThread(
// to receive its callbacks before that.
BlockingTaskRunner::CapturePostTasks blocked;
- RenderingStatsInstrumentation* stats_instrumentation =
- layer_tree_host_->rendering_stats_instrumentation();
- base::TimeTicks start_time = stats_instrumentation->StartRecording();
-
CompletionEvent completion;
Proxy::ImplThreadTaskRunner()->PostTask(
FROM_HERE,
@@ -886,20 +925,21 @@ void ThreadProxy::BeginFrameOnMainThread(
offscreen_context_provider));
completion.Wait();
- base::TimeDelta duration = stats_instrumentation->EndRecording(start_time);
- stats_instrumentation->AddCommit(duration);
- stats_instrumentation->IssueTraceEventForMainThreadStats();
+ RenderingStatsInstrumentation* stats_instrumentation =
+ layer_tree_host()->rendering_stats_instrumentation();
+ BenchmarkInstrumentation::IssueMainThreadRenderingStatsEvent(
+ stats_instrumentation->main_thread_rendering_stats());
stats_instrumentation->AccumulateAndClearMainThreadStats();
}
- layer_tree_host_->CommitComplete();
- layer_tree_host_->DidBeginFrame();
+ layer_tree_host()->CommitComplete();
+ layer_tree_host()->DidBeginMainFrame();
}
void ThreadProxy::StartCommitOnImplThread(
CompletionEvent* completion,
ResourceUpdateQueue* raw_queue,
- scoped_refptr<cc::ContextProvider> offscreen_context_provider) {
+ scoped_refptr<ContextProvider> offscreen_context_provider) {
scoped_ptr<ResourceUpdateQueue> queue(raw_queue);
TRACE_EVENT0("cc", "ThreadProxy::StartCommitOnImplThread");
@@ -919,8 +959,18 @@ void ThreadProxy::StartCommitOnImplThread(
layer_tree_host_impl_->SetOffscreenContextProvider(
offscreen_context_provider);
- if (layer_tree_host_->contents_texture_manager()) {
- if (layer_tree_host_->contents_texture_manager()->
+ if (contents_texture_manager_unsafe_) {
+ DCHECK_EQ(contents_texture_manager_unsafe_,
+ contents_texture_manager_on_main_thread());
+ } else {
+ // Cache this pointer that was created on the main thread side to avoid a
+ // data race between creating it and using it on the compositor thread.
+ contents_texture_manager_unsafe_ =
+ contents_texture_manager_on_main_thread();
+ }
+
+ if (contents_texture_manager_on_main_thread()) {
+ if (contents_texture_manager_on_main_thread()->
LinkedEvictedBackingsExist()) {
// Clear any uploads we were making to textures linked to evicted
// resources
@@ -930,7 +980,7 @@ void ThreadProxy::StartCommitOnImplThread(
SetNeedsCommitOnImplThread();
}
- layer_tree_host_->contents_texture_manager()->
+ contents_texture_manager_on_main_thread()->
PushTexturePrioritiesToBackings();
}
@@ -945,23 +995,17 @@ void ThreadProxy::StartCommitOnImplThread(
scheduler_on_impl_thread_->AnticipatedDrawTime());
}
-void ThreadProxy::BeginFrameAbortedByMainThreadOnImplThread(bool did_handle) {
- TRACE_EVENT0("cc", "ThreadProxy::BeginFrameAbortedByMainThreadOnImplThread");
+void ThreadProxy::BeginMainFrameAbortedOnImplThread(bool did_handle) {
+ TRACE_EVENT0("cc", "ThreadProxy::BeginMainFrameAbortedOnImplThread");
DCHECK(IsImplThread());
DCHECK(scheduler_on_impl_thread_);
DCHECK(scheduler_on_impl_thread_->CommitPending());
DCHECK(!layer_tree_host_impl_->pending_tree());
- // If the begin frame data was handled, then scroll and scale set was applied
- // by the main thread, so the active tree needs to be updated as if these sent
- // values were applied and committed.
- if (did_handle) {
- layer_tree_host_impl_->active_tree()
- ->ApplySentScrollAndScaleDeltasFromAbortedCommit();
- layer_tree_host_impl_->active_tree()->ResetContentsTexturesPurged();
+ if (did_handle)
SetInputThrottledUntilCommitOnImplThread(false);
- }
- scheduler_on_impl_thread_->BeginFrameAbortedByMainThread(did_handle);
+ layer_tree_host_impl_->BeginMainFrameAborted(did_handle);
+ scheduler_on_impl_thread_->BeginMainFrameAborted(did_handle);
}
void ThreadProxy::ScheduledActionCommit() {
@@ -976,8 +1020,8 @@ void ThreadProxy::ScheduledActionCommit() {
inside_commit_ = true;
layer_tree_host_impl_->BeginCommit();
- layer_tree_host_->BeginCommitOnImplThread(layer_tree_host_impl_.get());
- layer_tree_host_->FinishCommitOnImplThread(layer_tree_host_impl_.get());
+ layer_tree_host()->BeginCommitOnImplThread(layer_tree_host_impl_.get());
+ layer_tree_host()->FinishCommitOnImplThread(layer_tree_host_impl_.get());
layer_tree_host_impl_->CommitComplete();
inside_commit_ = false;
@@ -987,7 +1031,7 @@ void ThreadProxy::ScheduledActionCommit() {
next_frame_is_newly_committed_frame_on_impl_thread_ = true;
- if (layer_tree_host_->settings().impl_side_painting &&
+ if (layer_tree_host()->settings().impl_side_painting &&
commit_waits_for_activation_) {
// For some layer types in impl-side painting, the commit is held until
// the pending tree is activated. It's also possible that the
@@ -1004,8 +1048,8 @@ void ThreadProxy::ScheduledActionCommit() {
commit_waits_for_activation_ = false;
commit_complete_time_ = base::TimeTicks::HighResNow();
- begin_frame_to_commit_duration_history_.InsertSample(
- commit_complete_time_ - begin_frame_sent_to_main_thread_time_);
+ begin_main_frame_to_commit_duration_history_.InsertSample(
+ commit_complete_time_ - begin_main_frame_sent_time_);
// SetVisible kicks off the next scheduler action, so this must be last.
scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible());
@@ -1096,7 +1140,7 @@ DrawSwapReadbackResult ThreadProxy::DrawSwapReadbackInternal(
if (draw_frame) {
layer_tree_host_impl_->DrawLayers(
&frame,
- scheduler_on_impl_thread_->LastBeginFrameOnImplThreadTime());
+ scheduler_on_impl_thread_->LastBeginImplFrameTime());
result.did_draw = true;
}
layer_tree_host_impl_->DidDrawAllLayers(frame);
@@ -1254,8 +1298,8 @@ base::TimeDelta ThreadProxy::DrawDurationEstimate() {
return historical_estimate + padding;
}
-base::TimeDelta ThreadProxy::BeginFrameToCommitDurationEstimate() {
- return begin_frame_to_commit_duration_history_.Percentile(
+base::TimeDelta ThreadProxy::BeginMainFrameToCommitDurationEstimate() {
+ return begin_main_frame_to_commit_duration_history_.Percentile(
kCommitAndActivationDurationEstimationPercentile);
}
@@ -1264,14 +1308,18 @@ base::TimeDelta ThreadProxy::CommitToActivateDurationEstimate() {
kCommitAndActivationDurationEstimationPercentile);
}
-void ThreadProxy::PostBeginFrameDeadline(const base::Closure& closure,
- base::TimeTicks deadline) {
- base::TimeDelta delta = deadline - base::TimeTicks::Now();
+void ThreadProxy::PostBeginImplFrameDeadline(const base::Closure& closure,
+ base::TimeTicks deadline) {
+ base::TimeDelta delta = deadline - gfx::FrameTime::Now();
if (delta <= base::TimeDelta())
delta = base::TimeDelta();
Proxy::ImplThreadTaskRunner()->PostDelayedTask(FROM_HERE, closure, delta);
}
+void ThreadProxy::DidBeginImplFrameDeadline() {
+ layer_tree_host_impl_->ResetCurrentFrameTimeForNextFrame();
+}
+
void ThreadProxy::ReadyToFinalizeTextureUpdates() {
DCHECK(IsImplThread());
scheduler_on_impl_thread_->FinishCommit();
@@ -1279,25 +1327,25 @@ void ThreadProxy::ReadyToFinalizeTextureUpdates() {
void ThreadProxy::DidCommitAndDrawFrame() {
DCHECK(IsMainThread());
- if (!layer_tree_host_)
+ if (!layer_tree_host())
return;
- layer_tree_host_->DidCommitAndDrawFrame();
+ layer_tree_host()->DidCommitAndDrawFrame();
}
void ThreadProxy::DidCompleteSwapBuffers() {
DCHECK(IsMainThread());
- if (!layer_tree_host_)
+ if (!layer_tree_host())
return;
- layer_tree_host_->DidCompleteSwapBuffers();
+ layer_tree_host()->DidCompleteSwapBuffers();
}
void ThreadProxy::SetAnimationEvents(scoped_ptr<AnimationEventsVector> events,
base::Time wall_clock_time) {
TRACE_EVENT0("cc", "ThreadProxy::SetAnimationEvents");
DCHECK(IsMainThread());
- if (!layer_tree_host_)
+ if (!layer_tree_host())
return;
- layer_tree_host_->SetAnimationEvents(events.Pass(), wall_clock_time);
+ layer_tree_host()->SetAnimationEvents(events.Pass(), wall_clock_time);
}
void ThreadProxy::CreateAndInitializeOutputSurface() {
@@ -1320,7 +1368,7 @@ void ThreadProxy::CreateAndInitializeOutputSurface() {
if (has_initialized_output_surface_on_impl_thread)
return;
- layer_tree_host_->DidLoseOutputSurface();
+ layer_tree_host()->DidLoseOutputSurface();
output_surface_creation_callback_.Reset(base::Bind(
&ThreadProxy::DoCreateAndInitializeOutputSurface,
base::Unretained(this)));
@@ -1339,8 +1387,8 @@ void ThreadProxy::HasInitializedOutputSurfaceOnImplThread(
void ThreadProxy::InitializeImplOnImplThread(CompletionEvent* completion) {
TRACE_EVENT0("cc", "ThreadProxy::InitializeImplOnImplThread");
DCHECK(IsImplThread());
- layer_tree_host_impl_ = layer_tree_host_->CreateLayerTreeHostImpl(this);
- const LayerTreeSettings& settings = layer_tree_host_->settings();
+ layer_tree_host_impl_ = layer_tree_host()->CreateLayerTreeHostImpl(this);
+ const LayerTreeSettings& settings = layer_tree_host()->settings();
SchedulerSettings scheduler_settings;
scheduler_settings.deadline_scheduling_enabled =
settings.deadline_scheduling_enabled;
@@ -1353,7 +1401,8 @@ void ThreadProxy::InitializeImplOnImplThread(CompletionEvent* completion) {
settings.using_synchronous_renderer_compositor;
scheduler_settings.throttle_frame_production =
settings.throttle_frame_production;
- scheduler_on_impl_thread_ = Scheduler::Create(this, scheduler_settings);
+ scheduler_on_impl_thread_ = Scheduler::Create(this, scheduler_settings,
+ layer_tree_host_id_);
scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible());
impl_thread_weak_ptr_ = weak_factory_on_impl_thread_.GetWeakPtr();
@@ -1372,7 +1421,7 @@ void ThreadProxy::InitializeOutputSurfaceOnImplThread(
DCHECK(success);
DCHECK(capabilities);
- layer_tree_host_->DeleteContentsTexturesOnImplThread(
+ layer_tree_host()->DeleteContentsTexturesOnImplThread(
layer_tree_host_impl_->resource_provider());
*success = layer_tree_host_impl_->InitializeRenderer(output_surface.Pass());
@@ -1403,10 +1452,10 @@ void ThreadProxy::FinishGLOnImplThread(CompletionEvent* completion) {
void ThreadProxy::LayerTreeHostClosedOnImplThread(CompletionEvent* completion) {
TRACE_EVENT0("cc", "ThreadProxy::LayerTreeHostClosedOnImplThread");
DCHECK(IsImplThread());
- layer_tree_host_->DeleteContentsTexturesOnImplThread(
+ layer_tree_host()->DeleteContentsTexturesOnImplThread(
layer_tree_host_impl_->resource_provider());
current_resource_update_controller_on_impl_thread_.reset();
- layer_tree_host_impl_->SetNeedsBeginFrame(false);
+ layer_tree_host_impl_->SetNeedsBeginImplFrame(false);
scheduler_on_impl_thread_.reset();
layer_tree_host_impl_.reset();
weak_factory_on_impl_thread_.InvalidateWeakPtrs();
@@ -1417,12 +1466,12 @@ size_t ThreadProxy::MaxPartialTextureUpdates() const {
return ResourceUpdateController::MaxPartialTextureUpdates();
}
-ThreadProxy::BeginFrameAndCommitState::BeginFrameAndCommitState()
+ThreadProxy::BeginMainFrameAndCommitState::BeginMainFrameAndCommitState()
: memory_allocation_limit_bytes(0),
memory_allocation_priority_cutoff(0),
evicted_ui_resources(false) {}
-ThreadProxy::BeginFrameAndCommitState::~BeginFrameAndCommitState() {}
+ThreadProxy::BeginMainFrameAndCommitState::~BeginMainFrameAndCommitState() {}
scoped_ptr<base::Value> ThreadProxy::AsValue() const {
scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
@@ -1502,7 +1551,7 @@ void ThreadProxy::RenewTreePriority() {
DCHECK(IsImplThread());
bool smoothness_takes_priority =
layer_tree_host_impl_->pinch_gesture_active() ||
- layer_tree_host_impl_->CurrentlyScrollingLayer() ||
+ layer_tree_host_impl_->IsCurrentlyScrolling() ||
layer_tree_host_impl_->page_scale_animation_active();
base::TimeTicks now = layer_tree_host_impl_->CurrentPhysicalTimeTicks();
@@ -1597,4 +1646,9 @@ void ThreadProxy::DidActivatePendingTree() {
base::TimeTicks::HighResNow() - commit_complete_time_);
}
+void ThreadProxy::DidManageTiles() {
+ DCHECK(IsImplThread());
+ scheduler_on_impl_thread_->DidManageTiles();
+}
+
} // namespace cc
diff --git a/chromium/cc/trees/thread_proxy.h b/chromium/cc/trees/thread_proxy.h
index 78a59613d39..cf041edbcfd 100644
--- a/chromium/cc/trees/thread_proxy.h
+++ b/chromium/cc/trees/thread_proxy.h
@@ -56,6 +56,7 @@ class ThreadProxy : public Proxy,
virtual void NotifyInputThrottledUntilCommit() OVERRIDE;
virtual void SetDeferCommits(bool defer_commits) OVERRIDE;
virtual bool CommitRequested() const OVERRIDE;
+ virtual bool BeginMainFrameRequested() const OVERRIDE;
virtual void MainThreadHasStoppedFlinging() OVERRIDE;
virtual void Start(scoped_ptr<OutputSurface> first_output_surface) OVERRIDE;
virtual void Stop() OVERRIDE;
@@ -68,11 +69,13 @@ class ThreadProxy : public Proxy,
// LayerTreeHostImplClient implementation
virtual void DidLoseOutputSurfaceOnImplThread() OVERRIDE;
+ virtual void DidSwapBuffersOnImplThread() OVERRIDE {}
virtual void OnSwapBuffersCompleteOnImplThread() OVERRIDE;
- virtual void BeginFrameOnImplThread(const BeginFrameArgs& args) OVERRIDE;
- virtual void DidBeginFrameDeadlineOnImplThread() OVERRIDE;
+ virtual void BeginImplFrame(const BeginFrameArgs& args) OVERRIDE;
virtual void OnCanDrawStateChanged(bool can_draw) OVERRIDE;
virtual void NotifyReadyToActivate() OVERRIDE;
+ // Please call these 2 functions through
+ // LayerTreeHostImpl's SetNeedsRedraw() and SetNeedsRedrawRect().
virtual void SetNeedsRedrawOnImplThread() OVERRIDE;
virtual void SetNeedsRedrawRectOnImplThread(gfx::Rect dirty_rect) OVERRIDE;
virtual void SetNeedsManageTilesOnImplThread() OVERRIDE;
@@ -84,17 +87,17 @@ class ThreadProxy : public Proxy,
virtual bool ReduceContentsTextureMemoryOnImplThread(size_t limit_bytes,
int priority_cutoff)
OVERRIDE;
- virtual void ReduceWastedContentsTextureMemoryOnImplThread() OVERRIDE;
virtual void SendManagedMemoryStats() OVERRIDE;
virtual bool IsInsideDraw() OVERRIDE;
virtual void RenewTreePriority() OVERRIDE;
virtual void RequestScrollbarAnimationOnImplThread(base::TimeDelta delay)
OVERRIDE;
virtual void DidActivatePendingTree() OVERRIDE;
+ virtual void DidManageTiles() OVERRIDE;
// SchedulerClient implementation
- virtual void SetNeedsBeginFrameOnImplThread(bool enable) OVERRIDE;
- virtual void ScheduledActionSendBeginFrameToMainThread() OVERRIDE;
+ virtual void SetNeedsBeginImplFrame(bool enable) OVERRIDE;
+ virtual void ScheduledActionSendBeginMainFrame() OVERRIDE;
virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapIfPossible()
OVERRIDE;
virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapForced() OVERRIDE;
@@ -107,10 +110,11 @@ class ThreadProxy : public Proxy,
virtual void ScheduledActionManageTiles() OVERRIDE;
virtual void DidAnticipatedDrawTimeChange(base::TimeTicks time) OVERRIDE;
virtual base::TimeDelta DrawDurationEstimate() OVERRIDE;
- virtual base::TimeDelta BeginFrameToCommitDurationEstimate() OVERRIDE;
+ virtual base::TimeDelta BeginMainFrameToCommitDurationEstimate() OVERRIDE;
virtual base::TimeDelta CommitToActivateDurationEstimate() OVERRIDE;
- virtual void PostBeginFrameDeadline(const base::Closure& closure,
- base::TimeTicks deadline) OVERRIDE;
+ virtual void PostBeginImplFrameDeadline(const base::Closure& closure,
+ base::TimeTicks deadline) OVERRIDE;
+ virtual void DidBeginImplFrameDeadline() OVERRIDE;
// ResourceUpdateControllerClient implementation
virtual void ReadyToFinalizeTextureUpdates() OVERRIDE;
@@ -119,9 +123,9 @@ class ThreadProxy : public Proxy,
ThreadProxy(LayerTreeHost* layer_tree_host,
scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner);
- struct BeginFrameAndCommitState {
- BeginFrameAndCommitState();
- ~BeginFrameAndCommitState();
+ struct BeginMainFrameAndCommitState {
+ BeginMainFrameAndCommitState();
+ ~BeginMainFrameAndCommitState();
base::TimeTicks monotonic_frame_begin_time;
scoped_ptr<ScrollAndScaleSet> scroll_info;
@@ -131,8 +135,8 @@ class ThreadProxy : public Proxy,
};
// Called on main thread.
- void BeginFrameOnMainThread(
- scoped_ptr<BeginFrameAndCommitState> begin_frame_state);
+ void BeginMainFrame(
+ scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state);
void DidCommitAndDrawFrame();
void DidCompleteSwapBuffers();
void SetAnimationEvents(scoped_ptr<AnimationEventsVector> queue,
@@ -150,13 +154,13 @@ class ThreadProxy : public Proxy,
struct SchedulerStateRequest;
void ForceCommitForReadbackOnImplThread(
- CompletionEvent* begin_frame_sent_completion,
+ CompletionEvent* begin_main_frame_sent_completion,
ReadbackRequest* request);
void StartCommitOnImplThread(
CompletionEvent* completion,
ResourceUpdateQueue* queue,
- scoped_refptr<cc::ContextProvider> offscreen_context_provider);
- void BeginFrameAbortedByMainThreadOnImplThread(bool did_handle);
+ scoped_refptr<ContextProvider> offscreen_context_provider);
+ void BeginMainFrameAbortedOnImplThread(bool did_handle);
void RequestReadbackOnImplThread(ReadbackRequest* request);
void FinishAllRenderingOnImplThread(CompletionEvent* completion);
void InitializeImplOnImplThread(CompletionEvent* completion);
@@ -191,6 +195,10 @@ class ThreadProxy : public Proxy,
void StartScrollbarAnimationOnImplThread();
void MainThreadHasStoppedFlingingOnImplThread();
void SetInputThrottledUntilCommitOnImplThread(bool is_throttled);
+ LayerTreeHost* layer_tree_host();
+ const LayerTreeHost* layer_tree_host() const;
+ PrioritizedResourceManager* contents_texture_manager_on_main_thread();
+ PrioritizedResourceManager* contents_texture_manager_on_impl_thread();
// Accessed on main thread only.
@@ -198,12 +206,17 @@ class ThreadProxy : public Proxy,
bool animate_requested_;
// Set only when SetNeedsCommit is called.
bool commit_requested_;
- // Set by SetNeedsCommit and SetNeedsAnimate.
+ // Set by SetNeedsAnimate, SetNeedsUpdateLayers, and SetNeedsCommit.
bool commit_request_sent_to_impl_thread_;
- // Set by BeginFrameOnMainThread
+ // Set by BeginMainFrame
bool created_offscreen_context_provider_;
base::CancelableClosure output_surface_creation_callback_;
- LayerTreeHost* layer_tree_host_;
+ // Don't use this variable directly, go through layer_tree_host() to ensure it
+ // is only used on the main thread or if the main thread is blocked.
+ LayerTreeHost* layer_tree_host_unsafe_;
+ // Use one of the contents_texture_manager_on functions above instead of using
+ // this variable directly.
+ PrioritizedResourceManager* contents_texture_manager_unsafe_;
RendererCapabilities renderer_capabilities_main_thread_copy_;
bool started_;
bool textures_acquired_;
@@ -219,19 +232,14 @@ class ThreadProxy : public Proxy,
bool commit_waits_for_activation_;
bool inside_commit_;
- base::WeakPtrFactory<ThreadProxy> weak_factory_on_impl_thread_;
-
- base::WeakPtr<ThreadProxy> main_thread_weak_ptr_;
- base::WeakPtrFactory<ThreadProxy> weak_factory_;
-
scoped_ptr<LayerTreeHostImpl> layer_tree_host_impl_;
scoped_ptr<Scheduler> scheduler_on_impl_thread_;
// Set when the main thread is waiting on a
- // ScheduledActionSendBeginFrameToMainThread to be issued.
+ // ScheduledActionSendBeginMainFrame to be issued.
CompletionEvent*
- begin_frame_sent_to_main_thread_completion_event_on_impl_thread_;
+ begin_main_frame_sent_completion_event_on_impl_thread_;
// Set when the main thread is waiting on a readback.
ReadbackRequest* readback_request_on_impl_thread_;
@@ -253,7 +261,7 @@ class ThreadProxy : public Proxy,
bool next_frame_is_newly_committed_frame_on_impl_thread_;
bool throttle_frame_production_;
- bool begin_frame_scheduling_enabled_;
+ bool begin_impl_frame_scheduling_enabled_;
bool using_synchronous_renderer_compositor_;
bool inside_draw_;
@@ -262,21 +270,27 @@ class ThreadProxy : public Proxy,
bool defer_commits_;
bool input_throttled_until_commit_;
- scoped_ptr<BeginFrameAndCommitState> pending_deferred_commit_;
+ scoped_ptr<BeginMainFrameAndCommitState> pending_deferred_commit_;
base::TimeTicks smoothness_takes_priority_expiration_time_;
bool renew_tree_priority_on_impl_thread_pending_;
RollingTimeDeltaHistory draw_duration_history_;
- RollingTimeDeltaHistory begin_frame_to_commit_duration_history_;
+ RollingTimeDeltaHistory begin_main_frame_to_commit_duration_history_;
RollingTimeDeltaHistory commit_to_activate_duration_history_;
// Used for computing samples added to
- // begin_frame_to_commit_draw_duration_history_ and
+ // begin_main_frame_to_commit_duration_history_ and
// activation_duration_history_.
- base::TimeTicks begin_frame_sent_to_main_thread_time_;
+ base::TimeTicks begin_main_frame_sent_time_;
base::TimeTicks commit_complete_time_;
+ base::WeakPtr<ThreadProxy> main_thread_weak_ptr_;
+ base::WeakPtrFactory<ThreadProxy> weak_factory_on_impl_thread_;
+ base::WeakPtrFactory<ThreadProxy> weak_factory_;
+
+ const int layer_tree_host_id_;
+
DISALLOW_COPY_AND_ASSIGN(ThreadProxy);
};
diff --git a/chromium/cc/trees/tree_synchronizer_unittest.cc b/chromium/cc/trees/tree_synchronizer_unittest.cc
index 4e0c89fca5c..827c3662f79 100644
--- a/chromium/cc/trees/tree_synchronizer_unittest.cc
+++ b/chromium/cc/trees/tree_synchronizer_unittest.cc
@@ -552,11 +552,8 @@ TEST_F(TreeSynchronizerTest, SynchronizeAnimations) {
FakeProxy proxy;
DebugScopedSetImplThread impl(&proxy);
FakeRenderingStatsInstrumentation stats_instrumentation;
- scoped_ptr<LayerTreeHostImpl> host_impl =
- LayerTreeHostImpl::Create(settings,
- NULL,
- &proxy,
- &stats_instrumentation);
+ scoped_ptr<LayerTreeHostImpl> host_impl = LayerTreeHostImpl::Create(
+ settings, NULL, &proxy, &stats_instrumentation, NULL, 0);
scoped_refptr<Layer> layer_tree_root = Layer::Create();
host_->SetRootLayer(layer_tree_root);
@@ -587,11 +584,8 @@ TEST_F(TreeSynchronizerTest, SynchronizeScrollParent) {
FakeProxy proxy;
DebugScopedSetImplThread impl(&proxy);
FakeRenderingStatsInstrumentation stats_instrumentation;
- scoped_ptr<LayerTreeHostImpl> host_impl =
- LayerTreeHostImpl::Create(settings,
- NULL,
- &proxy,
- &stats_instrumentation);
+ scoped_ptr<LayerTreeHostImpl> host_impl = LayerTreeHostImpl::Create(
+ settings, NULL, &proxy, &stats_instrumentation, NULL, 0);
scoped_refptr<Layer> layer_tree_root = Layer::Create();
scoped_refptr<Layer> scroll_parent = Layer::Create();
@@ -665,11 +659,8 @@ TEST_F(TreeSynchronizerTest, SynchronizeClipParent) {
FakeProxy proxy;
DebugScopedSetImplThread impl(&proxy);
FakeRenderingStatsInstrumentation stats_instrumentation;
- scoped_ptr<LayerTreeHostImpl> host_impl =
- LayerTreeHostImpl::Create(settings,
- NULL,
- &proxy,
- &stats_instrumentation);
+ scoped_ptr<LayerTreeHostImpl> host_impl = LayerTreeHostImpl::Create(
+ settings, NULL, &proxy, &stats_instrumentation, NULL, 0);
scoped_refptr<Layer> layer_tree_root = Layer::Create();
scoped_refptr<Layer> clip_parent = Layer::Create();